]> Tony Duckles's Git Repositories (git.nynim.org) - dotfiles.git/blob - bin/ack
bin/colortable: Print a color table of ANSI colors (normal+bright)
[dotfiles.git] / bin / ack
1 #!/usr/bin/env perl
2 #
3 # This file, ack, is generated code.
4 # Please DO NOT EDIT or send patches for it.
5 #
6 # Please take a look at the source from
7 # https://github.com/petdance/ack
8 # and submit patches against the individual files
9 # that build ack.
10 #
11
12 use warnings;
13 use strict;
14
15 our $VERSION = '1.96';
16 # Check http://betterthangrep.com/ for updates
17
18 # These are all our globals.
19
20
21 MAIN: {
22 if ( $App::Ack::VERSION ne $main::VERSION ) {
23 App::Ack::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
24 }
25
26 # Do preliminary arg checking;
27 my $env_is_usable = 1;
28 for ( @ARGV ) {
29 last if ( $_ eq '--' );
30
31 # Priorities! Get the --thpppt checking out of the way.
32 /^--th[pt]+t+$/ && App::Ack::_thpppt($_);
33
34 # See if we want to ignore the environment. (Don't tell Al Gore.)
35 if ( /^--(no)?env$/ ) {
36 $env_is_usable = defined $1 ? 0 : 1;
37 }
38 }
39 if ( $env_is_usable ) {
40 unshift( @ARGV, App::Ack::read_ackrc() );
41 }
42 else {
43 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
44 delete @ENV{@keys};
45 }
46 App::Ack::load_colors();
47
48 if ( exists $ENV{ACK_SWITCHES} ) {
49 App::Ack::warn( 'ACK_SWITCHES is no longer supported. Use ACK_OPTIONS.' );
50 }
51
52 if ( !@ARGV ) {
53 App::Ack::show_help();
54 exit 1;
55 }
56
57 main();
58 }
59
60 sub main {
61 my $opt = App::Ack::get_command_line_options();
62
63 $| = 1 if $opt->{flush}; # Unbuffer the output if flush mode
64
65 if ( App::Ack::input_from_pipe() ) {
66 # We're going into filter mode
67 for ( qw( f g l ) ) {
68 $opt->{$_} and App::Ack::die( "Can't use -$_ when acting as a filter." );
69 }
70 $opt->{show_filename} = 0;
71 $opt->{regex} = App::Ack::build_regex( defined $opt->{regex} ? $opt->{regex} : shift @ARGV, $opt );
72 if ( my $nargs = @ARGV ) {
73 my $s = $nargs == 1 ? '' : 's';
74 App::Ack::warn( "Ignoring $nargs argument$s on the command-line while acting as a filter." );
75 }
76
77 my $res = App::Ack::Resource::Basic->new( '-' );
78 my $nmatches;
79 if ( $opt->{count} ) {
80 $nmatches = App::Ack::search_and_list( $res, $opt );
81 }
82 else {
83 # normal searching
84 $nmatches = App::Ack::search_resource( $res, $opt );
85 }
86 $res->close();
87 App::Ack::exit_from_ack( $nmatches );
88 }
89
90 my $file_matching = $opt->{f} || $opt->{lines};
91 if ( $file_matching ) {
92 App::Ack::die( "Can't specify both a regex ($opt->{regex}) and use one of --line, -f or -g." ) if $opt->{regex};
93 }
94 else {
95 $opt->{regex} = App::Ack::build_regex( defined $opt->{regex} ? $opt->{regex} : shift @ARGV, $opt );
96 }
97
98 # check that all regexes do compile fine
99 App::Ack::check_regex( $_ ) for ( $opt->{regex}, $opt->{G} );
100
101 my $what = App::Ack::get_starting_points( \@ARGV, $opt );
102 my $iter = App::Ack::get_iterator( $what, $opt );
103 App::Ack::filetype_setup();
104
105 my $nmatches = 0;
106
107 App::Ack::set_up_pager( $opt->{pager} ) if defined $opt->{pager};
108 if ( $opt->{f} ) {
109 $nmatches = App::Ack::print_files( $iter, $opt );
110 }
111 elsif ( $opt->{l} || $opt->{count} ) {
112 $nmatches = App::Ack::print_files_with_matches( $iter, $opt );
113 }
114 else {
115 $nmatches = App::Ack::print_matches( $iter, $opt );
116 }
117 close $App::Ack::fh;
118 App::Ack::exit_from_ack( $nmatches );
119 }
120
121 =head1 NAME
122
123 ack - grep-like text finder
124
125 =head1 SYNOPSIS
126
127 ack [options] PATTERN [FILE...]
128 ack -f [options] [DIRECTORY...]
129
130 =head1 DESCRIPTION
131
132 Ack is designed as a replacement for 99% of the uses of F<grep>.
133
134 Ack searches the named input FILEs (or standard input if no files are
135 named, or the file name - is given) for lines containing a match to the
136 given PATTERN. By default, ack prints the matching lines.
137
138 Ack can also list files that would be searched, without actually searching
139 them, to let you take advantage of ack's file-type filtering capabilities.
140
141 =head1 FILE SELECTION
142
143 I<ack> is intelligent about the files it searches. It knows about
144 certain file types, based on both the extension on the file and,
145 in some cases, the contents of the file. These selections can be
146 made with the B<--type> option.
147
148 With no file selections, I<ack> only searches files of types that
149 it recognizes. If you have a file called F<foo.wango>, and I<ack>
150 doesn't know what a .wango file is, I<ack> won't search it.
151
152 The B<-a> option tells I<ack> to select all files, regardless of
153 type.
154
155 Some files will never be selected by I<ack>, even with B<-a>,
156 including:
157
158 =over 4
159
160 =item * Backup files: Files matching F<#*#> or ending with F<~>.
161
162 =item * Coredumps: Files matching F<core.\d+>
163
164 =back
165
166 However, I<ack> always searches the files given on the command line,
167 no matter what type. Furthermore, by specifying the B<-u> option all
168 files will be searched.
169
170 =head1 DIRECTORY SELECTION
171
172 I<ack> descends through the directory tree of the starting directories
173 specified. However, it will ignore the shadow directories used by
174 many version control systems, and the build directories used by the
175 Perl MakeMaker system. You may add or remove a directory from this
176 list with the B<--[no]ignore-dir> option. The option may be repeated
177 to add/remove multiple directories from the ignore list.
178
179 For a complete list of directories that do not get searched, run
180 F<ack --help>.
181
182 =head1 WHEN TO USE GREP
183
184 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
185 throw I<grep> away, because there are times you'll still need it.
186
187 E.g., searching through huge files looking for regexes that can be
188 expressed with I<grep> syntax should be quicker with I<grep>.
189
190 If your script or parent program uses I<grep> C<--quiet> or
191 C<--silent> or needs exit 2 on IO error, use I<grep>.
192
193 =head1 OPTIONS
194
195 =over 4
196
197 =item B<-a>, B<--all>
198
199 Operate on all files, regardless of type (but still skip directories
200 like F<blib>, F<CVS>, etc.)
201
202 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
203
204 Print I<NUM> lines of trailing context after matching lines.
205
206 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
207
208 Print I<NUM> lines of leading context before matching lines.
209
210 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
211
212 Print I<NUM> lines (default 2) of context around matching lines.
213
214 =item B<-c>, B<--count>
215
216 Suppress normal output; instead print a count of matching lines for
217 each input file. If B<-l> is in effect, it will only show the
218 number of lines for each file that has lines matching. Without
219 B<-l>, some line counts may be zeroes.
220
221 If combined with B<-h> (B<--no-filename>) ack outputs only one total count.
222
223 =item B<--color>, B<--nocolor>
224
225 B<--color> highlights the matching text. B<--nocolor> supresses
226 the color. This is on by default unless the output is redirected.
227
228 On Windows, this option is off by default unless the
229 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
230 environment variable is used.
231
232 =item B<--color-filename=I<color>>
233
234 Sets the color to be used for filenames.
235
236 =item B<--color-match=I<color>>
237
238 Sets the color to be used for matches.
239
240 =item B<--color-lineno=I<color>>
241
242 Sets the color to be used for line numbers.
243
244 =item B<--column>
245
246 Show the column number of the first match. This is helpful for editors
247 that can place your cursor at a given position.
248
249 =item B<--env>, B<--noenv>
250
251 B<--noenv> disables all environment processing. No F<.ackrc> is read
252 and all environment variables are ignored. By default, F<ack> considers
253 F<.ackrc> and settings in the environment.
254
255 =item B<--flush>
256
257 B<--flush> flushes output immediately. This is off by default
258 unless ack is running interactively (when output goes to a pipe
259 or file).
260
261 =item B<-f>
262
263 Only print the files that would be searched, without actually doing
264 any searching. PATTERN must not be specified, or it will be taken as
265 a path to search.
266
267 =item B<--follow>, B<--nofollow>
268
269 Follow or don't follow symlinks, other than whatever starting files
270 or directories were specified on the command line.
271
272 This is off by default.
273
274 =item B<-G I<REGEX>>
275
276 Only paths matching I<REGEX> are included in the search. The entire
277 path and filename are matched against I<REGEX>, and I<REGEX> is a
278 Perl regular expression, not a shell glob.
279
280 The options B<-i>, B<-w>, B<-v>, and B<-Q> do not apply to this I<REGEX>.
281
282 =item B<-g I<REGEX>>
283
284 Print files where the relative path + filename matches I<REGEX>. This option is
285 a convenience shortcut for B<-f> B<-G I<REGEX>>.
286
287 The options B<-i>, B<-w>, B<-v>, and B<-Q> do not apply to this I<REGEX>.
288
289 =item B<--group>, B<--nogroup>
290
291 B<--group> groups matches by file name with. This is the default when
292 used interactively.
293
294 B<--nogroup> prints one result per line, like grep. This is the default
295 when output is redirected.
296
297 =item B<-H>, B<--with-filename>
298
299 Print the filename for each match.
300
301 =item B<-h>, B<--no-filename>
302
303 Suppress the prefixing of filenames on output when multiple files are
304 searched.
305
306 =item B<--help>
307
308 Print a short help statement.
309
310 =item B<-i>, B<--ignore-case>
311
312 Ignore case in the search strings.
313
314 This applies only to the PATTERN, not to the regexes given for the B<-g>
315 and B<-G> options.
316
317 =item B<--[no]ignore-dir=I<DIRNAME>>
318
319 Ignore directory (as CVS, .svn, etc are ignored). May be used multiple times
320 to ignore multiple directories. For example, mason users may wish to include
321 B<--ignore-dir=data>. The B<--noignore-dir> option allows users to search
322 directories which would normally be ignored (perhaps to research the contents
323 of F<.svn/props> directories).
324
325 The I<DIRNAME> must always be a simple directory name. Nested directories like
326 F<foo/bar> are NOT supported. You would need to specify B<--ignore-dir=foo> and
327 then no files from any foo directory are taken into account by ack unless given
328 explicitly on the command line.
329
330 =item B<--line=I<NUM>>
331
332 Only print line I<NUM> of each file. Multiple lines can be given with multiple
333 B<--line> options or as a comma separated list (B<--line=3,5,7>). B<--line=4-7>
334 also works. The lines are always output in ascending order, no matter the
335 order given on the command line.
336
337 =item B<-l>, B<--files-with-matches>
338
339 Only print the filenames of matching files, instead of the matching text.
340
341 =item B<-L>, B<--files-without-matches>
342
343 Only print the filenames of files that do I<NOT> match. This is equivalent
344 to specifying B<-l> and B<-v>.
345
346 =item B<--match I<REGEX>>
347
348 Specify the I<REGEX> explicitly. This is helpful if you don't want to put the
349 regex as your first argument, e.g. when executing multiple searches over the
350 same set of files.
351
352 # search for foo and bar in given files
353 ack file1 t/file* --match foo
354 ack file1 t/file* --match bar
355
356 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
357
358 Stop reading a file after I<NUM> matches.
359
360 =item B<--man>
361
362 Print this manual page.
363
364 =item B<-n>, B<--no-recurse>
365
366 No descending into subdirectories.
367
368 =item B<-o>
369
370 Show only the part of each line matching PATTERN (turns off text
371 highlighting)
372
373 =item B<--output=I<expr>>
374
375 Output the evaluation of I<expr> for each line (turns off text
376 highlighting)
377
378 =item B<--pager=I<program>>
379
380 Direct ack's output through I<program>. This can also be specified
381 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
382
383 Using --pager does not suppress grouping and coloring like piping
384 output on the command-line does.
385
386 =item B<--passthru>
387
388 Prints all lines, whether or not they match the expression. Highlighting
389 will still work, though, so it can be used to highlight matches while
390 still seeing the entire file, as in:
391
392 # Watch a log file, and highlight a certain IP address
393 $ tail -f ~/access.log | ack --passthru 123.45.67.89
394
395 =item B<--print0>
396
397 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
398 are output separated with a null byte instead of the usual newline. This is
399 helpful when dealing with filenames that contain whitespace, e.g.
400
401 # remove all files of type html
402 ack -f --html --print0 | xargs -0 rm -f
403
404 =item B<-Q>, B<--literal>
405
406 Quote all metacharacters in PATTERN, it is treated as a literal.
407
408 This applies only to the PATTERN, not to the regexes given for the B<-g>
409 and B<-G> options.
410
411 =item B<-r>, B<-R>, B<--recurse>
412
413 Recurse into sub-directories. This is the default and just here for
414 compatibility with grep. You can also use it for turning B<--no-recurse> off.
415
416 =item B<--smart-case>, B<--no-smart-case>
417
418 Ignore case in the search strings if PATTERN contains no uppercase
419 characters. This is similar to C<smartcase> in vim. This option is
420 off by default.
421
422 B<-i> always overrides this option.
423
424 This applies only to the PATTERN, not to the regexes given for the
425 B<-g> and B<-G> options.
426
427 =item B<--sort-files>
428
429 Sorts the found files lexically. Use this if you want your file
430 listings to be deterministic between runs of I<ack>.
431
432 =item B<--show-types>
433
434 Outputs the filetypes that ack associates with each file.
435
436 Works with B<-f> and B<-g> options.
437
438 =item B<--thpppt>
439
440 Display the all-important Bill The Cat logo. Note that the exact
441 spelling of B<--thpppppt> is not important. It's checked against
442 a regular expression.
443
444 =item B<--type=TYPE>, B<--type=noTYPE>
445
446 Specify the types of files to include or exclude from a search.
447 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
448 also be specified as B<--perl>, and B<--type=noperl> can be done
449 as B<--noperl>.
450
451 If a file is of both type "foo" and "bar", specifying --foo and
452 --nobar will exclude the file, because an exclusion takes precedence
453 over an inclusion.
454
455 Type specifications can be repeated and are ORed together.
456
457 See I<ack --help=types> for a list of valid types.
458
459 =item B<--type-add I<TYPE>=I<.EXTENSION>[,I<.EXT2>[,...]]>
460
461 Files with the given EXTENSION(s) are recognized as being of (the
462 existing) type TYPE. See also L</"Defining your own types">.
463
464
465 =item B<--type-set I<TYPE>=I<.EXTENSION>[,I<.EXT2>[,...]]>
466
467 Files with the given EXTENSION(s) are recognized as being of type
468 TYPE. This replaces an existing definition for type TYPE. See also
469 L</"Defining your own types">.
470
471 =item B<-u>, B<--unrestricted>
472
473 All files and directories (including blib/, core.*, ...) are searched,
474 nothing is skipped. When both B<-u> and B<--ignore-dir> are used, the
475 B<--ignore-dir> option has no effect.
476
477 =item B<-v>, B<--invert-match>
478
479 Invert match: select non-matching lines
480
481 This applies only to the PATTERN, not to the regexes given for the B<-g>
482 and B<-G> options.
483
484 =item B<--version>
485
486 Display version and copyright information.
487
488 =item B<-w>, B<--word-regexp>
489
490 Force PATTERN to match only whole words. The PATTERN is wrapped with
491 C<\b> metacharacters.
492
493 This applies only to the PATTERN, not to the regexes given for the B<-g>
494 and B<-G> options.
495
496 =item B<-1>
497
498 Stops after reporting first match of any kind. This is different
499 from B<--max-count=1> or B<-m1>, where only one match per file is
500 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
501 not.
502
503 =back
504
505 =head1 THE .ackrc FILE
506
507 The F<.ackrc> file contains command-line options that are prepended
508 to the command line before processing. Multiple options may live
509 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
510 might look like this:
511
512 # Always sort the files
513 --sort-files
514
515 # Always color, even if piping to a another program
516 --color
517
518 # Use "less -r" as my pager
519 --pager=less -r
520
521 Note that arguments with spaces in them do not need to be quoted,
522 as they are not interpreted by the shell. Basically, each I<line>
523 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
524
525 F<ack> looks in your home directory for the F<.ackrc>. You can
526 specify another location with the F<ACKRC> variable, below.
527
528 If B<--noenv> is specified on the command line, the F<.ackrc> file
529 is ignored.
530
531 =head1 Defining your own types
532
533 ack allows you to define your own types in addition to the predefined
534 types. This is done with command line options that are best put into
535 an F<.ackrc> file - then you do not have to define your types over and
536 over again. In the following examples the options will always be shown
537 on one command line so that they can be easily copy & pasted.
538
539 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
540 tells you, that perl files are files ending
541 in .pl, .pm, .pod or .t. So what if you would like to include .xs
542 files as well when searching for --perl files? I<ack --type-add perl=.xs --perl foo>
543 does this for you. B<--type-add> appends
544 additional extensions to an existing type.
545
546 If you want to define a new type, or completely redefine an existing
547 type, then use B<--type-set>. I<ack --type-set
548 eiffel=.e,.eiffel> defines the type I<eiffel> to include files with
549 the extensions .e or .eiffel. So to search for all eiffel files
550 containing the word Bertrand use I<ack --type-set eiffel=.e,.eiffel --eiffel Bertrand>.
551 As usual, you can also write B<--type=eiffel>
552 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
553 all eiffel files from a search. Redefining also works: I<ack --type-set cc=.c,.h>
554 and I<.xs> files no longer belong to the type I<cc>.
555
556 When defining your own types in the F<.ackrc> file you have to use
557 the following:
558
559 --type-set=eiffel=.e,.eiffel
560
561 or writing on separate lines
562
563 --type-set
564 eiffel=.e,.eiffel
565
566 The following does B<NOT> work in the F<.ackrc> file:
567
568 --type-set eiffel=.e,.eiffel
569
570
571 In order to see all currently defined types, use I<--help types>, e.g.
572 I<ack --type-set backup=.bak --type-add perl=.perl --help types>
573
574 Restrictions:
575
576 =over 4
577
578 =item
579
580 The types 'skipped', 'make', 'binary' and 'text' are considered "builtin" and
581 cannot be altered.
582
583 =item
584
585 The shebang line recognition of the types 'perl', 'ruby', 'php', 'python',
586 'shell' and 'xml' cannot be redefined by I<--type-set>, it is always
587 active. However, the shebang line is only examined for files where the
588 extension is not recognised. Therefore it is possible to say
589 I<ack --type-set perl=.perl --type-set foo=.pl,.pm,.pod,.t --perl --nofoo> and
590 only find your shiny new I<.perl> files (and all files with unrecognized extension
591 and perl on the shebang line).
592
593 =back
594
595 =head1 ENVIRONMENT VARIABLES
596
597 For commonly-used ack options, environment variables can make life much easier.
598 These variables are ignored if B<--noenv> is specified on the command line.
599
600 =over 4
601
602 =item ACKRC
603
604 Specifies the location of the F<.ackrc> file. If this file doesn't
605 exist, F<ack> looks in the default location.
606
607 =item ACK_OPTIONS
608
609 This variable specifies default options to be placed in front of
610 any explicit options on the command line.
611
612 =item ACK_COLOR_FILENAME
613
614 Specifies the color of the filename when it's printed in B<--group>
615 mode. By default, it's "bold green".
616
617 The recognized attributes are clear, reset, dark, bold, underline,
618 underscore, blink, reverse, concealed black, red, green, yellow,
619 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
620 on_magenta, on_cyan, and on_white. Case is not significant.
621 Underline and underscore are equivalent, as are clear and reset.
622 The color alone sets the foreground color, and on_color sets the
623 background color.
624
625 This option can also be set with B<--color-filename>.
626
627 =item ACK_COLOR_MATCH
628
629 Specifies the color of the matching text when printed in B<--color>
630 mode. By default, it's "black on_yellow".
631
632 This option can also be set with B<--color-match>.
633
634 See B<ACK_COLOR_FILENAME> for the color specifications.
635
636 =item ACK_COLOR_LINENO
637
638 Specifies the color of the line number when printed in B<--color>
639 mode. By default, it's "bold yellow".
640
641 This option can also be set with B<--color-lineno>.
642
643 See B<ACK_COLOR_FILENAME> for the color specifications.
644
645 =item ACK_PAGER
646
647 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
648 ack will send its output.
649
650 Using C<ACK_PAGER> does not suppress grouping and coloring like
651 piping output on the command-line does, except that on Windows
652 ack will assume that C<ACK_PAGER> does not support color.
653
654 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
655
656 =item ACK_PAGER_COLOR
657
658 Specifies a pager program that understands ANSI color sequences.
659 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
660 like piping output on the command-line does.
661
662 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
663
664 =back
665
666 =head1 ACK & OTHER TOOLS
667
668 =head2 Vim integration
669
670 F<ack> integrates easily with the Vim text editor. Set this in your
671 F<.vimrc> to use F<ack> instead of F<grep>:
672
673 set grepprg=ack\ -a
674
675 That examples uses C<-a> to search through all files, but you may
676 use other default flags. Now you can search with F<ack> and easily
677 step through the results in Vim:
678
679 :grep Dumper perllib
680
681 =head2 Emacs integration
682
683 Phil Jackson put together an F<ack.el> extension that "provides a
684 simple compilation mode ... has the ability to guess what files you
685 want to search for based on the major-mode."
686
687 L<http://www.shellarchive.co.uk/content/emacs.html>
688
689 =head2 TextMate integration
690
691 Pedro Melo is a TextMate user who writes "I spend my day mostly
692 inside TextMate, and the built-in find-in-project sucks with large
693 projects. So I hacked a TextMate command that was using find +
694 grep to use ack. The result is the Search in Project with ack, and
695 you can find it here:
696 L<http://www.simplicidade.org/notes/archives/2008/03/search_in_proje.html>"
697
698 =head2 Shell and Return Code
699
700 For greater compatibility with I<grep>, I<ack> in normal use returns
701 shell return or exit code of 0 only if something is found and 1 if
702 no match is found.
703
704 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
705
706 The I<grep> code 2 for errors is not used.
707
708 If C<-f> or C<-g> are specified, then 0 is returned if at least one
709 file is found. If no files are found, then 1 is returned.
710
711 =cut
712
713 =head1 DEBUGGING ACK PROBLEMS
714
715 If ack gives you output you're not expecting, start with a few simple steps.
716
717 =head2 Use B<--noenv>
718
719 Your environment variables and F<.ackrc> may be doing things you're
720 not expecting, or forgotten you specified. Use B<--noenv> to ignore
721 your environment and F<.ackrc>.
722
723 =head2 Use B<-f> to see what files you're scanning
724
725 The reason I created B<-f> in the first place was as a debugging
726 tool. If ack is not finding matches you think it should find, run
727 F<ack -f> to see what files are being checked.
728
729 =head1 TIPS
730
731 =head2 Use the F<.ackrc> file.
732
733 The F<.ackrc> is the place to put all your options you use most of
734 the time but don't want to remember. Put all your --type-add and
735 --type-set definitions in it. If you like --smart-case, set it
736 there, too. I also set --sort-files there.
737
738 =head2 Use F<-f> for working with big codesets
739
740 Ack does more than search files. C<ack -f --perl> will create a
741 list of all the Perl files in a tree, ideal for sending into F<xargs>.
742 For example:
743
744 # Change all "this" to "that" in all Perl files in a tree.
745 ack -f --perl | xargs perl -p -i -e's/this/that/g'
746
747 or if you prefer:
748
749 perl -p -i -e's/this/thatg/' $(ack -f --perl)
750
751 =head2 Use F<-Q> when in doubt about metacharacters
752
753 If you're searching for something with a regular expression
754 metacharacter, most often a period in a filename or IP address, add
755 the -Q to avoid false positives without all the backslashing. See
756 the following example for more...
757
758 =head2 Use ack to watch log files
759
760 Here's one I used the other day to find trouble spots for a website
761 visitor. The user had a problem loading F<troublesome.gif>, so I
762 took the access log and scanned it with ack twice.
763
764 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
765
766 The first ack finds only the lines in the Apache log for the given
767 IP. The second finds the match on my troublesome GIF, and shows
768 the previous five lines from the log in each case.
769
770 =head2 Share your knowledge
771
772 Join the ack-users mailing list. Send me your tips and I may add
773 them here.
774
775 =head1 FAQ
776
777 =head2 Why isn't ack finding a match in (some file)?
778
779 Probably because it's of a type that ack doesn't recognize. ack's
780 searching behavior is driven by filetype. B<If ack doesn't know
781 what kind of file it is, ack ignores the file.>
782
783 Use the C<-f> switch to see a list of files that ack will search
784 for you.
785
786 If you want ack to search files that it doesn't recognize, use the
787 C<-a> switch.
788
789 If you want ack to search every file, even ones that it always
790 ignores like coredumps and backup files, use the C<-u> switch.
791
792 =head2 Why does ack ignore unknown files by default?
793
794 ack is designed by a programmer, for programmers, for searching
795 large trees of code. Most codebases have a lot files in them which
796 aren't source files (like compiled object files, source control
797 metadata, etc), and grep wastes a lot of time searching through all
798 of those as well and returning matches from those files.
799
800 That's why ack's behavior of not searching things it doesn't recognize
801 is one of its greatest strengths: the speed you get from only
802 searching the things that you want to be looking at.
803
804 =head2 Wouldn't it be great if F<ack> did search & replace?
805
806 No, ack will always be read-only. Perl has a perfectly good way
807 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
808 switches.
809
810 You can certainly use ack to select your files to update. For
811 example, to change all "foo" to "bar" in all PHP files, you can do
812 this from the Unix shell:
813
814 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
815
816 =head2 Can you make ack recognize F<.xyz> files?
817
818 That's an enhancement. Please see the section in the manual about
819 enhancements.
820
821 =head2 There's already a program/package called ack.
822
823 Yes, I know.
824
825 =head2 Why is it called ack if it's called ack-grep?
826
827 The name of the program is "ack". Some packagers have called it
828 "ack-grep" when creating packages because there's already a package
829 out there called "ack" that has nothing to do with this ack.
830
831 I suggest you make a symlink named F<ack> that points to F<ack-grep>
832 because one of the crucial benefits of ack is having a name that's
833 so short and simple to type.
834
835 To do that, run this with F<sudo> or as root:
836
837 ln -s /usr/bin/ack-grep /usr/bin/ack
838
839 =head2 What does F<ack> mean?
840
841 Nothing. I wanted a name that was easy to type and that you could
842 pronounce as a single syllable.
843
844 =head2 Can I do multi-line regexes?
845
846 No, ack does not support regexes that match multiple lines. Doing
847 so would require reading in the entire file at a time.
848
849 If you want to see lines near your match, use the C<--A>, C<--B>
850 and C<--C> switches for displaying context.
851
852 =head1 AUTHOR
853
854 Andy Lester, C<< <andy at petdance.com> >>
855
856 =head1 BUGS
857
858 Please report any bugs or feature requests to the issues list at
859 Github: L<https://github.com/petdance/ack/issues>
860
861 =head1 ENHANCEMENTS
862
863 All enhancement requests MUST first be posted to the ack-users
864 mailing list at L<http://groups.google.com/group/ack-users>. I
865 will not consider a request without it first getting seen by other
866 ack users. This includes requests for new filetypes.
867
868 There is a list of enhancements I want to make to F<ack> in the ack
869 issues list at Github: L<https://github.com/petdance/ack/issues>
870
871 Patches are always welcome, but patches with tests get the most
872 attention.
873
874 =head1 SUPPORT
875
876 Support for and information about F<ack> can be found at:
877
878 =over 4
879
880 =item * The ack homepage
881
882 L<http://betterthangrep.com/>
883
884 =item * The ack issues list at Github
885
886 L<https://github.com/petdance/ack/issues>
887
888 =item * AnnoCPAN: Annotated CPAN documentation
889
890 L<http://annocpan.org/dist/ack>
891
892 =item * CPAN Ratings
893
894 L<http://cpanratings.perl.org/d/ack>
895
896 =item * Search CPAN
897
898 L<http://search.cpan.org/dist/ack>
899
900 =item * Git source repository
901
902 L<https://github.com/petdance/ack>
903
904 =back
905
906 =head1 ACKNOWLEDGEMENTS
907
908 How appropriate to have I<ack>nowledgements!
909
910 Thanks to everyone who has contributed to ack in any way, including
911 Matthew Wild,
912 Scott Kyle,
913 Nick Hooey,
914 Bo Borgerson,
915 Mark Szymanski,
916 Marq Schneider,
917 Packy Anderson,
918 JR Boyens,
919 Dan Sully,
920 Ryan Niebur,
921 Kent Fredric,
922 Mike Morearty,
923 Ingmar Vanhassel,
924 Eric Van Dewoestine,
925 Sitaram Chamarty,
926 Adam James,
927 Richard Carlsson,
928 Pedro Melo,
929 AJ Schuster,
930 Phil Jackson,
931 Michael Schwern,
932 Jan Dubois,
933 Christopher J. Madsen,
934 Matthew Wickline,
935 David Dyck,
936 Jason Porritt,
937 Jjgod Jiang,
938 Thomas Klausner,
939 Uri Guttman,
940 Peter Lewis,
941 Kevin Riggle,
942 Ori Avtalion,
943 Torsten Blix,
944 Nigel Metheringham,
945 GE<aacute>bor SzabE<oacute>,
946 Tod Hagan,
947 Michael Hendricks,
948 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
949 Piers Cawley,
950 Stephen Steneker,
951 Elias Lutfallah,
952 Mark Leighton Fisher,
953 Matt Diephouse,
954 Christian Jaeger,
955 Bill Sully,
956 Bill Ricker,
957 David Golden,
958 Nilson Santos F. Jr,
959 Elliot Shank,
960 Merijn Broeren,
961 Uwe Voelker,
962 Rick Scott,
963 Ask BjE<oslash>rn Hansen,
964 Jerry Gay,
965 Will Coleda,
966 Mike O'Regan,
967 Slaven ReziE<0x107>,
968 Mark Stosberg,
969 David Alan Pisoni,
970 Adriano Ferreira,
971 James Keenan,
972 Leland Johnson,
973 Ricardo Signes
974 and Pete Krawczyk.
975
976 =head1 COPYRIGHT & LICENSE
977
978 Copyright 2005-2011 Andy Lester.
979
980 This program is free software; you can redistribute it and/or modify
981 it under the terms of the Artistic License v2.0.
982
983 =cut
984 package File::Next;
985
986 use strict;
987 use warnings;
988
989
990 our $VERSION = '1.06';
991
992
993
994 use File::Spec ();
995
996
997 our $name; # name of the current file
998 our $dir; # dir of the current file
999
1000 our %files_defaults;
1001 our %skip_dirs;
1002
1003 BEGIN {
1004 %files_defaults = (
1005 file_filter => undef,
1006 descend_filter => undef,
1007 error_handler => sub { CORE::die @_ },
1008 sort_files => undef,
1009 follow_symlinks => 1,
1010 );
1011 %skip_dirs = map {($_,1)} (File::Spec->curdir, File::Spec->updir);
1012 }
1013
1014
1015 sub files {
1016 ($_[0] eq __PACKAGE__) && die 'File::Next::files must not be invoked as File::Next->files';
1017
1018 my ($parms,@queue) = _setup( \%files_defaults, @_ );
1019 my $filter = $parms->{file_filter};
1020
1021 return sub {
1022 while (@queue) {
1023 my ($dir,$file,$fullpath) = splice( @queue, 0, 3 );
1024 if ( -f $fullpath ) {
1025 if ( $filter ) {
1026 local $_ = $file;
1027 local $File::Next::dir = $dir;
1028 local $File::Next::name = $fullpath;
1029 next if not $filter->();
1030 }
1031 return wantarray ? ($dir,$file,$fullpath) : $fullpath;
1032 }
1033 elsif ( -d _ ) {
1034 unshift( @queue, _candidate_files( $parms, $fullpath ) );
1035 }
1036 } # while
1037
1038 return;
1039 }; # iterator
1040 }
1041
1042
1043
1044
1045
1046
1047
1048 sub sort_standard($$) { return $_[0]->[1] cmp $_[1]->[1] }
1049 sub sort_reverse($$) { return $_[1]->[1] cmp $_[0]->[1] }
1050
1051 sub reslash {
1052 my $path = shift;
1053
1054 my @parts = split( /\//, $path );
1055
1056 return $path if @parts < 2;
1057
1058 return File::Spec->catfile( @parts );
1059 }
1060
1061
1062
1063 sub _setup {
1064 my $defaults = shift;
1065 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
1066
1067 my %passed_parms = %{$passed_parms};
1068
1069 my $parms = {};
1070 for my $key ( keys %{$defaults} ) {
1071 $parms->{$key} =
1072 exists $passed_parms{$key}
1073 ? delete $passed_parms{$key}
1074 : $defaults->{$key};
1075 }
1076
1077 # Any leftover keys are bogus
1078 for my $badkey ( keys %passed_parms ) {
1079 my $sub = (caller(1))[3];
1080 $parms->{error_handler}->( "Invalid option passed to $sub(): $badkey" );
1081 }
1082
1083 # If it's not a code ref, assume standard sort
1084 if ( $parms->{sort_files} && ( ref($parms->{sort_files}) ne 'CODE' ) ) {
1085 $parms->{sort_files} = \&sort_standard;
1086 }
1087 my @queue;
1088
1089 for ( @_ ) {
1090 my $start = reslash( $_ );
1091 if (-d $start) {
1092 push @queue, ($start,undef,$start);
1093 }
1094 else {
1095 push @queue, (undef,$start,$start);
1096 }
1097 }
1098
1099 return ($parms,@queue);
1100 }
1101
1102
1103 sub _candidate_files {
1104 my $parms = shift;
1105 my $dir = shift;
1106
1107 my $dh;
1108 if ( !opendir $dh, $dir ) {
1109 $parms->{error_handler}->( "$dir: $!" );
1110 return;
1111 }
1112
1113 my @newfiles;
1114 my $descend_filter = $parms->{descend_filter};
1115 my $follow_symlinks = $parms->{follow_symlinks};
1116 my $sort_sub = $parms->{sort_files};
1117
1118 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
1119 my $has_stat;
1120
1121 # Only do directory checking if we have a descend_filter
1122 my $fullpath = File::Spec->catdir( $dir, $file );
1123 if ( !$follow_symlinks ) {
1124 next if -l $fullpath;
1125 $has_stat = 1;
1126 }
1127
1128 if ( $descend_filter ) {
1129 if ( $has_stat ? (-d _) : (-d $fullpath) ) {
1130 local $File::Next::dir = $fullpath;
1131 local $_ = $file;
1132 next if not $descend_filter->();
1133 }
1134 }
1135 if ( $sort_sub ) {
1136 push( @newfiles, [ $dir, $file, $fullpath ] );
1137 }
1138 else {
1139 push( @newfiles, $dir, $file, $fullpath );
1140 }
1141 }
1142 closedir $dh;
1143
1144 if ( $sort_sub ) {
1145 return map { @{$_} } sort $sort_sub @newfiles;
1146 }
1147
1148 return @newfiles;
1149 }
1150
1151
1152 1; # End of File::Next
1153 package App::Ack;
1154
1155 use warnings;
1156 use strict;
1157
1158
1159
1160
1161 our $VERSION;
1162 our $COPYRIGHT;
1163 BEGIN {
1164 $VERSION = '1.96';
1165 $COPYRIGHT = 'Copyright 2005-2011 Andy Lester.';
1166 }
1167
1168 our $fh;
1169
1170 BEGIN {
1171 $fh = *STDOUT;
1172 }
1173
1174
1175 our %types;
1176 our %type_wanted;
1177 our %mappings;
1178 our %ignore_dirs;
1179
1180 our $input_from_pipe;
1181 our $output_to_pipe;
1182
1183 our $dir_sep_chars;
1184 our $is_cygwin;
1185 our $is_windows;
1186
1187 use File::Spec ();
1188 use File::Glob ':glob';
1189 use Getopt::Long ();
1190
1191 BEGIN {
1192 %ignore_dirs = (
1193 '.bzr' => 'Bazaar',
1194 '.cdv' => 'Codeville',
1195 '~.dep' => 'Interface Builder',
1196 '~.dot' => 'Interface Builder',
1197 '~.nib' => 'Interface Builder',
1198 '~.plst' => 'Interface Builder',
1199 '.git' => 'Git',
1200 '.hg' => 'Mercurial',
1201 '.pc' => 'quilt',
1202 '.svn' => 'Subversion',
1203 _MTN => 'Monotone',
1204 blib => 'Perl module building',
1205 CVS => 'CVS',
1206 RCS => 'RCS',
1207 SCCS => 'SCCS',
1208 _darcs => 'darcs',
1209 _sgbak => 'Vault/Fortress',
1210 'autom4te.cache' => 'autoconf',
1211 'cover_db' => 'Devel::Cover',
1212 _build => 'Module::Build',
1213 );
1214
1215 %mappings = (
1216 actionscript => [qw( as mxml )],
1217 ada => [qw( ada adb ads )],
1218 asm => [qw( asm s )],
1219 batch => [qw( bat cmd )],
1220 binary => q{Binary files, as defined by Perl's -B op (default: off)},
1221 cc => [qw( c h xs )],
1222 cfmx => [qw( cfc cfm cfml )],
1223 clojure => [qw( clj )],
1224 cpp => [qw( cpp cc cxx m hpp hh h hxx )],
1225 csharp => [qw( cs )],
1226 css => [qw( css )],
1227 delphi => [qw( pas int dfm nfm dof dpk dproj groupproj bdsgroup bdsproj )],
1228 elisp => [qw( el )],
1229 erlang => [qw( erl hrl )],
1230 fortran => [qw( f f77 f90 f95 f03 for ftn fpp )],
1231 go => [qw( go )],
1232 groovy => [qw( groovy gtmpl gpp grunit )],
1233 haskell => [qw( hs lhs )],
1234 hh => [qw( h )],
1235 html => [qw( htm html shtml xhtml )],
1236 java => [qw( java properties )],
1237 js => [qw( js )],
1238 jsp => [qw( jsp jspx jhtm jhtml )],
1239 lisp => [qw( lisp lsp )],
1240 lua => [qw( lua )],
1241 make => q{Makefiles (including *.mk and *.mak)},
1242 mason => [qw( mas mhtml mpl mtxt )],
1243 objc => [qw( m h )],
1244 objcpp => [qw( mm h )],
1245 ocaml => [qw( ml mli )],
1246 parrot => [qw( pir pasm pmc ops pod pg tg )],
1247 perl => [qw( pl pm pm6 pod t )],
1248 php => [qw( php phpt php3 php4 php5 phtml)],
1249 plone => [qw( pt cpt metadata cpy py )],
1250 python => [qw( py )],
1251 rake => q{Rakefiles},
1252 ruby => [qw( rb rhtml rjs rxml erb rake spec )],
1253 scala => [qw( scala )],
1254 scheme => [qw( scm ss )],
1255 shell => [qw( sh bash csh tcsh ksh zsh )],
1256 skipped => q{Files, but not directories, normally skipped by ack (default: off)},
1257 smalltalk => [qw( st )],
1258 sql => [qw( sql ctl )],
1259 tcl => [qw( tcl itcl itk )],
1260 tex => [qw( tex cls sty )],
1261 text => q{Text files, as defined by Perl's -T op (default: off)},
1262 tt => [qw( tt tt2 ttml )],
1263 vb => [qw( bas cls frm ctl vb resx )],
1264 verilog => [qw( v vh sv )],
1265 vhdl => [qw( vhd vhdl )],
1266 vim => [qw( vim )],
1267 yaml => [qw( yaml yml )],
1268 xml => [qw( xml dtd xsl xslt ent )],
1269 );
1270
1271 while ( my ($type,$exts) = each %mappings ) {
1272 if ( ref $exts ) {
1273 for my $ext ( @{$exts} ) {
1274 push( @{$types{$ext}}, $type );
1275 }
1276 }
1277 }
1278 # add manually Makefile extensions
1279 push @{$types{$_}}, 'make' for qw{ mk mak };
1280
1281 # These have to be checked before any filehandle diddling.
1282 $output_to_pipe = not -t *STDOUT;
1283 $input_from_pipe = -p STDIN;
1284
1285 $is_cygwin = ($^O eq 'cygwin');
1286 $is_windows = ($^O =~ /MSWin32/);
1287 $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File::Spec->catfile( '', '' ) );
1288 }
1289
1290
1291 sub read_ackrc {
1292 my @files = ( $ENV{ACKRC} );
1293 my @dirs =
1294 $is_windows
1295 ? ( $ENV{HOME}, $ENV{USERPROFILE} )
1296 : ( '~', $ENV{HOME} );
1297 for my $dir ( grep { defined } @dirs ) {
1298 for my $file ( '.ackrc', '_ackrc' ) {
1299 push( @files, bsd_glob( "$dir/$file", GLOB_TILDE ) );
1300 }
1301 }
1302 for my $filename ( @files ) {
1303 if ( defined $filename && -e $filename ) {
1304 open( my $fh, '<', $filename ) or App::Ack::die( "$filename: $!\n" );
1305 my @lines = grep { /./ && !/^\s*#/ } <$fh>;
1306 chomp @lines;
1307 close $fh or App::Ack::die( "$filename: $!\n" );
1308
1309 # get rid of leading and trailing whitespaces
1310 for ( @lines ) {
1311 s/^\s+//;
1312 s/\s+$//;
1313 }
1314
1315 return @lines;
1316 }
1317 }
1318
1319 return;
1320 }
1321
1322
1323 sub get_command_line_options {
1324 my %opt = (
1325 pager => $ENV{ACK_PAGER_COLOR} || $ENV{ACK_PAGER},
1326 );
1327
1328 my $getopt_specs = {
1329 1 => sub { $opt{1} = $opt{m} = 1 },
1330 'A|after-context=i' => \$opt{after_context},
1331 'B|before-context=i' => \$opt{before_context},
1332 'C|context:i' => sub { shift; my $val = shift; $opt{before_context} = $opt{after_context} = ($val || 2) },
1333 'a|all-types' => \$opt{all},
1334 'break!' => \$opt{break},
1335 c => \$opt{count},
1336 'color|colour!' => \$opt{color},
1337 'color-match=s' => \$ENV{ACK_COLOR_MATCH},
1338 'color-filename=s' => \$ENV{ACK_COLOR_FILENAME},
1339 'color-lineno=s' => \$ENV{ACK_COLOR_LINENO},
1340 'column!' => \$opt{column},
1341 count => \$opt{count},
1342 'env!' => sub { }, # ignore this option, it is handled beforehand
1343 f => \$opt{f},
1344 flush => \$opt{flush},
1345 'follow!' => \$opt{follow},
1346 'g=s' => sub { shift; $opt{G} = shift; $opt{f} = 1 },
1347 'G=s' => \$opt{G},
1348 'group!' => sub { shift; $opt{heading} = $opt{break} = shift },
1349 'heading!' => \$opt{heading},
1350 'h|no-filename' => \$opt{h},
1351 'H|with-filename' => \$opt{H},
1352 'i|ignore-case' => \$opt{i},
1353 'invert-file-match' => \$opt{invert_file_match},
1354 'lines=s' => sub { shift; my $val = shift; push @{$opt{lines}}, $val },
1355 'l|files-with-matches' => \$opt{l},
1356 'L|files-without-matches' => sub { $opt{l} = $opt{v} = 1 },
1357 'm|max-count=i' => \$opt{m},
1358 'match=s' => \$opt{regex},
1359 'n|no-recurse' => \$opt{n},
1360 o => sub { $opt{output} = '$&' },
1361 'output=s' => \$opt{output},
1362 'pager=s' => \$opt{pager},
1363 'nopager' => sub { $opt{pager} = undef },
1364 'passthru' => \$opt{passthru},
1365 'print0' => \$opt{print0},
1366 'Q|literal' => \$opt{Q},
1367 'r|R|recurse' => sub { $opt{n} = 0 },
1368 'show-types' => \$opt{show_types},
1369 'smart-case!' => \$opt{smart_case},
1370 'sort-files' => \$opt{sort_files},
1371 'u|unrestricted' => \$opt{u},
1372 'v|invert-match' => \$opt{v},
1373 'w|word-regexp' => \$opt{w},
1374
1375 'ignore-dirs=s' => sub { shift; my $dir = remove_dir_sep( shift ); $ignore_dirs{$dir} = '--ignore-dirs' },
1376 'noignore-dirs=s' => sub { shift; my $dir = remove_dir_sep( shift ); delete $ignore_dirs{$dir} },
1377
1378 'version' => sub { print_version_statement(); exit; },
1379 'help|?:s' => sub { shift; show_help(@_); exit; },
1380 'help-types'=> sub { show_help_types(); exit; },
1381 'man' => sub {
1382 require Pod::Usage;
1383 Pod::Usage::pod2usage({
1384 -verbose => 2,
1385 -exitval => 0,
1386 });
1387 },
1388
1389 'type=s' => sub {
1390 # Whatever --type=xxx they specify, set it manually in the hash
1391 my $dummy = shift;
1392 my $type = shift;
1393 my $wanted = ($type =~ s/^no//) ? 0 : 1; # must not be undef later
1394
1395 if ( exists $type_wanted{ $type } ) {
1396 $type_wanted{ $type } = $wanted;
1397 }
1398 else {
1399 App::Ack::die( qq{Unknown --type "$type"} );
1400 }
1401 }, # type sub
1402 };
1403
1404 # Stick any default switches at the beginning, so they can be overridden
1405 # by the command line switches.
1406 unshift @ARGV, split( ' ', $ENV{ACK_OPTIONS} ) if defined $ENV{ACK_OPTIONS};
1407
1408 # first pass through options, looking for type definitions
1409 def_types_from_ARGV();
1410
1411 for my $i ( filetypes_supported() ) {
1412 $getopt_specs->{ "$i!" } = \$type_wanted{ $i };
1413 }
1414
1415
1416 my $parser = Getopt::Long::Parser->new();
1417 $parser->configure( 'bundling', 'no_ignore_case', );
1418 $parser->getoptions( %{$getopt_specs} ) or
1419 App::Ack::die( 'See ack --help, ack --help-types or ack --man for options.' );
1420
1421 my $to_screen = not output_to_pipe();
1422 my %defaults = (
1423 all => 0,
1424 color => $to_screen,
1425 follow => 0,
1426 break => $to_screen,
1427 heading => $to_screen,
1428 before_context => 0,
1429 after_context => 0,
1430 );
1431 if ( $is_windows && $defaults{color} && not $ENV{ACK_PAGER_COLOR} ) {
1432 if ( $ENV{ACK_PAGER} || not eval { require Win32::Console::ANSI } ) {
1433 $defaults{color} = 0;
1434 }
1435 }
1436 if ( $to_screen && $ENV{ACK_PAGER_COLOR} ) {
1437 $defaults{color} = 1;
1438 }
1439
1440 while ( my ($key,$value) = each %defaults ) {
1441 if ( not defined $opt{$key} ) {
1442 $opt{$key} = $value;
1443 }
1444 }
1445
1446 if ( defined $opt{m} && $opt{m} <= 0 ) {
1447 App::Ack::die( '-m must be greater than zero' );
1448 }
1449
1450 for ( qw( before_context after_context ) ) {
1451 if ( defined $opt{$_} && $opt{$_} < 0 ) {
1452 App::Ack::die( "--$_ may not be negative" );
1453 }
1454 }
1455
1456 if ( defined( my $val = $opt{output} ) ) {
1457 $opt{output} = eval qq[ sub { "$val" } ];
1458 }
1459 if ( defined( my $l = $opt{lines} ) ) {
1460 # --line=1 --line=5 is equivalent to --line=1,5
1461 my @lines = split( /,/, join( ',', @{$l} ) );
1462
1463 # --line=1-3 is equivalent to --line=1,2,3
1464 @lines = map {
1465 my @ret;
1466 if ( /-/ ) {
1467 my ($from, $to) = split /-/, $_;
1468 if ( $from > $to ) {
1469 App::Ack::warn( "ignoring --line=$from-$to" );
1470 @ret = ();
1471 }
1472 else {
1473 @ret = ( $from .. $to );
1474 }
1475 }
1476 else {
1477 @ret = ( $_ );
1478 };
1479 @ret
1480 } @lines;
1481
1482 if ( @lines ) {
1483 my %uniq;
1484 @uniq{ @lines } = ();
1485 $opt{lines} = [ sort { $a <=> $b } keys %uniq ]; # numerical sort and each line occurs only once!
1486 }
1487 else {
1488 # happens if there are only ignored --line directives
1489 App::Ack::die( 'All --line options are invalid.' );
1490 }
1491 }
1492
1493 return \%opt;
1494 }
1495
1496
1497 sub def_types_from_ARGV {
1498 my @typedef;
1499
1500 my $parser = Getopt::Long::Parser->new();
1501 # pass_through => leave unrecognized command line arguments alone
1502 # no_auto_abbrev => otherwise -c is expanded and not left alone
1503 $parser->configure( 'no_ignore_case', 'pass_through', 'no_auto_abbrev' );
1504 $parser->getoptions(
1505 'type-set=s' => sub { shift; push @typedef, ['c', shift] },
1506 'type-add=s' => sub { shift; push @typedef, ['a', shift] },
1507 ) or App::Ack::die( 'See ack --help or ack --man for options.' );
1508
1509 for my $td (@typedef) {
1510 my ($type, $ext) = split /=/, $td->[1];
1511
1512 if ( $td->[0] eq 'c' ) {
1513 # type-set
1514 if ( exists $mappings{$type} ) {
1515 # can't redefine types 'make', 'skipped', 'text' and 'binary'
1516 App::Ack::die( qq{--type-set: Builtin type "$type" cannot be changed.} )
1517 if ref $mappings{$type} ne 'ARRAY';
1518
1519 delete_type($type);
1520 }
1521 }
1522 else {
1523 # type-add
1524
1525 # can't append to types 'make', 'skipped', 'text' and 'binary'
1526 App::Ack::die( qq{--type-add: Builtin type "$type" cannot be changed.} )
1527 if exists $mappings{$type} && ref $mappings{$type} ne 'ARRAY';
1528
1529 App::Ack::warn( qq{--type-add: Type "$type" does not exist, creating with "$ext" ...} )
1530 unless exists $mappings{$type};
1531 }
1532
1533 my @exts = split /,/, $ext;
1534 s/^\.// for @exts;
1535
1536 if ( !exists $mappings{$type} || ref($mappings{$type}) eq 'ARRAY' ) {
1537 push @{$mappings{$type}}, @exts;
1538 for my $e ( @exts ) {
1539 push @{$types{$e}}, $type;
1540 }
1541 }
1542 else {
1543 App::Ack::die( qq{Cannot append to type "$type".} );
1544 }
1545 }
1546
1547 return;
1548 }
1549
1550
1551 sub delete_type {
1552 my $type = shift;
1553
1554 App::Ack::die( qq{Internal error: Cannot delete builtin type "$type".} )
1555 unless ref $mappings{$type} eq 'ARRAY';
1556
1557 delete $mappings{$type};
1558 delete $type_wanted{$type};
1559 for my $ext ( keys %types ) {
1560 $types{$ext} = [ grep { $_ ne $type } @{$types{$ext}} ];
1561 }
1562 }
1563
1564
1565 sub ignoredir_filter {
1566 return !exists $ignore_dirs{$_} && !exists $ignore_dirs{$File::Next::dir};
1567 }
1568
1569
1570 sub remove_dir_sep {
1571 my $path = shift;
1572 $path =~ s/[$dir_sep_chars]$//;
1573
1574 return $path;
1575 }
1576
1577
1578 use constant TEXT => 'text';
1579
1580 sub filetypes {
1581 my $filename = shift;
1582
1583 my $basename = $filename;
1584 $basename =~ s{.*[$dir_sep_chars]}{};
1585
1586 return 'skipped' unless is_searchable( $basename );
1587
1588 my $lc_basename = lc $basename;
1589 return ('make',TEXT) if $lc_basename eq 'makefile' || $lc_basename eq 'gnumakefile';
1590 return ('rake','ruby',TEXT) if $lc_basename eq 'rakefile';
1591
1592 # If there's an extension, look it up
1593 if ( $filename =~ m{\.([^\.$dir_sep_chars]+)$}o ) {
1594 my $ref = $types{lc $1};
1595 return (@{$ref},TEXT) if $ref;
1596 }
1597
1598 # At this point, we can't tell from just the name. Now we have to
1599 # open it and look inside.
1600
1601 return unless -e $filename;
1602 # From Elliot Shank:
1603 # I can't see any reason that -r would fail on these-- the ACLs look
1604 # fine, and no program has any of them open, so the busted Windows
1605 # file locking model isn't getting in there. If I comment the if
1606 # statement out, everything works fine
1607 # So, for cygwin, don't bother trying to check for readability.
1608 if ( !$is_cygwin ) {
1609 if ( !-r $filename ) {
1610 App::Ack::warn( "$filename: Permission denied" );
1611 return;
1612 }
1613 }
1614
1615 return 'binary' if -B $filename;
1616
1617 # If there's no extension, or we don't recognize it, check the shebang line
1618 my $fh;
1619 if ( !open( $fh, '<', $filename ) ) {
1620 App::Ack::warn( "$filename: $!" );
1621 return;
1622 }
1623 my $header = <$fh>;
1624 close $fh;
1625
1626 if ( $header =~ /^#!/ ) {
1627 return ($1,TEXT) if $header =~ /\b(ruby|lua|p(?:erl|hp|ython))-?(\d[\d.]*)?\b/;
1628 return ('shell',TEXT) if $header =~ /\b(?:ba|t?c|k|z)?sh\b/;
1629 }
1630 else {
1631 return ('xml',TEXT) if $header =~ /\Q<?xml /i;
1632 }
1633
1634 return (TEXT);
1635 }
1636
1637
1638 sub is_searchable {
1639 my $filename = shift;
1640
1641 # If these are updated, update the --help message
1642 return if $filename =~ /[.]bak$/;
1643 return if $filename =~ /~$/;
1644 return if $filename =~ m{^#.*#$}o;
1645 return if $filename =~ m{^core\.\d+$}o;
1646 return if $filename =~ m{[._].*\.swp$}o;
1647 return if $filename =~ /[.-]min\.js$/;
1648
1649 return 1;
1650 }
1651
1652
1653 sub build_regex {
1654 my $str = shift;
1655 my $opt = shift;
1656
1657 defined $str or App::Ack::die( 'No regular expression found.' );
1658
1659 $str = quotemeta( $str ) if $opt->{Q};
1660 if ( $opt->{w} ) {
1661 $str = "\\b$str" if $str =~ /^\w/;
1662 $str = "$str\\b" if $str =~ /\w$/;
1663 }
1664
1665 my $regex_is_lc = $str eq lc $str;
1666 if ( $opt->{i} || ($opt->{smart_case} && $regex_is_lc) ) {
1667 $str = "(?i)$str";
1668 }
1669
1670 return $str;
1671 }
1672
1673
1674 sub check_regex {
1675 my $regex = shift;
1676
1677 return unless defined $regex;
1678
1679 eval { qr/$regex/ };
1680 if ($@) {
1681 (my $error = $@) =~ s/ at \S+ line \d+.*//;
1682 chomp($error);
1683 App::Ack::die( "Invalid regex '$regex':\n $error" );
1684 }
1685
1686 return;
1687 }
1688
1689
1690
1691
1692 sub warn {
1693 return CORE::warn( _my_program(), ': ', @_, "\n" );
1694 }
1695
1696
1697 sub die {
1698 return CORE::die( _my_program(), ': ', @_, "\n" );
1699 }
1700
1701 sub _my_program {
1702 require File::Basename;
1703 return File::Basename::basename( $0 );
1704 }
1705
1706
1707
1708 sub filetypes_supported {
1709 return keys %mappings;
1710 }
1711
1712 sub _get_thpppt {
1713 my $y = q{_ /|,\\'!.x',=(www)=, U };
1714 $y =~ tr/,x!w/\nOo_/;
1715 return $y;
1716 }
1717
1718 sub _thpppt {
1719 my $y = _get_thpppt();
1720 App::Ack::print( "$y ack $_[0]!\n" );
1721 exit 0;
1722 }
1723
1724 sub _key {
1725 my $str = lc shift;
1726 $str =~ s/[^a-z]//g;
1727
1728 return $str;
1729 }
1730
1731
1732 sub show_help {
1733 my $help_arg = shift || 0;
1734
1735 return show_help_types() if $help_arg =~ /^types?/;
1736
1737 my $ignore_dirs = _listify( sort { _key($a) cmp _key($b) } keys %ignore_dirs );
1738
1739 App::Ack::print( <<"END_OF_HELP" );
1740 Usage: ack [OPTION]... PATTERN [FILE]
1741
1742 Search for PATTERN in each source file in the tree from cwd on down.
1743 If [FILES] is specified, then only those files/directories are checked.
1744 ack may also search STDIN, but only if no FILE are specified, or if
1745 one of FILES is "-".
1746
1747 Default switches may be specified in ACK_OPTIONS environment variable or
1748 an .ackrc file. If you want no dependency on the environment, turn it
1749 off with --noenv.
1750
1751 Example: ack -i select
1752
1753 Searching:
1754 -i, --ignore-case Ignore case distinctions in PATTERN
1755 --[no]smart-case Ignore case distinctions in PATTERN,
1756 only if PATTERN contains no upper case
1757 Ignored if -i is specified
1758 -v, --invert-match Invert match: select non-matching lines
1759 -w, --word-regexp Force PATTERN to match only whole words
1760 -Q, --literal Quote all metacharacters; PATTERN is literal
1761
1762 Search output:
1763 --line=NUM Only print line(s) NUM of each file
1764 -l, --files-with-matches
1765 Only print filenames containing matches
1766 -L, --files-without-matches
1767 Only print filenames with no matches
1768 -o Show only the part of a line matching PATTERN
1769 (turns off text highlighting)
1770 --passthru Print all lines, whether matching or not
1771 --output=expr Output the evaluation of expr for each line
1772 (turns off text highlighting)
1773 --match PATTERN Specify PATTERN explicitly.
1774 -m, --max-count=NUM Stop searching in each file after NUM matches
1775 -1 Stop searching after one match of any kind
1776 -H, --with-filename Print the filename for each match
1777 -h, --no-filename Suppress the prefixing filename on output
1778 -c, --count Show number of lines matching per file
1779 --column Show the column number of the first match
1780
1781 -A NUM, --after-context=NUM
1782 Print NUM lines of trailing context after matching
1783 lines.
1784 -B NUM, --before-context=NUM
1785 Print NUM lines of leading context before matching
1786 lines.
1787 -C [NUM], --context[=NUM]
1788 Print NUM lines (default 2) of output context.
1789
1790 --print0 Print null byte as separator between filenames,
1791 only works with -f, -g, -l, -L or -c.
1792
1793 File presentation:
1794 --pager=COMMAND Pipes all ack output through COMMAND. For example,
1795 --pager="less -R". Ignored if output is redirected.
1796 --nopager Do not send output through a pager. Cancels any
1797 setting in ~/.ackrc, ACK_PAGER or ACK_PAGER_COLOR.
1798 --[no]heading Print a filename heading above each file's results.
1799 (default: on when used interactively)
1800 --[no]break Print a break between results from different files.
1801 (default: on when used interactively)
1802 --group Same as --heading --break
1803 --nogroup Same as --noheading --nobreak
1804 --[no]color Highlight the matching text (default: on unless
1805 output is redirected, or on Windows)
1806 --[no]colour Same as --[no]color
1807 --color-filename=COLOR
1808 --color-match=COLOR
1809 --color-lineno=COLOR Set the color for filenames, matches, and line numbers.
1810 --flush Flush output immediately, even when ack is used
1811 non-interactively (when output goes to a pipe or
1812 file).
1813
1814 File finding:
1815 -f Only print the files found, without searching.
1816 The PATTERN must not be specified.
1817 -g REGEX Same as -f, but only print files matching REGEX.
1818 --sort-files Sort the found files lexically.
1819 --invert-file-match Print/search handle files that do not match -g/-G.
1820 --show-types Show which types each file has.
1821
1822 File inclusion/exclusion:
1823 -a, --all-types All file types searched;
1824 Ignores CVS, .svn and other ignored directories
1825 -u, --unrestricted All files and directories searched
1826 --[no]ignore-dir=name Add/Remove directory from the list of ignored dirs
1827 -r, -R, --recurse Recurse into subdirectories (ack's default behavior)
1828 -n, --no-recurse No descending into subdirectories
1829 -G REGEX Only search files that match REGEX
1830
1831 --perl Include only Perl files.
1832 --type=perl Include only Perl files.
1833 --noperl Exclude Perl files.
1834 --type=noperl Exclude Perl files.
1835 See "ack --help type" for supported filetypes.
1836
1837 --type-set TYPE=.EXTENSION[,.EXT2[,...]]
1838 Files with the given EXTENSION(s) are recognized as
1839 being of type TYPE. This replaces an existing
1840 definition for type TYPE.
1841 --type-add TYPE=.EXTENSION[,.EXT2[,...]]
1842 Files with the given EXTENSION(s) are recognized as
1843 being of (the existing) type TYPE
1844
1845 --[no]follow Follow symlinks. Default is off.
1846
1847 Directories ignored by default:
1848 $ignore_dirs
1849
1850 Files not checked for type:
1851 /~\$/ - Unix backup files
1852 /#.+#\$/ - Emacs swap files
1853 /[._].*\\.swp\$/ - Vi(m) swap files
1854 /core\\.\\d+\$/ - core dumps
1855 /[.-]min\\.js\$/ - Minified javascript files
1856
1857 Miscellaneous:
1858 --noenv Ignore environment variables and ~/.ackrc
1859 --help This help
1860 --man Man page
1861 --version Display version & copyright
1862 --thpppt Bill the Cat
1863
1864 Exit status is 0 if match, 1 if no match.
1865
1866 This is version $VERSION of ack.
1867 END_OF_HELP
1868
1869 return;
1870 }
1871
1872
1873
1874 sub show_help_types {
1875 App::Ack::print( <<'END_OF_HELP' );
1876 Usage: ack [OPTION]... PATTERN [FILES]
1877
1878 The following is the list of filetypes supported by ack. You can
1879 specify a file type with the --type=TYPE format, or the --TYPE
1880 format. For example, both --type=perl and --perl work.
1881
1882 Note that some extensions may appear in multiple types. For example,
1883 .pod files are both Perl and Parrot.
1884
1885 END_OF_HELP
1886
1887 my @types = filetypes_supported();
1888 my $maxlen = 0;
1889 for ( @types ) {
1890 $maxlen = length if $maxlen < length;
1891 }
1892 for my $type ( sort @types ) {
1893 next if $type =~ /^-/; # Stuff to not show
1894 my $ext_list = $mappings{$type};
1895
1896 if ( ref $ext_list ) {
1897 $ext_list = join( ' ', map { ".$_" } @{$ext_list} );
1898 }
1899 App::Ack::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
1900 }
1901
1902 return;
1903 }
1904
1905 sub _listify {
1906 my @whats = @_;
1907
1908 return '' if !@whats;
1909
1910 my $end = pop @whats;
1911 my $str = @whats ? join( ', ', @whats ) . " and $end" : $end;
1912
1913 no warnings 'once';
1914 require Text::Wrap;
1915 $Text::Wrap::columns = 75;
1916 return Text::Wrap::wrap( '', ' ', $str );
1917 }
1918
1919
1920 sub get_version_statement {
1921 require Config;
1922
1923 my $copyright = get_copyright();
1924 my $this_perl = $Config::Config{perlpath};
1925 if ($^O ne 'VMS') {
1926 my $ext = $Config::Config{_exe};
1927 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
1928 }
1929 my $ver = sprintf( '%vd', $^V );
1930
1931 return <<"END_OF_VERSION";
1932 ack $VERSION
1933 Running under Perl $ver at $this_perl
1934
1935 $copyright
1936
1937 This program is free software. You may modify or distribute it
1938 under the terms of the Artistic License v2.0.
1939 END_OF_VERSION
1940 }
1941
1942
1943 sub print_version_statement {
1944 App::Ack::print( get_version_statement() );
1945
1946 return;
1947 }
1948
1949
1950 sub get_copyright {
1951 return $COPYRIGHT;
1952 }
1953
1954
1955 sub load_colors {
1956 eval 'use Term::ANSIColor ()';
1957
1958 $ENV{ACK_COLOR_MATCH} ||= 'black on_yellow';
1959 $ENV{ACK_COLOR_FILENAME} ||= 'bold green';
1960 $ENV{ACK_COLOR_LINENO} ||= 'bold yellow';
1961
1962 return;
1963 }
1964
1965
1966 sub is_interesting {
1967 return if /^\./;
1968
1969 my $include;
1970
1971 for my $type ( filetypes( $File::Next::name ) ) {
1972 if ( defined $type_wanted{$type} ) {
1973 if ( $type_wanted{$type} ) {
1974 $include = 1;
1975 }
1976 else {
1977 return;
1978 }
1979 }
1980 }
1981
1982 return $include;
1983 }
1984
1985
1986
1987 # print subs added in order to make it easy for a third party
1988 # module (such as App::Wack) to redefine the display methods
1989 # and show the results in a different way.
1990 sub print { print {$fh} @_ }
1991 sub print_first_filename { App::Ack::print( $_[0], "\n" ) }
1992 sub print_blank_line { App::Ack::print( "\n" ) }
1993 sub print_separator { App::Ack::print( "--\n" ) }
1994 sub print_filename { App::Ack::print( $_[0], $_[1] ) }
1995 sub print_line_no { App::Ack::print( $_[0], $_[1] ) }
1996 sub print_column_no { App::Ack::print( $_[0], $_[1] ) }
1997 sub print_count {
1998 my $filename = shift;
1999 my $nmatches = shift;
2000 my $ors = shift;
2001 my $count = shift;
2002 my $show_filename = shift;
2003
2004 if ($show_filename) {
2005 App::Ack::print( $filename );
2006 App::Ack::print( ':', $nmatches ) if $count;
2007 }
2008 else {
2009 App::Ack::print( $nmatches ) if $count;
2010 }
2011 App::Ack::print( $ors );
2012 }
2013
2014 sub print_count0 {
2015 my $filename = shift;
2016 my $ors = shift;
2017 my $show_filename = shift;
2018
2019 if ($show_filename) {
2020 App::Ack::print( $filename, ':0', $ors );
2021 }
2022 else {
2023 App::Ack::print( '0', $ors );
2024 }
2025 }
2026
2027
2028
2029 {
2030 my $filename;
2031 my $regex;
2032 my $display_filename;
2033
2034 my $keep_context;
2035
2036 my $last_output_line; # number of the last line that has been output
2037 my $any_output; # has there been any output for the current file yet
2038 my $context_overall_output_count; # has there been any output at all
2039
2040 sub search_resource {
2041 my $res = shift;
2042 my $opt = shift;
2043
2044 $filename = $res->name();
2045
2046 my $v = $opt->{v};
2047 my $passthru = $opt->{passthru};
2048 my $max = $opt->{m};
2049 my $nmatches = 0;
2050
2051 $display_filename = undef;
2052
2053 # for --line processing
2054 my $has_lines = 0;
2055 my @lines;
2056 if ( defined $opt->{lines} ) {
2057 $has_lines = 1;
2058 @lines = ( @{$opt->{lines}}, -1 );
2059 undef $regex; # Don't match when printing matching line
2060 }
2061 else {
2062 $regex = qr/$opt->{regex}/;
2063 }
2064
2065 # for context processing
2066 $last_output_line = -1;
2067 $any_output = 0;
2068 my $before_context = $opt->{before_context};
2069 my $after_context = $opt->{after_context};
2070
2071 $keep_context = ($before_context || $after_context) && !$passthru;
2072
2073 my @before;
2074 my $before_starts_at_line;
2075 my $after = 0; # number of lines still to print after a match
2076
2077 while ( $res->next_text ) {
2078 # XXX Optimize away the case when there are no more @lines to find.
2079 # XXX $has_lines, $passthru and $v never change. Optimize.
2080 if ( $has_lines
2081 ? $. != $lines[0] # $lines[0] should be a scalar
2082 : $v ? m/$regex/ : !m/$regex/ ) {
2083 if ( $passthru ) {
2084 App::Ack::print( $_ );
2085 next;
2086 }
2087
2088 if ( $keep_context ) {
2089 if ( $after ) {
2090 print_match_or_context( $opt, 0, $., $-[0], $+[0], $_ );
2091 $after--;
2092 }
2093 elsif ( $before_context ) {
2094 if ( @before ) {
2095 if ( @before >= $before_context ) {
2096 shift @before;
2097 ++$before_starts_at_line;
2098 }
2099 }
2100 else {
2101 $before_starts_at_line = $.;
2102 }
2103 push @before, $_;
2104 }
2105 last if $max && ( $nmatches >= $max ) && !$after;
2106 }
2107 next;
2108 } # not a match
2109
2110 ++$nmatches;
2111
2112 # print an empty line as a divider before first line in each file (not before the first file)
2113 if ( !$any_output && $opt->{show_filename} && $opt->{break} && defined( $context_overall_output_count ) ) {
2114 App::Ack::print_blank_line();
2115 }
2116
2117 shift @lines if $has_lines;
2118
2119 if ( $res->is_binary ) {
2120 App::Ack::print( "Binary file $filename matches\n" );
2121 last;
2122 }
2123 if ( $keep_context ) {
2124 if ( @before ) {
2125 print_match_or_context( $opt, 0, $before_starts_at_line, $-[0], $+[0], @before );
2126 @before = ();
2127 $before_starts_at_line = 0;
2128 }
2129 if ( $max && $nmatches > $max ) {
2130 --$after;
2131 }
2132 else {
2133 $after = $after_context;
2134 }
2135 }
2136 print_match_or_context( $opt, 1, $., $-[0], $+[0], $_ );
2137
2138 last if $max && ( $nmatches >= $max ) && !$after;
2139 } # while
2140
2141 return $nmatches;
2142 } # search_resource()
2143
2144
2145
2146 sub print_match_or_context {
2147 my $opt = shift; # opts array
2148 my $is_match = shift; # is there a match on the line?
2149 my $line_no = shift;
2150 my $match_start = shift;
2151 my $match_end = shift;
2152
2153 my $color = $opt->{color};
2154 my $heading = $opt->{heading};
2155 my $show_filename = $opt->{show_filename};
2156 my $show_column = $opt->{column};
2157
2158 if ( $show_filename ) {
2159 if ( not defined $display_filename ) {
2160 $display_filename =
2161 $color
2162 ? Term::ANSIColor::colored( $filename, $ENV{ACK_COLOR_FILENAME} )
2163 : $filename;
2164 if ( $heading && !$any_output ) {
2165 App::Ack::print_first_filename($display_filename);
2166 }
2167 }
2168 }
2169
2170 my $sep = $is_match ? ':' : '-';
2171 my $output_func = $opt->{output};
2172 for ( @_ ) {
2173 if ( $keep_context && !$output_func ) {
2174 if ( ( $last_output_line != $line_no - 1 ) &&
2175 ( $any_output || ( !$heading && defined( $context_overall_output_count ) ) ) ) {
2176 App::Ack::print_separator();
2177 }
2178 # to ensure separators between different files when --noheading
2179
2180 $last_output_line = $line_no;
2181 }
2182
2183 if ( $show_filename ) {
2184 App::Ack::print_filename($display_filename, $sep) if not $heading;
2185 my $display_line_no =
2186 $color
2187 ? Term::ANSIColor::colored( $line_no, $ENV{ACK_COLOR_LINENO} )
2188 : $line_no;
2189 App::Ack::print_line_no($display_line_no, $sep);
2190 }
2191
2192 if ( $output_func ) {
2193 while ( /$regex/go ) {
2194 App::Ack::print( $output_func->() . "\n" );
2195 }
2196 }
2197 else {
2198 if ( $color && $is_match && $regex &&
2199 s/$regex/Term::ANSIColor::colored( substr($_, $-[0], $+[0] - $-[0]), $ENV{ACK_COLOR_MATCH} )/eg ) {
2200 # At the end of the line reset the color and remove newline
2201 s/[\r\n]*\z/\e[0m\e[K/;
2202 }
2203 else {
2204 # remove any kind of newline at the end of the line
2205 s/[\r\n]*\z//;
2206 }
2207 if ( $show_column ) {
2208 App::Ack::print_column_no( $match_start+1, $sep );
2209 }
2210 App::Ack::print($_ . "\n");
2211 }
2212 $any_output = 1;
2213 ++$context_overall_output_count;
2214 ++$line_no;
2215 }
2216
2217 return;
2218 } # print_match_or_context()
2219
2220 } # scope around search_resource() and print_match_or_context()
2221
2222
2223 TOTAL_COUNT_SCOPE: {
2224 my $total_count;
2225
2226 sub get_total_count {
2227 return $total_count;
2228 }
2229
2230 sub reset_total_count {
2231 $total_count = 0;
2232 }
2233
2234
2235 sub search_and_list {
2236 my $res = shift;
2237 my $opt = shift;
2238
2239 my $nmatches = 0;
2240 my $count = $opt->{count};
2241 my $ors = $opt->{print0} ? "\0" : "\n"; # output record separator
2242 my $show_filename = $opt->{show_filename};
2243
2244 my $regex = qr/$opt->{regex}/;
2245
2246 if ( $opt->{v} ) {
2247 while ( $res->next_text ) {
2248 if ( /$regex/ ) {
2249 return 0 unless $count;
2250 }
2251 else {
2252 ++$nmatches;
2253 }
2254 }
2255 }
2256 else {
2257 while ( $res->next_text ) {
2258 if ( /$regex/ ) {
2259 ++$nmatches;
2260 last unless $count;
2261 }
2262 }
2263 }
2264
2265 if ( $opt->{show_total} ) {
2266 $total_count += $nmatches;
2267 }
2268 else {
2269 if ( $nmatches ) {
2270 App::Ack::print_count( $res->name, $nmatches, $ors, $count, $show_filename );
2271 }
2272 elsif ( $count && !$opt->{l} ) {
2273 App::Ack::print_count0( $res->name, $ors, $show_filename );
2274 }
2275 }
2276
2277 return $nmatches ? 1 : 0;
2278 } # search_and_list()
2279
2280 } # scope around $total_count
2281
2282
2283
2284 sub filetypes_supported_set {
2285 return grep { defined $type_wanted{$_} && ($type_wanted{$_} == 1) } filetypes_supported();
2286 }
2287
2288
2289
2290 sub print_files {
2291 my $iter = shift;
2292 my $opt = shift;
2293
2294 my $ors = $opt->{print0} ? "\0" : "\n";
2295
2296 my $nmatches = 0;
2297 while ( defined ( my $file = $iter->() ) ) {
2298 App::Ack::print $file, $opt->{show_types} ? " => " . join( ',', filetypes( $file ) ) : (), $ors;
2299 $nmatches++;
2300 last if $opt->{1};
2301 }
2302
2303 return $nmatches;
2304 }
2305
2306
2307 sub print_files_with_matches {
2308 my $iter = shift;
2309 my $opt = shift;
2310
2311 # if we have -l and only 1 file given on command line (this means
2312 # show_filename is set to 0), we want to see the filename nevertheless
2313 $opt->{show_filename} = 1 if $opt->{l};
2314
2315 $opt->{show_filename} = 0 if $opt->{h};
2316 $opt->{show_filename} = 1 if $opt->{H};
2317
2318 # abuse options to hand in the show_total parameter to search_and_list
2319 $opt->{show_total} = $opt->{count} && !$opt->{show_filename};
2320 reset_total_count();
2321
2322 my $nmatches = 0;
2323 while ( defined ( my $filename = $iter->() ) ) {
2324 my $repo = App::Ack::Repository::Basic->new( $filename );
2325 my $res;
2326 while ( $res = $repo->next_resource() ) {
2327 $nmatches += search_and_list( $res, $opt );
2328 $res->close();
2329 last if $nmatches && $opt->{1};
2330 }
2331 $repo->close();
2332 }
2333
2334 if ( $nmatches && $opt->{show_total} ) {
2335 App::Ack::print_count('', get_total_count(), "\n", 1, 0 )
2336 }
2337
2338 return $nmatches;
2339 }
2340
2341
2342 sub print_matches {
2343 my $iter = shift;
2344 my $opt = shift;
2345
2346 $opt->{show_filename} = 0 if $opt->{h};
2347 $opt->{show_filename} = 1 if $opt->{H};
2348
2349 my $nmatches = 0;
2350 while ( defined ( my $filename = $iter->() ) ) {
2351 my $repo;
2352 my $tarballs_work = 0;
2353 if ( $tarballs_work && $filename =~ /\.tar\.gz$/ ) {
2354 App::Ack::die( 'Not working here yet' );
2355 require App::Ack::Repository::Tar; # XXX Error checking
2356 $repo = App::Ack::Repository::Tar->new( $filename );
2357 }
2358 else {
2359 $repo = App::Ack::Repository::Basic->new( $filename );
2360 }
2361 $repo or next;
2362
2363 while ( my $res = $repo->next_resource() ) {
2364 my $needs_line_scan;
2365 if ( $opt->{regex} && !$opt->{passthru} ) {
2366 $needs_line_scan = $res->needs_line_scan( $opt );
2367 if ( $needs_line_scan ) {
2368 $res->reset();
2369 }
2370 }
2371 else {
2372 $needs_line_scan = 1;
2373 }
2374 if ( $needs_line_scan ) {
2375 $nmatches += search_resource( $res, $opt );
2376 }
2377 $res->close();
2378 }
2379 last if $nmatches && $opt->{1};
2380 $repo->close();
2381 }
2382 return $nmatches;
2383 }
2384
2385
2386 sub filetype_setup {
2387 my $filetypes_supported_set = filetypes_supported_set();
2388 # If anyone says --no-whatever, we assume all other types must be on.
2389 if ( !$filetypes_supported_set ) {
2390 for my $i ( keys %type_wanted ) {
2391 $type_wanted{$i} = 1 unless ( defined( $type_wanted{$i} ) || $i eq 'binary' || $i eq 'text' || $i eq 'skipped' );
2392 }
2393 }
2394 return;
2395 }
2396
2397
2398 EXPAND_FILENAMES_SCOPE: {
2399 my $filter;
2400
2401 sub expand_filenames {
2402 my $argv = shift;
2403
2404 my $attr;
2405 my @files;
2406
2407 foreach my $pattern ( @{$argv} ) {
2408 my @results = bsd_glob( $pattern );
2409
2410 if (@results == 0) {
2411 @results = $pattern; # Glob didn't match, pass it thru unchanged
2412 }
2413 elsif ( (@results > 1) or ($results[0] ne $pattern) ) {
2414 if (not defined $filter) {
2415 eval 'require Win32::File;';
2416 if ($@) {
2417 $filter = 0;
2418 }
2419 else {
2420 $filter = Win32::File::HIDDEN()|Win32::File::SYSTEM();
2421 }
2422 } # end unless we've tried to load Win32::File
2423 if ( $filter ) {
2424 # Filter out hidden and system files:
2425 @results = grep { not(Win32::File::GetAttributes($_, $attr) and $attr & $filter) } @results;
2426 App::Ack::warn( "$pattern: Matched only hidden files" ) unless @results;
2427 } # end if we can filter by file attributes
2428 } # end elsif this pattern got expanded
2429
2430 push @files, @results;
2431 } # end foreach pattern
2432
2433 return \@files;
2434 } # end expand_filenames
2435 } # EXPAND_FILENAMES_SCOPE
2436
2437
2438
2439 sub get_starting_points {
2440 my $argv = shift;
2441 my $opt = shift;
2442
2443 my @what;
2444
2445 if ( @{$argv} ) {
2446 @what = @{ $is_windows ? expand_filenames($argv) : $argv };
2447 $_ = File::Next::reslash( $_ ) for @what;
2448
2449 # Show filenames unless we've specified one single file
2450 $opt->{show_filename} = (@what > 1) || (!-f $what[0]);
2451 }
2452 else {
2453 @what = '.'; # Assume current directory
2454 $opt->{show_filename} = 1;
2455 }
2456
2457 for my $start_point (@what) {
2458 App::Ack::warn( "$start_point: No such file or directory" ) unless -e $start_point;
2459 }
2460 return \@what;
2461 }
2462
2463 sub _match {
2464 my ( $target, $expression, $invert_flag ) = @_;
2465
2466 if ( $invert_flag ) {
2467 return $target !~ $expression;
2468 }
2469 else {
2470 return $target =~ $expression;
2471 }
2472 }
2473
2474
2475 sub get_iterator {
2476 my $what = shift;
2477 my $opt = shift;
2478
2479 # Starting points are always searched, no matter what
2480 my %starting_point = map { ($_ => 1) } @{$what};
2481
2482 my $g_regex = defined $opt->{G} ? qr/$opt->{G}/ : undef;
2483 my $file_filter;
2484
2485 if ( $g_regex ) {
2486 $file_filter
2487 = $opt->{u} ? sub { _match( $File::Next::name, qr/$g_regex/, $opt->{invert_file_match} ) } # XXX Maybe this should be a 1, no?
2488 : $opt->{all} ? sub { $starting_point{ $File::Next::name } || ( _match( $File::Next::name, qr/$g_regex/, $opt->{invert_file_match} ) && is_searchable( $_ ) ) }
2489 : sub { $starting_point{ $File::Next::name } || ( _match( $File::Next::name, qr/$g_regex/, $opt->{invert_file_match} ) && is_interesting( @ _) ) }
2490 ;
2491 }
2492 else {
2493 $file_filter
2494 = $opt->{u} ? sub {1}
2495 : $opt->{all} ? sub { $starting_point{ $File::Next::name } || is_searchable( $_ ) }
2496 : sub { $starting_point{ $File::Next::name } || is_interesting( @_ ) }
2497 ;
2498 }
2499
2500 my $descend_filter
2501 = $opt->{n} ? sub {0}
2502 : $opt->{u} ? sub {1}
2503 : \&ignoredir_filter;
2504
2505 my $iter =
2506 File::Next::files( {
2507 file_filter => $file_filter,
2508 descend_filter => $descend_filter,
2509 error_handler => sub { my $msg = shift; App::Ack::warn( $msg ) },
2510 sort_files => $opt->{sort_files},
2511 follow_symlinks => $opt->{follow},
2512 }, @{$what} );
2513 return $iter;
2514 }
2515
2516
2517 sub set_up_pager {
2518 my $command = shift;
2519
2520 return if App::Ack::output_to_pipe();
2521
2522 my $pager;
2523 if ( not open( $pager, '|-', $command ) ) {
2524 App::Ack::die( qq{Unable to pipe to pager "$command": $!} );
2525 }
2526 $fh = $pager;
2527
2528 return;
2529 }
2530
2531
2532 sub input_from_pipe {
2533 return $input_from_pipe;
2534 }
2535
2536
2537
2538 sub output_to_pipe {
2539 return $output_to_pipe;
2540 }
2541
2542
2543 sub exit_from_ack {
2544 my $nmatches = shift;
2545
2546 my $rc = $nmatches ? 0 : 1;
2547 exit $rc;
2548 }
2549
2550
2551
2552 1; # End of App::Ack
2553 package App::Ack::Repository;
2554
2555
2556 use warnings;
2557 use strict;
2558
2559 sub FAIL {
2560 require Carp;
2561 Carp::confess( 'Must be overloaded' );
2562 }
2563
2564
2565 sub new {
2566 FAIL();
2567 }
2568
2569
2570 sub next_resource {
2571 FAIL();
2572 }
2573
2574
2575 sub close {
2576 FAIL();
2577 }
2578
2579 1;
2580 package App::Ack::Resource;
2581
2582
2583 use warnings;
2584 use strict;
2585
2586 sub FAIL {
2587 require Carp;
2588 Carp::confess( 'Must be overloaded' );
2589 }
2590
2591
2592 sub new {
2593 FAIL();
2594 }
2595
2596
2597 sub name {
2598 FAIL();
2599 }
2600
2601
2602 sub is_binary {
2603 FAIL();
2604 }
2605
2606
2607
2608 sub needs_line_scan {
2609 FAIL();
2610 }
2611
2612
2613 sub reset {
2614 FAIL();
2615 }
2616
2617
2618 sub next_text {
2619 FAIL();
2620 }
2621
2622
2623 sub close {
2624 FAIL();
2625 }
2626
2627 1;
2628 package App::Ack::Plugin::Basic;
2629
2630
2631
2632 package App::Ack::Resource::Basic;
2633
2634
2635 use warnings;
2636 use strict;
2637
2638
2639 our @ISA = qw( App::Ack::Resource );
2640
2641
2642 sub new {
2643 my $class = shift;
2644 my $filename = shift;
2645
2646 my $self = bless {
2647 filename => $filename,
2648 fh => undef,
2649 could_be_binary => undef,
2650 opened => undef,
2651 id => undef,
2652 }, $class;
2653
2654 if ( $self->{filename} eq '-' ) {
2655 $self->{fh} = *STDIN;
2656 $self->{could_be_binary} = 0;
2657 }
2658 else {
2659 if ( !open( $self->{fh}, '<', $self->{filename} ) ) {
2660 App::Ack::warn( "$self->{filename}: $!" );
2661 return;
2662 }
2663 $self->{could_be_binary} = 1;
2664 }
2665
2666 return $self;
2667 }
2668
2669
2670 sub name {
2671 my $self = shift;
2672
2673 return $self->{filename};
2674 }
2675
2676
2677 sub is_binary {
2678 my $self = shift;
2679
2680 if ( $self->{could_be_binary} ) {
2681 return -B $self->{filename};
2682 }
2683
2684 return 0;
2685 }
2686
2687
2688
2689 sub needs_line_scan {
2690 my $self = shift;
2691 my $opt = shift;
2692
2693 return 1 if $opt->{v};
2694
2695 my $size = -s $self->{fh};
2696 if ( $size == 0 ) {
2697 return 0;
2698 }
2699 elsif ( $size > 100_000 ) {
2700 return 1;
2701 }
2702
2703 my $buffer;
2704 my $rc = sysread( $self->{fh}, $buffer, $size );
2705 if ( not defined $rc ) {
2706 App::Ack::warn( "$self->{filename}: $!" );
2707 return 1;
2708 }
2709 return 0 unless $rc && ( $rc == $size );
2710
2711 my $regex = $opt->{regex};
2712 return $buffer =~ /$regex/m;
2713 }
2714
2715
2716 sub reset {
2717 my $self = shift;
2718
2719 seek( $self->{fh}, 0, 0 )
2720 or App::Ack::warn( "$self->{filename}: $!" );
2721
2722 return;
2723 }
2724
2725
2726 sub next_text {
2727 if ( defined ($_ = readline $_[0]->{fh}) ) {
2728 $. = ++$_[0]->{line};
2729 return 1;
2730 }
2731
2732 return;
2733 }
2734
2735
2736 sub close {
2737 my $self = shift;
2738
2739 if ( not close $self->{fh} ) {
2740 App::Ack::warn( $self->name() . ": $!" );
2741 }
2742
2743 return;
2744 }
2745
2746 package App::Ack::Repository::Basic;
2747
2748
2749 our @ISA = qw( App::Ack::Repository );
2750
2751
2752 use warnings;
2753 use strict;
2754
2755 sub new {
2756 my $class = shift;
2757 my $filename = shift;
2758
2759 my $self = bless {
2760 filename => $filename,
2761 nexted => 0,
2762 }, $class;
2763
2764 return $self;
2765 }
2766
2767
2768 sub next_resource {
2769 my $self = shift;
2770
2771 return if $self->{nexted};
2772 $self->{nexted} = 1;
2773
2774 return App::Ack::Resource::Basic->new( $self->{filename} );
2775 }
2776
2777
2778 sub close {
2779 }
2780
2781
2782
2783 1;