rbfind 1.13 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2e088901eba3d900228dba6ffb052866b3ffcf282622838625bbeb7ebfbf3b9
4
- data.tar.gz: 7651789fed1a8d3963210d8c9efcc131c08840f94e00dcec518c7daae4072fc8
3
+ metadata.gz: 5a6e7b3de72cc2efdb3033593f8ffac176da6dab3395d68594570d08c3992249
4
+ data.tar.gz: 36f03f0b41bd1180429bd527f0fa7f6a8f8e2897c3f99569fbc6250f3e358baf
5
5
  SHA512:
6
- metadata.gz: 170d599e93cd82d128f3ea4541b6d4c92f04d21b79e15cd09a7c1de1f18d5a3bf4862b56bfa2ab2ccfb8229eef6e428135591f59f84b6b59266f129bb2e932be
7
- data.tar.gz: 2f3dba6cca4000d736d77f054962bb0265a22414a3db2fc837d97bd2c68d17cb7e8d1c94f30e22725ead2d974fefec34e4acfc46df893a46c3df541c6ffa03aa
6
+ metadata.gz: b30427e248f24b028eb554b5c5672d96695f7fdec4c87e3ae39343671702c89e02664a78ac6bbc40f101baa348fbebc67c9a5e564f8694d27e9d53b1bc7cd103
7
+ data.tar.gz: 847dbf390ec156f619b06c1820e5df1ca4d51f89b8ebc7ae06f7a055d98bd734d74a7ae6d122e5c58d5eaa0ce183afba0a70db1856801d62bd413c49988ad6b4
data/bin/rbfind CHANGED
@@ -5,137 +5,423 @@
5
5
  #
6
6
 
7
7
  require "rbfind"
8
+ require "rbfind/humansiz"
9
+ require "English"
10
+ require 'getoptlong'
8
11
 
9
- PROGRAM = <<EOT
10
- rbfind #{RbFind::VERSION} -- A find tool using Ruby
11
12
 
12
- Author: Bertram Scharpf <software@bertram-scharpf.de>
13
- License: BSD
14
- EOT
13
+ module RbFind
14
+
15
+ class Application
16
+
17
+ PROGRAM = <<~EOT
18
+ rbfind #{RbFind::VERSION} -- A find tool using Ruby
19
+
20
+ Author: Bertram Scharpf <software@bertram-scharpf.de>
21
+ License: BSD
22
+ EOT
23
+
24
+ OPTIONS = [
25
+ # options arg description
26
+ [ %w(--help -h), nil, "print this help"],
27
+ [ %w(--examples -X), nil, "print this help and examples"],
28
+ [ %w(--version -V), nil, "print version information"],
29
+ [ %w(--verbose -v), nil, "standard Ruby error reports"],
30
+ [ %w(--show -o), nil, "just show Ruby block built from options"],
31
+ [ %w(--bw -w), nil, "black and white on -p or default output"],
32
+ [ %w(--colored -c), nil, "force color on -p or default output"],
33
+ [ %w(--depth -d), nil, "yield directory after its contents"],
34
+ [ %w(--maxdepth -m), :num, "maxium step depth"],
35
+ [ %w(--follow -y), nil, "follow symbolic links"],
36
+ [ %w(--nosort -S), nil, "unsorted"],
37
+ [ %w(--sort-by -s), :str, "sort expression ('n' is name)"],
38
+ [ %w(--reverse -R), :str, "reverse sort"],
39
+ [ %w(--require -r), :rb, "require library"],
40
+ [ %w(--fileutils -U), nil, "include FileUtils module"],
41
+ [ %w(--puts-path -p), nil, "do 'puts path/cpath' on true block"],
42
+ [ %w(--ls-l -P), nil, "do 'ls -l' style output on true block"],
43
+ [ %w(--wider -+), nil, "widen fields in long output format (--ls-l)"],
44
+ [ %w(--slash -/), nil, "append a slash to directory names"],
45
+ [ %w(--lines -l), :blk, "surround block by 'lines { |$_,$.| ... }'"],
46
+ [ %w(--reallines -L), :blk, "same as -l but stop at any null character"],
47
+ [ %w(--grep -g), :blk, "grep files (implies -pL)"],
48
+ [ %w(--igrep -G), :blk, "case insensitive grep"],
49
+ [ %w(--binary -b), nil, "grep even binary files"],
50
+ [ %w(--no-vcs -C), nil, "prune version control dirs (CVS/.svn/.git)"],
51
+ [ %w(--no-swap -W), nil, "ignore Vim swapfiles"],
52
+ [ %w(--skip -k), :lst, "filenames to skip"],
53
+ [ %w(--demand -D), :lst, "skip all filenames but these"],
54
+ [ %w(--ext -e), :lst, "skip all filename extensions but these"],
55
+ [ %w(--visible -I), nil, "skip all hidden (starting with .dot)"],
56
+ [ %w(--nodirs -N), nil, "skip directories"],
57
+ [ %w(--begin -B), :blk, "eval block before begin"],
58
+ [ %w(--end -E), :blk, "eval block after end"],
59
+ [ %w(--file -f), :blk, "read block expression from file"],
60
+ [ %w(--encoding -K), :str, "encoding extern[:intern] (same as ruby -E)"],
61
+ ]
62
+
63
+ def initialize
64
+ @params = {}
65
+ envopts = ENV[ "RBFIND_OPTIONS"]
66
+ $*.unshift *envopts.split if envopts
67
+ opts = GetoptLong.new *OPTIONS.map { |(long,short),arg,|
68
+ [long,short,(arg ? GetoptLong::REQUIRED_ARGUMENT : GetoptLong::NO_ARGUMENT)]
69
+ }
70
+ opts.ordering = GetoptLong::PERMUTE
71
+ opts.quiet = true
72
+ opts.each do |opt,arg|
73
+ case opt
74
+ when '--help' then usage ; exit
75
+ when '--version' then puts PROGRAM ; exit
76
+ when '--examples' then usage_examples ; exit
77
+ when '--verbose' then @verbose = true
78
+ when '--show' then @show = true
79
+ when '--bw' then @color = false
80
+ when '--colored' then @color = true
81
+ when '--depth' then @params[ :depth_first] = true
82
+ when '--maxdepth' then @params[ :max_depth] = arg.to_i
83
+ when '--follow' then @params[ :follow] = true
84
+ when '--nosort' then @params[ :sort] = false
85
+ when '--sort-by' then @params[ :sort] = instance_eval "proc { |n| #{arg} }"
86
+ when '--reverse' then @params[ :reverse] = true
87
+ when '--require' then require arg
88
+ when '--fileutils' then require "fileutils" ; include FileUtils
89
+ when '--puts-path' then @puts = true
90
+ when '--ls-l' then @puts = true ; @wd = 6
91
+ when '--wider' then @wd = @wd ? @wd.succ : 4
92
+ when '--slash' then @slash = true
93
+ when '--lines' then @lines = :plain ; @block = arg
94
+ when '--reallines' then @lines = :plain ; @real = true ; @block = arg
95
+ when '--grep' then @lines = :grep ; @block = arg
96
+ when '--igrep' then @lines = :grep ; @icase = true ; @block = arg
97
+ when '--binary' then @binary = true
98
+ when '--no-vcs' then @vcs = true
99
+ when '--no-swap' then @vim = true
100
+ when '--skip' then @skip = arg
101
+ when '--demand' then @demand = arg
102
+ when '--ext' then @ext = arg
103
+ when '--visible' then @visible = true
104
+ when '--nodirs' then @nodirs = true
105
+ when '--begin' then @blkbegin = arg
106
+ when '--end' then @blkend = arg
107
+ when '--file' then @block = File.read arg
108
+ when '--encoding' then e, i = arg.split ":" ; set_encoding e, i
109
+ end
110
+ end
111
+ @args = $*.dup
112
+ if @args.empty? and not $stdin.tty? then
113
+ $stdin.each_line { |l|
114
+ l.chomp!
115
+ @args.push l
116
+ }
117
+ end
118
+ build_block
119
+ rescue GetoptLong::InvalidOption
120
+ $stderr.puts $!
121
+ $stderr.puts
122
+ usage
123
+ exit 9
124
+ rescue
125
+ $stderr.puts $!
126
+ exit 8
127
+ end
15
128
 
129
+ def build_block
130
+ co = color_on $stdout
131
+ opath = co ? "cpath" : "path"
132
+ @slash and opath << "!"
133
+ case @lines
134
+ when :plain then
135
+ @puts and @block = "( #@block ) and colsep #{opath}, num, line"
136
+ @real and @block = "break if ~/\0/o ; #@block"
137
+ @block = "lines { |line,num| #@block }"
138
+
139
+ when :grep then
140
+ re = Regexp.new @block, @icase && Regexp::IGNORECASE
141
+ @block = "grep #{re.inspect}"
142
+ @block << ", true" if co
143
+ @block << " ; $stdout.flush" unless $stdout.tty?
144
+ @binary or @block = "not binary? and (#@block)"
16
145
 
17
- require 'getoptlong'
146
+ else
147
+ @block ||= if @args.last and not (File.exists? @args.last) then
148
+ @args.pop.dup
149
+ else
150
+ @puts ||= true
151
+ "true"
152
+ end
153
+ if @puts then
154
+ @block = "( #@block ) and "
155
+ @block << if @wd then
156
+ "spcsep stype+modes, user.w#@wd, group.w#@wd, size.w#@wd, " +
157
+ "mtime.lsish, #{opath} + #{co ? 'carrow' : 'arrow'}.to_s"
158
+ else
159
+ "puts #{opath}"
160
+ end
161
+ end
18
162
 
19
- OPTIONS = [
20
- # options arg description
21
- [ %w(--help -h), nil, "print this help"],
22
- [ %w(--examples -X), nil, "print this help and examples"],
23
- [ %w(--version -V), nil, "print version information"],
24
- [ %w(--verbose -v), nil, "standard Ruby error reports"],
25
- [ %w(--show -o), nil, "just show Ruby block built from options"],
26
- [ %w(--bw -w), nil, "black and white on -p or default output"],
27
- [ %w(--colored -c), nil, "force color on -p or default output"],
28
- [ %w(--depth -d), nil, "yield directory after its contents"],
29
- [ %w(--maxdepth -m), :num, "maxium step depth"],
30
- [ %w(--follow -y), nil, "follow symbolic links"],
31
- [ %w(--sort -s), :str, "=reverse/desc/-1,unsorted; default is sorted"],
32
- [ %w(--sort-by -S), :str, "sort expression ('name' is name)"],
33
- [ %w(--require -r), :rb, "require library"],
34
- [ %w(--fileutils -U), nil, "include FileUtils module"],
35
- [ %w(--puts-path -p), nil, "do 'puts path/cpath' on true block"],
36
- [ %w(--ls-l -P), nil, "do 'ls -l' style output on true block"],
37
- [ %w(--wider -+), nil, "widen fields in long output format (--ls-l)"],
38
- [ %w(--slash -/), nil, "append a slash to directory names"],
39
- [ %w(--lines -l), :blk, "surround block by 'lines { |$_,$.| ... }'"],
40
- [ %w(--reallines -L), :blk, "same as -l but stop at any null character"],
41
- [ %w(--grep -g), :blk, "grep files (implies -pL)"],
42
- [ %w(--igrep -G), :blk, "case insensitive grep"],
43
- [ %w(--binary -b), nil, "grep even binary files"],
44
- [ %w(--no-vcs -C), nil, "prune version control dirs (CVS/.svn/.git)"],
45
- [ %w(--no-swap -W), nil, "ignore Vim swapfiles"],
46
- [ %w(--skip -k), :lst, "filenames to skip"],
47
- [ %w(--demand -D), :lst, "skip all filenames but these"],
48
- [ %w(--ext -e), :lst, "skip all filename extensions but these"],
49
- [ %w(--visible -I), nil, "skip all hidden (starting with .dot)"],
50
- [ %w(--nodirs -N), nil, "skip directories"],
51
- [ %w(--begin -B), :blk, "eval block before begin"],
52
- [ %w(--end -E), :blk, "eval block after end"],
53
- [ %w(--file -f), :blk, "read block expression from file"],
54
- [ %w(--encoding -K), :str, "encoding extern[:intern] (same as ruby -E)"],
55
- ]
56
-
57
- def usage
58
- puts <<EOT
59
- Usage:
60
-
61
- rbfind [options] path... 'block'
62
-
63
- EOT
64
- OPTIONS.each { |(long,short),arg,desc|
65
- puts " %-12s %2s %-5s %s" % [long,short,arg.to_s.upcase,desc]
66
- }
67
- puts <<'EOT'
68
-
69
- "--" stops option processing.
70
-
71
- The last argument is a block that will be executed on every found
72
- file object. It may be omitted; then "puts path" is assumed or "cpath"
73
- in case the output is a terminal.
74
-
75
- Default sort order is alphabetical.
76
-
77
- EOT
78
- end
163
+ end
79
164
 
80
- def usage_examples
81
- usage
82
- puts <<'EOT'
83
- Examples:
84
- $ rbfind -p 'file and age < 5.m'
85
- $ rbfind -p 'file and age > 1.d'
86
- $ rbfind -p '(90.d .. 183.d) === age'
87
-
88
- $ rbfind -Cg require
89
- $ rbfind -Cp
90
- $ rbfind 'filesize < 100.kB and grep /require/'
91
- $ rbfind -g 'define\s*ALLOC_N'
92
- $ rbfind myproject -e rb -l '~/require/ and puts $_'
93
-
94
- $ rbfind -pe '.rb c h'
95
- $ rbfind /usr/include -e .h -g EACCES
96
- $ rbfind -d -m3 -- /mnt/data
97
- $ rbfind 'filesize > 10.MiB and colsep size.to_hib, path'
98
-
99
- $ rbfind -S "name =~ /^\.*/ ; $'.downcase"
100
- $ rbfind -B '$s=0' -E 'puts $s.to_h' 'filesize {|s|$s+=s}'
101
- $ rbfind 'puts path if ext == ".rb"'
102
- $ rbfind -p 'ext == ".rb"'
103
- $ rbfind /usr/include -p -D '\.h$' -l '~/EACCES/'
104
- $ rbfind /usr/include -pD 'pg|pq|postgres' dir
105
- $ rbfind 'no_svn ; puts path'
106
- $ rbfind 'prune if name == ".svn" ; puts path'
107
- $ rbfind -p 'prune if name == ".svn"'
108
- $ rbfind myproject 'name[/\.rb$/] and lines { |l,i| l=~/require/ and puts l }'
109
- # rbfind /etc 'lines { |l,| l["192.168."] and (puts path ; break) }'
110
- $ rbfind /etc 'readable? or raise "Access denied: #{path}" ;
111
- > lines { |l,| l["192.168."] and (puts path ; break) }'
112
-
113
- $ rbfind 'col_sep stype+modes, size.w10, path'
114
- $ rbfind 'tab_sep stype+modes, size.w10, path'
115
- $ rbfind 'spc_sep stype+modes, size.to_h, user, group, mtime.lsish, path'
116
- $ rbfind 'spacesep stype+modes, size.to_h, user, group, mtime.lsish, path'
117
- $ rbfind 'spacesep stype+modes, size.to_h, user, group, mtime!, path'
118
- $ rbfind 'spacesep stype+modes, size.to_h, user, group, mtime.i, path'
119
- $ rbfind 'spacesep mtime.u, path'
120
- $ rbfind 'spacesep modes, user.w8, group.w8, size.w8, cpath + carrow.to_s'
121
-
122
- $ rbfind 'spacesep digest_md5, size.w8, path'
123
- $ rbfind 'spacesep digest_sha256, size.w8, path'
124
-
125
- $ rbfind 'rename name.downcase'
126
- $ rbfind 'ext == ".tgz" and rename without_ext+".tar.gz"'
127
-
128
- See the RbFind class documentation or the "rbfind.rb" source file for more
129
- sophisticated examples and for a full list of file examination methods.
130
-
131
- Valid units are 1.s, 1.m, 1.h, 1.d, 1.w for time values and
132
- 1.kB == 1000, 1.kiB == 1024, 1.MB, 1.MiB for file sizes.
133
- EOT
134
- end
165
+ osic = File::ALT_SEPARATOR&&Regexp::IGNORECASE
166
+ if @skip then
167
+ re = Regexp.new @skip, osic
168
+ @block.insert 0, "done if name =~ #{re.inspect} ; "
169
+ end
135
170
 
171
+ if @demand then
172
+ re = Regexp.new @demand, osic
173
+ @block.insert 0, "done unless name =~ #{re.inspect} ; "
174
+ end
136
175
 
137
- require "humansiz"
138
- require "English"
176
+ if @ext then
177
+ re = Regexp.new '\A\.(' +
178
+ @ext.split(/ +|,/).map { |e| e[ /\A\.?(.*)\z/, 1] }.join('|') +
179
+ ')\z', osic
180
+ @block.insert 0, "ext =~ #{re.inspect} or done ; "
181
+ end
182
+
183
+ @visible and @block.insert 0, "visible? or done ; "
184
+
185
+ @nodirs and @block.insert 0, "done if dir? ; "
186
+
187
+ @vcs and @block.insert 0, "no_vcs ; "
188
+ @vim and @block.insert 0, "vimswap? and done ; "
189
+
190
+ @params[ :error] = proc do
191
+ case $!
192
+ when Errno::EPIPE then raise
193
+ when NameError, TypeError then raise
194
+ when ArgumentError then raise
195
+ else show_error $!
196
+ end
197
+ end
198
+ end
199
+
200
+ def run
201
+ if @show then
202
+ show
203
+ else
204
+ execute
205
+ end
206
+ end
207
+
208
+ private
209
+
210
+ def usage
211
+ puts <<~EOT
212
+ Usage:
213
+
214
+ rbfind [options] path... 'block'
215
+
216
+ EOT
217
+ OPTIONS.each { |(long,short),arg,desc|
218
+ puts " %-12s %2s %-5s %s" % [long,short,arg.to_s.upcase,desc]
219
+ }
220
+ puts <<~'EOT'
221
+
222
+ "--" stops option processing.
223
+
224
+ The last argument is a block that will be executed on every found
225
+ file object. It may be omitted; then "puts path" is assumed or "cpath"
226
+ in case the output is a terminal.
227
+
228
+ Default sort order is alphabetical.
229
+ EOT
230
+ end
231
+
232
+ def usage_examples
233
+ usage
234
+ puts <<~'EOT'
235
+ Examples:
236
+ $ rbfind -p 'file and age < 5.m'
237
+ $ rbfind -p 'file and age > 1.d'
238
+ $ rbfind -p '(90.d .. 183.d) === age'
239
+
240
+ $ rbfind -Cg require
241
+ $ rbfind -Cp
242
+ $ rbfind 'filesize < 100.kB and grep /require/'
243
+ $ rbfind -g 'define\s*ALLOC_N'
244
+ $ rbfind myproject -e rb -l '~/require/ and puts $_'
245
+
246
+ $ rbfind -pe '.rb c h'
247
+ $ rbfind /usr/include -e .h -g EACCES
248
+ $ rbfind -d -m3 -- /mnt/data
249
+ $ rbfind 'filesize > 10.MiB and colsep size.to_hib, path'
250
+
251
+ $ rbfind -S "name =~ /^\.*/ ; $'.downcase"
252
+ $ rbfind -B '$s=0' -E 'puts $s.to_h' 'filesize {|s|$s+=s}'
253
+ $ rbfind 'puts path if ext == ".rb"'
254
+ $ rbfind -p 'ext == ".rb"'
255
+ $ rbfind /usr/include -p -D '\.h$' -l '~/EACCES/'
256
+ $ rbfind /usr/include -pD 'pg|pq|postgres' dir
257
+ $ rbfind 'no_svn ; puts path'
258
+ $ rbfind 'prune if name == ".svn" ; puts path'
259
+ $ rbfind -p 'prune if name == ".svn"'
260
+ $ rbfind myproject 'name[/\.rb$/] and lines { |l,i| l=~/require/ and puts l }'
261
+ # rbfind /etc 'lines { |l,| l["192.168."] and (puts path ; break) }'
262
+ $ rbfind /etc 'readable? or raise "Access denied: #{path}" ;
263
+ > lines { |l,| l["192.168."] and (puts path ; break) }'
264
+
265
+ $ rbfind 'col_sep stype+modes, size.w10, path'
266
+ $ rbfind 'tab_sep stype+modes, size.w10, path'
267
+ $ rbfind 'spc_sep stype+modes, size.to_h, user, group, mtime.lsish, path'
268
+ $ rbfind 'p stype+modes, size.to_h, user, group, mtime.lsish, path'
269
+ $ rbfind 'p stype+modes, size.to_h, user, group, mtime!, path'
270
+ $ rbfind 'p stype+modes, size.to_h, user, group, mtime.i, path'
271
+ $ rbfind 'p mtime.u, path'
272
+ $ rbfind 'p modes, user.w8, group.w8, size.w8, cpath + carrow.to_s'
273
+
274
+ $ rbfind 'p digest_md5, size.w8, path'
275
+ $ rbfind 'p digest_sha256, size.w8, path'
276
+
277
+ $ rbfind 'rename name.downcase'
278
+ $ rbfind 'ext == ".tgz" and rename without_ext+".tar.gz"'
279
+
280
+ See the RbFind documentation or the "rbfind.rb" source file for more
281
+ sophisticated examples and for a full list of file examination methods.
282
+
283
+ Valid units are 1.s, 1.m, 1.h, 1.d, 1.w for time values and
284
+ 1.kB == 1000, 1.kiB == 1024, 1.MB, 1.MiB for file sizes.
285
+ EOT
286
+ end
287
+
288
+ def set_encoding extern, intern = nil
289
+ Encoding.default_external = extern if extern and not extern.empty?
290
+ Encoding.default_internal = intern if intern and not intern.empty?
291
+ [ $stdin, $stdout, $stderr].each do |io|
292
+ io.set_encoding extern, intern
293
+ end
294
+ end
295
+
296
+ def color_on stream
297
+ @color.nil? ? !File::ALT_SEPARATOR && stream.tty? : @color
298
+ end
299
+
300
+
301
+ def show_error e
302
+ co = color_on $stderr
303
+ $stderr.puts co ? "\e[31m#{e.class}: \e[1m#{e}\e[m" : "#{e.class}: #{e}"
304
+ end
305
+
306
+ def error_handle
307
+ if @verbose then
308
+ yield
309
+ else
310
+ begin
311
+ yield
312
+ rescue ArgumentError
313
+ show_error $!
314
+ if $!.message[ "invalid byte sequence"] then
315
+ $stderr.puts <<~EOT
316
+ Hint: Try to give a different default encoding by explicitly setting one or
317
+ by changing the locale.
318
+
319
+ $ rbfind -K ascii-8bit ...
320
+ $ LC_ALL="C" rbfind ...
321
+
322
+ Alternatively, you may prefer to scrub the invalid encodings yourself.
323
+
324
+ $ rbfind -P 'name.scrub =~ /Fu.ball/'
325
+
326
+ EOT
327
+ end
328
+ exit 1
329
+ rescue
330
+ show_error $!
331
+ exit 1
332
+ rescue NoMemoryError, ScriptError, SignalException
333
+ show_error $!
334
+ exit 2
335
+ end
336
+ end
337
+ end
338
+
339
+ def execute
340
+ error_handle do
341
+ eval @blkbegin if @blkbegin
342
+ b = @block
343
+ Walk.run *@args, **@params do instance_eval b end
344
+ eval @blkend if @blkend
345
+ end
346
+ end
347
+
348
+ def show
349
+ puts "arguments:"
350
+ @args.each { |a| puts_val a }.any? or puts_val "(none)"
351
+ puts "parameters:"
352
+ @params.each { |k,v| puts_val k, "=", v }.any? or puts_val "(none)"
353
+ puts "block:"
354
+ @block.each_line { |l| puts_val l }
355
+ end
356
+
357
+ INDENT = " "*2
358
+
359
+ def puts_val *args
360
+ l = [ INDENT, *args].join ""
361
+ puts l
362
+ end
363
+
364
+ end
365
+
366
+
367
+ class Entry
368
+
369
+ # Alias the question marks away from all method names because
370
+ # they're a nuisance on the command line.
371
+ alias hidden hidden?
372
+ alias visible visible?
373
+ alias broken_link broken_link?
374
+ alias dir dir?
375
+ alias binary binary?
376
+ alias bin bin?
377
+ alias vimswap vimswap?
378
+
379
+ def blockdev ; blockdev? ; end
380
+ def chardev ; chardev? ; end
381
+ def directory ; directory? ; end
382
+ def executable ; executable? ; end
383
+ def executable_real ; executable_real? ; end
384
+ def file ; file? ; end
385
+ def grpowned ; grpowned? ; end
386
+ def owned ; owned? ; end
387
+ def pipe ; pipe? ; end
388
+ def readable ; readable? ; end
389
+ def readable_real ; readable_real? ; end
390
+ def setgid ; setgid? ; end
391
+ def setuid ; setuid? ; end
392
+ def socket ; socket? ; end
393
+ def sticky ; sticky? ; end
394
+ def symlink ; symlink? ; end
395
+ def writable ; writable? ; end
396
+ def writable_real ; writable_real? ; end
397
+ def zero ; zero? ; end
398
+
399
+ # convenient digest and time format methods
400
+ alias method_missing_orig method_missing
401
+ def method_missing sym, *args, &block
402
+ case sym.to_s
403
+ when /\Adigest_(.*)/, /\A([a-z]+[0-9]+)\z/ then
404
+ m = $1
405
+ d = begin
406
+ Digest.const_get m.upcase
407
+ rescue NameError
408
+ if m =~ /sha\d\d\d/ then m = "sha2" end
409
+ require "digest/#{m}" and retry
410
+ raise
411
+ end
412
+ e = d.new
413
+ read 0x1000_0000 do |b| e.update b end
414
+ e.hexdigest
415
+ when /\A([amc]time)!\z/ then
416
+ (send $1).strftime "%Y-%m-%d %H:%M:%S %z"
417
+ else
418
+ method_missing_orig sym, *args, &block
419
+ end
420
+ end
421
+
422
+ end
423
+
424
+ end
139
425
 
140
426
 
141
427
  class Time
@@ -176,9 +462,6 @@ class String
176
462
  else super
177
463
  end
178
464
  end
179
- def | width
180
- ljust width
181
- end
182
465
  # conventient date/time construction
183
466
  def time
184
467
  Time.parse self
@@ -201,298 +484,12 @@ class NilClass
201
484
  end
202
485
  end
203
486
 
204
-
205
- def set_encoding extern, intern = nil
206
- Encoding.default_external = extern if extern and not extern.empty?
207
- Encoding.default_internal = intern if intern and not intern.empty?
208
- [ $stdin, $stdout, $stderr].each do |io|
209
- io.set_encoding extern, intern
487
+ class Proc
488
+ def to_s
489
+ "#<%s:0x%08x>" % [ self.class, object_id]
210
490
  end
211
491
  end
212
492
 
213
493
 
214
- class RbFindApp < RbFind
215
-
216
- # Alias the question marks away from all method names because
217
- # they're a nuisance on the command line.
218
- alias hidden hidden?
219
- alias visible visible?
220
- alias broken_link broken_link?
221
- alias dir dir?
222
- alias binary binary?
223
- alias bin bin?
224
- alias vimswap vimswap?
225
-
226
- def blockdev ; blockdev? ; end
227
- def chardev ; chardev? ; end
228
- def directory ; directory? ; end
229
- def executable ; executable? ; end
230
- def executable_real ; executable_real? ; end
231
- def file ; file? ; end
232
- def grpowned ; grpowned? ; end
233
- def owned ; owned? ; end
234
- def pipe ; pipe? ; end
235
- def readable ; readable? ; end
236
- def readable_real ; readable_real? ; end
237
- def setgid ; setgid? ; end
238
- def setuid ; setuid? ; end
239
- def socket ; socket? ; end
240
- def sticky ; sticky? ; end
241
- def symlink ; symlink? ; end
242
- def writable ; writable? ; end
243
- def writable_real ; writable_real? ; end
244
- def zero ; zero? ; end
245
-
246
- # convenient digest and time format methods
247
- def method_missing sym, *args, &block
248
- case sym.to_s
249
- when /\Adigest_(.*)/, /\A([a-z]+[0-9]+)\z/ then
250
- m = $1
251
- d = begin
252
- Digest.const_get m.upcase
253
- rescue NameError
254
- if m =~ /sha\d\d\d/ then m = "sha2" end
255
- require "digest/#{m}" and retry
256
- raise
257
- end
258
- e = d.new
259
- read 0x1000_0000 do |b| e.update b end
260
- e.hexdigest
261
- when /\A([amc]time)!\z/ then
262
- (send $1).strftime "%Y-%m-%d %H:%M:%S %z"
263
- else
264
- super
265
- end
266
- end
267
-
268
- def hide_instance_eval
269
- instance_eval yield
270
- end
271
-
272
- end
273
-
274
-
275
- @params = {}
276
-
277
- envopts = ENV[ "RBFIND_OPTIONS"]
278
- $*.unshift *envopts.split if envopts
279
- opts = GetoptLong.new *OPTIONS.map { |(long,short),arg,|
280
- [long,short,(arg ? GetoptLong::REQUIRED_ARGUMENT : GetoptLong::NO_ARGUMENT)]
281
- }
282
- opts.ordering = GetoptLong::PERMUTE
283
- opts.quiet = true
284
- begin
285
- opts.each do |opt,arg|
286
- case opt
287
- when '--help' then usage ; exit
288
- when '--version' then puts PROGRAM ; exit
289
- when '--examples' then usage_examples ; exit
290
- when '--verbose' then @verbose = true
291
- when '--show' then @show = true
292
- when '--bw' then @color = false
293
- when '--colored' then @color = true
294
- when '--depth' then @params[ :depth] = true
295
- when '--maxdepth' then @params[ :max_depth] = arg
296
- when '--follow' then @params[ :follow] = true
297
- when '--sort' then @params[ :sort] = arg
298
- when '--sort-by' then
299
- @params[ :sort] = instance_eval "proc { |name| #{arg} }"
300
- when '--require' then require arg
301
- when '--fileutils' then require "fileutils" ; include FileUtils
302
- when '--puts-path' then @puts = true
303
- when '--ls-l' then @puts = true ; @wd = 6
304
- when '--wider' then @wd = @wd ? @wd.succ : 4
305
- when '--slash' then @slash = true
306
- when '--lines' then @lines = :plain ; @block = arg
307
- when '--reallines' then @lines = :plain ; @real = true ; @block = arg
308
- when '--grep' then @lines = :grep ; @block = arg
309
- when '--igrep' then @lines = :grep ; @icase = true ; @block = arg
310
- when '--binary' then @binary = true
311
- when '--no-vcs' then @vcs = true
312
- when '--no-swap' then @vim = true
313
- when '--skip' then @skip = arg
314
- when '--demand' then @demand = arg
315
- when '--ext' then @ext = arg
316
- when '--visible' then @visible = true
317
- when '--nodirs' then @nodirs = true
318
- when '--begin' then @blkbegin = arg
319
- when '--end' then @blkend = arg
320
- when '--file' then @block = File.read arg
321
- when '--encoding' then e, i = arg.split ":" ; set_encoding e, i
322
- end
323
- end
324
- rescue GetoptLong::InvalidOption
325
- $stderr.puts $!
326
- $stderr.puts
327
- usage
328
- exit 9
329
- rescue
330
- $stderr.puts $!
331
- exit 8
332
- end
333
-
334
- def color_on stream
335
- unless @color.nil? then
336
- @color
337
- else
338
- !File::ALT_SEPARATOR && stream.tty?
339
- end
340
- end
341
-
342
- if color_on $stderr then
343
- def show_error e
344
- $stderr.puts "\e[31m#{e.class}: \e[1m#{e}\e[m"
345
- end
346
- else
347
- def show_error e
348
- $stderr.puts "#{e.class}: #{e}"
349
- end
350
- end
351
-
352
- def error_handle
353
- if @verbose then
354
- yield
355
- else
356
- begin
357
- yield
358
- rescue ArgumentError
359
- show_error $!
360
- if $!.message[ "invalid byte sequence"] then
361
- $stderr.puts <<-EOT
362
- Hint: Try to give a different default encoding by explicitly setting one or
363
- by changing the locale.
364
-
365
- $ rbfind -K ascii-8bit ...
366
- $ LC_ALL="C" rbfind ...
367
-
368
- Alternatively, you may prefer to scrub the invalid encodings yourself.
369
-
370
- $ rbfind -P 'name.scrub =~ /Fu.ball/'
371
-
372
- EOT
373
- end
374
- exit 1
375
- rescue
376
- show_error $!
377
- exit 1
378
- rescue NoMemoryError, ScriptError, SignalException
379
- show_error $!
380
- exit 2
381
- end
382
- end
383
- end
384
-
385
-
386
- error_handle do
387
-
388
- co = color_on $stdout
389
- opath = co ? "cpath" : "path"
390
- @slash and opath << "!"
391
- case @lines
392
- when :plain then
393
- @puts and @block = "( #@block ) and colsep #{opath}, num, line"
394
- @real and @block = "break if ~/\0/o ; #@block"
395
- @block = "lines { |line,num| #@block }"
396
-
397
- when :grep then
398
- RE = Regexp.new @block, @icase && Regexp::IGNORECASE
399
- @block = "grep RE"
400
- @block << ", true" if co
401
- @block << " ; $stdout.flush" unless $stdout.tty?
402
- @binary or @block = "not binary? and (#@block)"
403
-
404
- else
405
- @block ||= if $*.last and not (File.exists? $*.last) then
406
- $*.pop.dup
407
- else
408
- @puts ||= true
409
- "true"
410
- end
411
- if @puts then
412
- @block = "( #@block ) and "
413
- @block << if @wd then
414
- "spcsep stype+modes, user|#@wd, group|#@wd, size.w#@wd, " +
415
- "mtime.lsish, #{opath} + #{co ? 'carrow' : 'arrow'}.to_s"
416
- else
417
- "puts #{opath}"
418
- end
419
- end
420
-
421
- end
422
-
423
- if @skip then
424
- RE_SKIP = Regexp.new @skip, File::ALT_SEPARATOR&&Regexp::IGNORECASE
425
- @block.insert 0, "next if name =~ RE_SKIP ; "
426
- end
427
-
428
- if @demand then
429
- RE_DEMAND = Regexp.new @demand, File::ALT_SEPARATOR&&Regexp::IGNORECASE
430
- @block.insert 0, "next unless name =~ RE_DEMAND ; "
431
- end
432
-
433
- if @ext then
434
- RE_EXT = Regexp.new '\A\.(' +
435
- @ext.split(/ +|,/).map { |e| e[ /\A\.?(.*)\z/, 1] }.join('|') + ')\z',
436
- File::ALT_SEPARATOR&&Regexp::IGNORECASE
437
- @block.insert 0, "ext =~ RE_EXT or next ; "
438
- end
439
-
440
- @visible and @block.insert 0, "visible? or prune ; "
441
-
442
- @nodirs and @block.insert 0, "next if dir? ; "
443
-
444
- @vcs and @block.insert 0, "no_vcs ; "
445
- @vim and @block.insert 0, "vimswap? and next ; "
446
-
447
- args = $*.dup
448
- if args.empty? and not $stdin.tty? then
449
- $stdin.each_line { |l|
450
- l.chomp!
451
- args.push l
452
- }
453
- end
454
-
455
- if @show then
456
- class Proc
457
- def to_s
458
- "#<%s:0x%08x>" % [ self.class, object_id]
459
- end
460
- end
461
- INDENT = " "*2
462
- def puts_val *args
463
- l = [ INDENT, *args].join ""
464
- puts l
465
- end
466
- puts "arguments:"
467
- args.each { |a| puts_val a }.any? or puts_val "(none)"
468
- puts "parameters:"
469
- @params.each { |k,v| puts_val k, "=", v }.any? or puts_val "(none)"
470
- puts "block:"
471
- self.class.constants.grep( /^RE(_[A-Z]+)?$/).each { |re|
472
- v = self.class.const_get re
473
- puts_val re, "=", v
474
- }
475
- puts_val @block
476
- exit
477
- end
478
-
479
- @params[ :error] = proc do
480
- case $!
481
- when Errno::EPIPE then raise
482
- when NameError, TypeError then raise
483
- when ArgumentError then raise
484
- else show_error $!
485
- end
486
- end
487
-
488
- @block = <<-EOT
489
- handle_error do
490
- #@block
491
- end
492
- EOT
493
-
494
- eval @blkbegin if @blkbegin
495
- RbFindApp.open args, @params do |f| f.hide_instance_eval { @block } end
496
- eval @blkend if @blkend
497
- end
494
+ RbFind::Application.new.run
498
495