rak-eugeneching 1.5

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.
data/lib/rak.rb ADDED
@@ -0,0 +1,4 @@
1
+
2
+ class Rak
3
+ VERSION = "1.4"
4
+ end
data/spec/help_spec.rb ADDED
@@ -0,0 +1,56 @@
1
+ require "spec_helper"
2
+
3
+ def extract_options_from_help_message(msg)
4
+ msg.scan(/\B--?(?:\[no\]|no)?([a-zA-Z0-9\-]+)/).flatten.sort.uniq
5
+ end
6
+
7
+ describe "Rak", "help and errors" do
8
+ it "--version prints version information" do
9
+ rak("--version").should == <<-END
10
+ rak #{Rak::VERSION}
11
+
12
+ Copyright 2008-#{Time.now.year} Daniel Lucraft, all rights reserved.
13
+ Based on the perl tool 'ack' by Andy Lester.
14
+
15
+ This program is free software; you can redistribute it and/or modify it
16
+ under the same terms as Ruby.
17
+ END
18
+ end
19
+
20
+ it "prints unknown type errors" do
21
+ rak("Virg --type=pyth").should == <<-END
22
+ rak: Unknown --type "pyth"
23
+ rak: See rak --help types
24
+ END
25
+ end
26
+
27
+ it "--help prints help information" do
28
+ rak("Virg --help").lines[0].should == <<-END
29
+ Usage: rak [OPTION]... PATTERN [FILES]
30
+ END
31
+ end
32
+
33
+ it "--help types prints type information" do
34
+ rak("--help types").lines[2].should == <<-END
35
+ The following is the list of filetypes supported by rak. You can
36
+ END
37
+ end
38
+
39
+ it "no options or patterns prints the usage info" do
40
+ rak.lines[0].should == <<-END
41
+ Usage: rak [OPTION]... PATTERN [FILES]
42
+ END
43
+ end
44
+
45
+ it "prints a nice message for unknown options" do
46
+ rak("foo --asfdasfd 2>/dev/null").should include <<-END
47
+ rak: see rak --help for usage.
48
+ END
49
+ end
50
+
51
+ it "should mention every option it supports in help" do
52
+ expected = extract_options_from_help_message(File.readlines(bin_rak).grep(/GetoptLong/).join) - ['color']
53
+ actual = extract_options_from_help_message(rak()) - ['ruby']
54
+ actual.should == expected
55
+ end
56
+ end
data/spec/rak_spec.rb ADDED
@@ -0,0 +1,615 @@
1
+ #encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe "Rak", "with no options" do
5
+ it "prints all matches from files in the current directory" do
6
+ rak("Cap.ic").should == <<-END
7
+ *foo.rb*
8
+ 3|foo foo foo *Capric*a foo foo foo
9
+ 4|foo *Capsic*um foo foo foo foo foo
10
+ END
11
+ end
12
+
13
+ it "prints all matches correctly" do
14
+ rak("foo", :ansi => '').should == <<-END
15
+ foo.rb
16
+ 3|foo foo foo Caprica foo foo foo
17
+ 4|foo Capsicum foo foo foo foo foo
18
+ 6|foo foo foo foo foo Pikon foo foo
19
+ 8|foo Pikon foo foo foo foo foo foo
20
+ 10|foo foo Six foo foo foo Six foo
21
+ 11|foo foo foo foo Six foo foo foo
22
+ 13|foo foo foo Gemenon foo foo foo
23
+ END
24
+ end
25
+
26
+ it "prints all matches from files in subdirectories" do
27
+ rak("Pikon").should == <<-END
28
+ *dir1/bar.rb*
29
+ 2|bar bar bar bar *Pikon* bar
30
+ 9|bar bar *Pikon* bar bar bar
31
+
32
+ *foo.rb*
33
+ 6|foo foo foo foo foo *Pikon* foo foo
34
+ 8|foo *Pikon* foo foo foo foo foo foo
35
+ END
36
+ end
37
+
38
+ it "prints multiple matches in a line" do
39
+ rak("Six").should == <<-END
40
+ *foo.rb*
41
+ 10|foo foo *Six* foo foo foo *Six* foo
42
+ 11|foo foo foo foo *Six* foo foo foo
43
+ END
44
+ end
45
+
46
+ it "skips VC dirs" do
47
+ rak("Aerelon").should == ""
48
+ end
49
+
50
+ it "does not follow symlinks" do
51
+ rak("Sagitarron").should == ""
52
+ end
53
+
54
+ it "changes defaults when redirected" do
55
+ rak("Six | cat", :test_mode => false).should == <<-END
56
+ foo.rb:10:foo foo Six foo foo foo Six foo
57
+ foo.rb:11:foo foo foo foo Six foo foo foo
58
+ END
59
+ end
60
+
61
+ it "searches shebangs for valid inputs" do
62
+ rak("Aquaria").should == <<-END
63
+ *shebang*
64
+ 3|goo goo goo *Aquaria* goo goo
65
+ END
66
+ end
67
+
68
+ it "recognizes Makefiles and Rakefiles" do
69
+ rak("Canceron").should == <<-END
70
+ *Rakefile*
71
+ 1|rakefile rakefile *Canceron* rakefile
72
+ END
73
+ end
74
+
75
+ it "matches unicode snowmen" do
76
+ rak("☃", :dir => "example2").should == <<-END
77
+ *snowman.txt*
78
+ 2|# *☃*
79
+ END
80
+ end
81
+ end
82
+
83
+ describe "Rak", "with FILE or STDIN inputs" do
84
+ it "should only search in given files or directories" do
85
+ rak("Pikon foo.rb").should == <<-END
86
+ 6|foo foo foo foo foo *Pikon* foo foo
87
+ 8|foo *Pikon* foo foo foo foo foo foo
88
+ END
89
+ rak("Pikon dir1/", :ansi => '').should == <<-END
90
+ dir1/bar.rb
91
+ 2|bar bar bar bar Pikon bar
92
+ 9|bar bar Pikon bar bar bar
93
+ END
94
+ end
95
+
96
+ it "should search in STDIN by default if no files are specified" do
97
+ rak("Aere", :pipe => "cat _darcs/baz.rb").should == <<-END
98
+ 2|baz baz baz *Aere*lon baz baz baz
99
+ END
100
+ end
101
+
102
+ it "only searches STDIN when piped to" do
103
+ rak("Cap", :pipe => "echo asdfCapasdf").should == <<-END
104
+ 1|asdf*Cap*asdf
105
+ END
106
+ end
107
+
108
+ it "should either match on rax x or rak -v x" do
109
+ (rak('"\A.{0,100}\Z" dir1/bar.rb').length + rak('-v "\A.{0,100}\Z" dir1/bar.rb').length).should > 0
110
+ end
111
+ end
112
+
113
+ describe "Rak", "options" do
114
+ it "prints only files with --files" do
115
+ t = <<-END
116
+ Rakefile
117
+ quux.py
118
+ dir1/bar.rb
119
+ foo.rb
120
+ shebang
121
+ END
122
+ rak("-f").lines.sort.should == t.lines.sort
123
+ end
124
+
125
+ it "prints a maximum number of matches if --max-count=x is specified" do
126
+ rak("Cap.ic -m 1").should == <<-END
127
+ *foo.rb*
128
+ 3|foo foo foo *Capric*a foo foo foo
129
+ END
130
+ end
131
+
132
+ it "prints context of all matches if -m and -C are both specified, without further highlighting" do
133
+ rak("Cap.ic -C2 -m 1").should == <<-END
134
+ *foo.rb*
135
+ 1|
136
+ 2|
137
+ 3|foo foo foo *Capric*a foo foo foo
138
+ 4|foo Capsicum foo foo foo foo foo
139
+ 5|
140
+ END
141
+ end
142
+
143
+ it "prints the evaluated output for --output" do
144
+ rak("Cap --output='$&'", :ansi => '').should == <<-END
145
+ Cap
146
+ Cap
147
+ END
148
+ end
149
+
150
+ it "-v -c displays correct counts even with multiple matches per line" do
151
+ rak("-v -c bar").lines.sort.join.should == <<-END
152
+ Rakefile:1
153
+ dir1/bar.rb:7
154
+ foo.rb:13
155
+ quux.py:1
156
+ shebang:3
157
+ END
158
+ end
159
+
160
+ it "-c prints only the number of matches found per file" do
161
+ rak("Pik -c").lines.sort.join.should == <<-END
162
+ dir1/bar.rb:2
163
+ foo.rb:2
164
+ END
165
+ end
166
+
167
+ it "-h suppresses filename and line number printing" do
168
+ rak("Pik -h").should == <<-END
169
+ bar bar bar bar *Pik*on bar
170
+ bar bar *Pik*on bar bar bar
171
+ foo foo foo foo foo *Pik*on foo foo
172
+ foo *Pik*on foo foo foo foo foo foo
173
+ END
174
+ end
175
+
176
+ it "ignores case with -i" do
177
+ rak("six -i").should == <<-END
178
+ *foo.rb*
179
+ 10|foo foo *Six* foo foo foo *Six* foo
180
+ 11|foo foo foo foo *Six* foo foo foo
181
+ END
182
+ end
183
+
184
+ it "inverts the match with -v" do
185
+ t1 = <<-END
186
+ quux.py
187
+ 1|quux quux quux quux Virgon quux quux
188
+ END
189
+ t12 = <<-END
190
+ dir1/bar.rb
191
+ 1|
192
+ 2|bar bar bar bar Pikon bar
193
+ 3|
194
+ 4|
195
+ 5|
196
+ 6|
197
+ 7|
198
+ 8|
199
+ 9|bar bar Pikon bar bar bar
200
+ END
201
+ t2 = <<-END
202
+ foo.rb
203
+ 1|
204
+ 2|
205
+ 5|
206
+ 7|
207
+ 9|
208
+ 12|
209
+ END
210
+ t3 = <<-END
211
+ shebang
212
+ 1|#!/usr/bin/env ruby
213
+ 2|
214
+ 3|goo goo goo Aquaria goo goo
215
+ END
216
+ t4 = <<-END
217
+ Rakefile
218
+ 1|rakefile rakefile Canceron rakefile
219
+ END
220
+ r = rak("foo -v", :ansi => '')
221
+ r.should include t1
222
+ r.should include t12
223
+ r.should include t2
224
+ r.should include t3
225
+ r.should include t4
226
+ r.lines.length.should == 29
227
+ end
228
+
229
+ it "doesn't descend into subdirs with -n" do
230
+ rak("Pikon -n", :ansi => '').should == <<-END
231
+ foo.rb
232
+ 6|foo foo foo foo foo Pikon foo foo
233
+ 8|foo Pikon foo foo foo foo foo foo
234
+ END
235
+ end
236
+
237
+ it "quotes meta-characters with -Q" do
238
+ rak("Cap. -Q").should == ""
239
+ end
240
+
241
+ it "prints only the matching portion with -o" do
242
+ rak("Cap -o", :ansi => '').should == <<-END
243
+ Cap
244
+ Cap
245
+ END
246
+ end
247
+
248
+ it "matches whole words only with -w" do
249
+ rak("'Cap|Hat' -w").should == ""
250
+ end
251
+
252
+ it "prints the file on each line with --nogroup" do
253
+ rak("Cap --nogroup").should == <<-END
254
+ *foo.rb*:3:foo foo foo *Cap*rica foo foo foo
255
+ *foo.rb*:4:foo *Cap*sicum foo foo foo foo foo
256
+ END
257
+ end
258
+
259
+ it "-l means only print filenames with matches" do
260
+ rak("Caprica -l").should == <<-END
261
+ foo.rb
262
+ END
263
+ end
264
+
265
+ it "-L means only print filenames without matches" do
266
+ t = <<-END
267
+ quux.py
268
+ dir1/bar.rb
269
+ shebang
270
+ Rakefile
271
+ END
272
+ rak("Caprica -L", :ansi => '').lines.sort.should == t.lines.sort
273
+ end
274
+
275
+ it "--passthru means print all lines whether matching or not" do
276
+ t1 = <<-END
277
+ quux quux quux quux Virgon quux quux
278
+ END
279
+
280
+ t2 = <<-END
281
+ *foo.rb*
282
+ 3|foo foo foo *Caprica* foo foo foo
283
+ foo Capsicum foo foo foo foo foo
284
+
285
+ foo foo foo foo foo Pikon foo foo
286
+
287
+ foo Pikon foo foo foo foo foo foo
288
+
289
+ foo foo Six foo foo foo Six foo
290
+ foo foo foo foo Six foo foo foo
291
+
292
+ foo foo foo Gemenon foo foo foo
293
+ END
294
+ t3 = <<-END
295
+ #!/usr/bin/env ruby
296
+
297
+ goo goo goo Aquaria goo goo
298
+ END
299
+ r = rak("Caprica --passthru -n")
300
+ r.should include t1
301
+ r.should include t2
302
+ r.should include t3
303
+ r.lines.length.should < (t1+t2+t3).lines.length+5
304
+ end
305
+
306
+ it "--nocolour means do not colourize the output" do
307
+ rak("Cap --nocolour").should == <<-END
308
+ foo.rb
309
+ 3|foo foo foo Caprica foo foo foo
310
+ 4|foo Capsicum foo foo foo foo foo
311
+ END
312
+ end
313
+
314
+ it "-a means to search every file" do
315
+ rak("Libris -a").should == <<-END
316
+ *qux*
317
+ 1|qux qux qux *Libris* qux qux qux
318
+ END
319
+ end
320
+
321
+ it "--ruby means only ruby files" do
322
+ rak("Virgon --ruby").should == ""
323
+ end
324
+
325
+ it "--python means only python files" do
326
+ rak("Cap --python").should == ""
327
+ end
328
+
329
+ it "--noruby means exclude ruby files" do
330
+ rak("Cap --noruby").should == ""
331
+ end
332
+
333
+ it "--type=ruby means only ruby files" do
334
+ rak("Virgon --type=ruby").should == ""
335
+ end
336
+
337
+ it "--type=python means only python files" do
338
+ rak("Cap --type=python").should == ""
339
+ end
340
+
341
+ it "--type=noruby means exclude ruby files" do
342
+ rak("Cap --type=noruby").should == ""
343
+ end
344
+
345
+ it "--sort-files" do
346
+ rak("-f --sort-files").should == <<-END
347
+ dir1/bar.rb
348
+ foo.rb
349
+ quux.py
350
+ Rakefile
351
+ shebang
352
+ END
353
+ end
354
+
355
+ it "--follow means follow symlinks" do
356
+ rak("Sagitarron --follow", :ansi => '').should == <<-END
357
+ corge.rb
358
+ 1|corge corge corge Sagitarron corge
359
+
360
+ ln_dir/corge.rb
361
+ 1|corge corge corge Sagitarron corge
362
+ END
363
+ end
364
+
365
+ it "-A NUM means show NUM lines after" do
366
+ rak("Caps -A 2", :ansi => '').should == <<-END
367
+ foo.rb
368
+ 4|foo Capsicum foo foo foo foo foo
369
+ 5|
370
+ 6|foo foo foo foo foo Pikon foo foo
371
+ END
372
+ end
373
+
374
+ it "-A should work when there are matches close together" do
375
+ rak("foo -A 2", :ansi => '').should == <<-END
376
+ foo.rb
377
+ 3|foo foo foo Caprica foo foo foo
378
+ 4|foo Capsicum foo foo foo foo foo
379
+ 5|
380
+ 6|foo foo foo foo foo Pikon foo foo
381
+ 7|
382
+ 8|foo Pikon foo foo foo foo foo foo
383
+ 9|
384
+ 10|foo foo Six foo foo foo Six foo
385
+ 11|foo foo foo foo Six foo foo foo
386
+ 12|
387
+ 13|foo foo foo Gemenon foo foo foo
388
+ END
389
+ end
390
+
391
+ it "-B NUM means show NUM lines before" do
392
+ rak("Caps -B 2", :ansi => '').should == <<-END
393
+ foo.rb
394
+ 2|
395
+ 3|foo foo foo Caprica foo foo foo
396
+ 4|foo Capsicum foo foo foo foo foo
397
+ END
398
+ end
399
+
400
+ it "-C means show 2 lines before and after" do
401
+ rak("Caps -C", :ansi => '').should == <<-END
402
+ foo.rb
403
+ 2|
404
+ 3|foo foo foo Caprica foo foo foo
405
+ 4|foo Capsicum foo foo foo foo foo
406
+ 5|
407
+ 6|foo foo foo foo foo Pikon foo foo
408
+ END
409
+ end
410
+
411
+ it "-C 1 means show 1 lines before and after" do
412
+ rak("Caps -C 1", :ansi => '').should == <<-END
413
+ foo.rb
414
+ 3|foo foo foo Caprica foo foo foo
415
+ 4|foo Capsicum foo foo foo foo foo
416
+ 5|
417
+ END
418
+ end
419
+
420
+ it "-C works correctly for nearby results" do
421
+ rak("Pik -g foo -C", :ansi => '').should == <<-END
422
+ foo.rb
423
+ 4|foo Capsicum foo foo foo foo foo
424
+ 5|
425
+ 6|foo foo foo foo foo Pikon foo foo
426
+ 7|
427
+ 8|foo Pikon foo foo foo foo foo foo
428
+ 9|
429
+ 10|foo foo Six foo foo foo Six foo
430
+ END
431
+ end
432
+
433
+ it "-g REGEX only searches in files matching REGEX" do
434
+ rak("Pikon -g f.o").should == <<-END
435
+ *foo.rb*
436
+ 6|foo foo foo foo foo *Pikon* foo foo
437
+ 8|foo *Pikon* foo foo foo foo foo foo
438
+ END
439
+ end
440
+
441
+ it "-k REGEX only searches in files not matching REGEX" do
442
+ rak("Pikon -k f.o").should == <<-END
443
+ *dir1/bar.rb*
444
+ 2|bar bar bar bar *Pikon* bar
445
+ 9|bar bar *Pikon* bar bar bar
446
+ END
447
+ end
448
+
449
+ it "-x means match only whole lines" do
450
+ rak("Cap -x").should == ""
451
+ rak('"foo|goo" -x').should == ""
452
+ rak('"(foo )+Cap\w+( foo)+" -x').should == <<-END
453
+ *foo.rb*
454
+ 3|*foo foo foo Caprica foo foo foo*
455
+ 4|*foo Capsicum foo foo foo foo foo*
456
+ END
457
+ end
458
+
459
+ it "-s means match only at the start of a line" do
460
+ rak('-s "foo Cap|Aquaria"').should == <<-END
461
+ *foo.rb*
462
+ 4|*foo Cap*sicum foo foo foo foo foo
463
+ END
464
+ end
465
+
466
+ it "-e means match only at the end of a line" do
467
+ rak('-e "Aquaria|kon foo foo"').should == <<-END
468
+ *foo.rb*
469
+ 6|foo foo foo foo foo Pi*kon foo foo*
470
+ END
471
+ end
472
+
473
+ it "should not recurse down '..' when used with . " do
474
+ rak("foo .", :dir=>HERE+"example/dir1").should == ""
475
+ end
476
+ end
477
+
478
+ describe "Rak", "with combinations of options" do
479
+ it "should process -c -v " do
480
+ t1=<<-END
481
+ quux.py:1
482
+ dir1/bar.rb:7
483
+ foo.rb:11
484
+ shebang:3
485
+ Rakefile:1
486
+ END
487
+ rak("Pikon -c -v", :ansi => '').lines.sort.should == t1.lines.sort
488
+ end
489
+
490
+ it "-h and redirection" do
491
+ rak("Pik -h | cat", :test_mode => false).should == <<-END
492
+ bar bar bar bar Pikon bar
493
+ bar bar Pikon bar bar bar
494
+ foo foo foo foo foo Pikon foo foo
495
+ foo Pikon foo foo foo foo foo foo
496
+ END
497
+ end
498
+ end
499
+
500
+ describe "Rak", "with --eval" do
501
+ it "should support next" do
502
+ rak(%Q[--eval 'next unless $. == $_.split.size']).should == <<-END
503
+ *foo.rb*
504
+ 8|*foo Pikon foo foo foo foo foo foo*
505
+ END
506
+ end
507
+
508
+ it "should support break" do
509
+ rak(%Q[--eval 'break if $. == 2']).should == <<-END
510
+ *dir1/bar.rb*
511
+ 1|*
512
+
513
+ *foo.rb*
514
+ 1|*
515
+
516
+ *quux.py*
517
+ 1|*quux quux quux quux Virgon quux quux*
518
+
519
+ *Rakefile*
520
+ 1|*rakefile rakefile Canceron rakefile*
521
+
522
+ *shebang*
523
+ 1|*#!/usr/bin/env ruby*
524
+ END
525
+ end
526
+
527
+ it "should support highlighting" do
528
+ rak(%Q[--eval 'next unless $_ =~ /Caprica/']).should == <<-END
529
+ *foo.rb*
530
+ 3|foo foo foo *Caprica* foo foo foo
531
+ END
532
+ end
533
+
534
+ it "should support ranges" do
535
+ rak(%Q[--eval 'next unless $_[/Capsicum/]..$_[/Pikon/]']).should == <<-END
536
+ *foo.rb*
537
+ 4|*foo Capsicum foo foo foo foo foo*
538
+ 5|*
539
+ 6|foo foo foo foo foo *Pikon* foo foo
540
+ END
541
+ end
542
+
543
+ it "should support next and contexts" do
544
+ rak(%Q[-C 2 --eval 'next unless $_ =~ /Pikon/']).should == <<-END
545
+ *dir1/bar.rb*
546
+ 1|
547
+ 2|bar bar bar bar *Pikon* bar
548
+ 3|
549
+ 4|
550
+ 7|
551
+ 8|
552
+ 9|bar bar *Pikon* bar bar bar
553
+
554
+ *foo.rb*
555
+ 4|foo Capsicum foo foo foo foo foo
556
+ 5|
557
+ 6|foo foo foo foo foo *Pikon* foo foo
558
+ 7|
559
+ 8|foo *Pikon* foo foo foo foo foo foo
560
+ 9|
561
+ 10|foo foo Six foo foo foo Six foo
562
+ END
563
+ end
564
+
565
+ it "should support break and contexts (and matches past break should get no highlighting)" do
566
+ rak(%Q[-C 2 --eval 'next unless $_[/Pikon/]...(break; nil)']).should == <<-END
567
+ *dir1/bar.rb*
568
+ 1|
569
+ 2|bar bar bar bar *Pikon* bar
570
+ 3|
571
+ 4|
572
+
573
+ *foo.rb*
574
+ 4|foo Capsicum foo foo foo foo foo
575
+ 5|
576
+ 6|foo foo foo foo foo *Pikon* foo foo
577
+ 7|
578
+ 8|foo Pikon foo foo foo foo foo foo
579
+ END
580
+ end
581
+
582
+ it "should support $_ transformations" do
583
+ rak(%Q[--eval '$_=$_.reverse; next unless $_ =~ /oof/']).should == <<-END
584
+ *foo.rb*
585
+ 3|*oof* oof oof acirpaC oof oof oof
586
+ 4|*oof* oof oof oof oof mucispaC oof
587
+ 6|*oof* oof nokiP oof oof oof oof oof
588
+ 8|*oof* oof oof oof oof oof nokiP oof
589
+ 10|*oof* xiS oof oof oof xiS oof oof
590
+ 11|*oof* oof oof xiS oof oof oof oof
591
+ 13|*oof* oof oof nonemeG oof oof oof
592
+ END
593
+ end
594
+
595
+ it "should support multiple matches" do
596
+ rak(%Q[--eval 'next unless $_ =~ /Pikon/; $_.scan(/\\b\\w{3}\\b/){ matches << $~ }']).should == <<-END
597
+ *dir1/bar.rb*
598
+ 2|*bar* *bar* *bar* *bar* Pikon *bar*
599
+ 9|*bar* *bar* Pikon *bar* *bar* *bar*
600
+
601
+ *foo.rb*
602
+ 6|*foo* *foo* *foo* *foo* *foo* Pikon *foo* *foo*
603
+ 8|*foo* Pikon *foo* *foo* *foo* *foo* *foo* *foo*
604
+ END
605
+ end
606
+ end
607
+
608
+ ## Other things --eval could support:
609
+ # * per file BEGIN{} END{}
610
+ # * global BEGIN{} END{}
611
+ # * better way to highlight multiple matches
612
+ #
613
+ # There's also redo but I cannot think of any sensible use
614
+ # (especially if $_ won't persist between runs)
615
+ # (also redo in -nl/-pl is broken)