]> Tony Duckles's Git Repositories (git.nynim.org) - dotfiles.git/blob - bin/ack
.tmux.conf: Shift+0-9 to select screens 10-19
[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 # http://github.com/petdance/ack2
8 # and submit patches against the individual files
9 # that build ack.
10 #
11
12 package File::Next;
13
14 use strict;
15 use warnings;
16
17
18 our $VERSION = '1.12';
19
20
21
22 use File::Spec ();
23
24 our $name; # name of the current file
25 our $dir; # dir of the current file
26
27 our %files_defaults;
28 our %skip_dirs;
29
30 BEGIN {
31 %files_defaults = (
32 file_filter => undef,
33 descend_filter => undef,
34 error_handler => sub { CORE::die @_ },
35 warning_handler => sub { CORE::warn @_ },
36 sort_files => undef,
37 follow_symlinks => 1,
38 nul_separated => 0,
39 );
40 %skip_dirs = map {($_,1)} (File::Spec->curdir, File::Spec->updir);
41 }
42
43
44 sub files {
45 die _bad_invocation() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__);
46
47 my ($parms,@queue) = _setup( \%files_defaults, @_ );
48 my $filter = $parms->{file_filter};
49
50 return sub {
51 while (@queue) {
52 my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 );
53 if ( -f $fullpath || -p $fullpath || $fullpath =~ m{^/dev/fd} ) {
54 if ( $filter ) {
55 local $_ = $file;
56 local $File::Next::dir = $dirname;
57 local $File::Next::name = $fullpath;
58 next if not $filter->();
59 }
60 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
61 }
62 elsif ( -d _ ) {
63 unshift( @queue, _candidate_files( $parms, $fullpath ) );
64 }
65 } # while
66
67 return;
68 }; # iterator
69 }
70
71
72
73
74
75
76 sub from_file {
77 die _bad_invocation() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__);
78
79 my ($parms,@queue) = _setup( \%files_defaults, @_ );
80 my $err = $parms->{error_handler};
81 my $warn = $parms->{error_handler};
82
83 my $filename = $queue[1];
84
85 if ( !defined($filename) ) {
86 $err->( 'Must pass a filename to from_file()' );
87 return undef;
88 }
89
90 my $fh;
91 if ( $filename eq '-' ) {
92 $fh = \*STDIN;
93 }
94 else {
95 if ( !open( $fh, '<', $filename ) ) {
96 $err->( "Unable to open $filename: $!" );
97 return undef;
98 }
99 }
100 my $filter = $parms->{file_filter};
101
102 return sub {
103 local $/ = $parms->{nul_separated} ? "\x00" : $/;
104 while ( my $fullpath = <$fh> ) {
105 chomp $fullpath;
106 next unless $fullpath =~ /./;
107 if ( not ( -f $fullpath || -p _ ) ) {
108 $warn->( "$fullpath: No such file" );
109 next;
110 }
111
112 my ($volume,$dirname,$file) = File::Spec->splitpath( $fullpath );
113 if ( $filter ) {
114 local $_ = $file;
115 local $File::Next::dir = $dirname;
116 local $File::Next::name = $fullpath;
117 next if not $filter->();
118 }
119 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
120 } # while
121 close $fh;
122
123 return;
124 }; # iterator
125 }
126
127 sub _bad_invocation {
128 my $good = (caller(1))[3];
129 my $bad = $good;
130 $bad =~ s/(.+)::/$1->/;
131 return "$good must not be invoked as $bad";
132 }
133
134 sub sort_standard($$) { return $_[0]->[1] cmp $_[1]->[1] }
135 sub sort_reverse($$) { return $_[1]->[1] cmp $_[0]->[1] }
136
137 sub reslash {
138 my $path = shift;
139
140 my @parts = split( /\//, $path );
141
142 return $path if @parts < 2;
143
144 return File::Spec->catfile( @parts );
145 }
146
147
148
149 sub _setup {
150 my $defaults = shift;
151 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
152
153 my %passed_parms = %{$passed_parms};
154
155 my $parms = {};
156 for my $key ( keys %{$defaults} ) {
157 $parms->{$key} =
158 exists $passed_parms{$key}
159 ? delete $passed_parms{$key}
160 : $defaults->{$key};
161 }
162
163 # Any leftover keys are bogus
164 for my $badkey ( keys %passed_parms ) {
165 my $sub = (caller(1))[3];
166 $parms->{error_handler}->( "Invalid option passed to $sub(): $badkey" );
167 }
168
169 # If it's not a code ref, assume standard sort
170 if ( $parms->{sort_files} && ( ref($parms->{sort_files}) ne 'CODE' ) ) {
171 $parms->{sort_files} = \&sort_standard;
172 }
173 my @queue;
174
175 for ( @_ ) {
176 my $start = reslash( $_ );
177 if (-d $start) {
178 push @queue, ($start,undef,$start);
179 }
180 else {
181 push @queue, (undef,$start,$start);
182 }
183 }
184
185 return ($parms,@queue);
186 }
187
188
189 sub _candidate_files {
190 my $parms = shift;
191 my $dirname = shift;
192
193 my $dh;
194 if ( !opendir $dh, $dirname ) {
195 $parms->{error_handler}->( "$dirname: $!" );
196 return;
197 }
198
199 my @newfiles;
200 my $descend_filter = $parms->{descend_filter};
201 my $follow_symlinks = $parms->{follow_symlinks};
202 my $sort_sub = $parms->{sort_files};
203
204 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
205 my $has_stat;
206
207 # Only do directory checking if we have a descend_filter
208 my $fullpath = File::Spec->catdir( $dirname, $file );
209 if ( !$follow_symlinks ) {
210 next if -l $fullpath;
211 $has_stat = 1;
212 }
213
214 if ( $descend_filter ) {
215 if ( $has_stat ? (-d _) : (-d $fullpath) ) {
216 local $File::Next::dir = $fullpath;
217 local $_ = $file;
218 next if not $descend_filter->();
219 }
220 }
221 if ( $sort_sub ) {
222 push( @newfiles, [ $dirname, $file, $fullpath ] );
223 }
224 else {
225 push( @newfiles, $dirname, $file, $fullpath );
226 }
227 }
228 closedir $dh;
229
230 if ( $sort_sub ) {
231 return map { @{$_} } sort $sort_sub @newfiles;
232 }
233
234 return @newfiles;
235 }
236
237
238 1; # End of File::Next
239 package App::Ack;
240
241 use warnings;
242 use strict;
243
244
245 our $VERSION;
246 our $GIT_REVISION;
247 our $COPYRIGHT;
248 BEGIN {
249 $VERSION = '2.10';
250 $COPYRIGHT = 'Copyright 2005-2013 Andy Lester.';
251 $GIT_REVISION = q{af91cce};
252 }
253
254 our $fh;
255
256 BEGIN {
257 $fh = *STDOUT;
258 }
259
260
261 our %types;
262 our %type_wanted;
263 our %mappings;
264 our %ignore_dirs;
265
266 our $is_filter_mode;
267 our $output_to_pipe;
268
269 our $dir_sep_chars;
270 our $is_cygwin;
271 our $is_windows;
272
273 use File::Spec 1.00015 ();
274
275 BEGIN {
276 # These have to be checked before any filehandle diddling.
277 $output_to_pipe = not -t *STDOUT;
278 $is_filter_mode = -p STDIN;
279
280 $is_cygwin = ($^O eq 'cygwin');
281 $is_windows = ($^O eq 'MSWin32');
282 $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File::Spec->catfile( '', '' ) );
283 }
284
285
286
287 sub remove_dir_sep {
288 my $path = shift;
289 $path =~ s/[$dir_sep_chars]$//;
290
291 return $path;
292 }
293
294
295
296 sub warn {
297 return CORE::warn( _my_program(), ': ', @_, "\n" );
298 }
299
300
301 sub die {
302 return CORE::die( _my_program(), ': ', @_, "\n" );
303 }
304
305 sub _my_program {
306 require File::Basename;
307 return File::Basename::basename( $0 );
308 }
309
310
311
312 sub filetypes_supported {
313 return keys %mappings;
314 }
315
316 sub _get_thpppt {
317 my $y = q{_ /|,\\'!.x',=(www)=, U };
318 $y =~ tr/,x!w/\nOo_/;
319 return $y;
320 }
321
322 sub _thpppt {
323 my $y = _get_thpppt();
324 App::Ack::print( "$y ack $_[0]!\n" );
325 exit 0;
326 }
327
328 sub _bar {
329 my $x;
330 $x = <<'_BAR';
331 6?!I'7!I"?%+!
332 3~!I#7#I"7#I!?!+!="+"="+!:!
333 2?#I!7!I!?#I!7!I"+"=%+"=#
334 1?"+!?*+!=#~"=!+#?"="+!
335 0?"+!?"I"?&+!="~!=!~"=!+%="+"
336 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
337 .?%I"?%+%='?!=#~$="
338 ,,!?%I"?(+$=$~!=#:"~$:!~!
339 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
340 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
341 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
342 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
343 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
344 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
345 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
346 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
347 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
348 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
349 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
350 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
351 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
352 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
353 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
354 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
355 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
356 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
357 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
358 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
359 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
360 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
361 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
362 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
363 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
364 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
365 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
366 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
367 7+:!,!~#,"=!7'I!?#I"7/+!7+
368 77I!+!7!?!7!I"71+!7,
369 _BAR
370
371 App::Ack::__pic($x);
372 }
373
374 sub _cathy {
375 my $x = <<'CATHY';
376 0+!--+!
377 0|! "C!H!O!C!O!L!A!T!E!!! !|!
378 0|! "C!H!O!C!O!L!A!T!E!!! !|!
379 0|! "C!H!O!C!O!L!A!T!E!!! !|!
380 0|! $A"C!K!!! $|!
381 0+!--+!
382 6\! 1:!,!.! !
383 7\! /.!M!~!Z!M!~!
384 8\! /~!D! "M! !
385 4.! $\! /M!~!.!8! +.!M# 4
386 0,!.! (\! .~!M!N! ,+!I!.!M!.! 3
387 /?!O!.!M!:! '\! .O!.! +~!Z!=!N!.! 4
388 ..! !D!Z!.!Z!.! '\! 9=!M".! 6
389 /.! !.!~!M".! '\! 8~! 9
390 4M!.! /.!7!N!M!.! F
391 4.! &:!M! !N"M# !M"N!M! #D!M&=! =
392 :M!7!M#:! !~!M!7!,!$!M!:! #.! !O!N!.!M!:!M# ;
393 8Z!M"~!N!$!D!.!N!?! !I!N!.! (?!M! !M!,!D!M".! 9
394 (?!Z!M!N!:! )=!M!O!8!.!M!+!M! !M!,! !O!M! +,!M!.!M!~!Z!N!M!:! &:!~! 0
395 &8!7!.!~!M"D!M!,! &M!?!=!8! !M!,!O! !M!+! !+!O!.!M! $M#~! !.!8!M!Z!.!M! !O!M"Z! %:!~!M!Z!M!Z!.! +
396 &:!M!7!,! *M!.!Z!M! !8"M!.!M!~! !.!M!.!=! #~!8!.!M! !7!M! "N!Z#I! !D!M!,!M!.! $."M!,! !M!.! *
397 2$!O! "N! !.!M!I! !7" "M! "+!O! !~!M! !d!O!.!7!I!M!.! !.!O!=!M!.! !M",!M!.! %.!$!O!D! +
398 1~!O! "M!+! !8!$! "M! "?!O! %Z!8!D!M!?!8!I!O!7!M! #M!.!M! "M",!M! 4
399 07!~! ".!8! !.!M! "I!+! !.!M! &Z!D!.!7!=!M! !:!.!M! #:!8"+! !.!+!8! !8! 3
400 /~!M! #N! !~!M!$! !.!M! !.!M" &~!M! "~!M!O! "D! $M! !8! "M!,!M!+!D!.! 1
401 #.! #?!M!N!.! #~!O! $M!.!7!$! "?" !?!~!M! '7!8!?!M!.!+!M"O! $?"$!D! !.!O! !$!7!I!.! 0
402 $,!M!:!O!?! ".! !?!=! $=!:!O! !M! "M! !M! !+!$! (.! +.!M! !M!.! !8! !+"Z!~! $:!M!$! !.! '
403 #.!8!.!I!$! $7!I! %M" !=!M! !~!M!D! "7!I! .I!O! %?!=!,!D! !,!M! !D!~!8!~! %D!M! (
404 #.!M"?! $=!O! %=!N! "8!.! !Z!M! #M!~! (M!:! #.!M" &O! !M!.! !?!,! !8!.!N!~! $8!N!M!,!.! %
405 *$!O! &M!,! "O! !.!M!.! #M! (~!M( &O!.! !7! "M! !.!M!.!M!,! #.!M! !M! &
406 )=!8!.! $.!M!O!.! "$!.!I!N! !I!M# (7!M(I! %D"Z!M! "=!I! "M! !M!:! #~!D! '
407 )D! &8!N!:! ".!O! !M!="M! "M! (7!M) %." !M!D!."M!.! !$!=! !M!,! +
408 (M! &+!.!M! #Z!7!O!M!.!~!8! +,!M#D!?!M#D! #.!Z!M#,!Z!?! !~!N! "N!.! !M! +
409 'D!:! %$!D! !?! #M!Z! !8!.! !M"?!7!?!7! '+!I!D! !?!O!:!M!:! ":!M!:! !M!7".!M! "8!+! !:!D! !.!M! *
410 %.!O!:! $.!O!+! !D!.! #M! "M!.!+!N!I!Z! "7!M!N!M!N!?!I!7!Z!=!M'D"~! #M!.!8!$! !:! !.!M! "N!?! !,!O! )
411 !.!?!M!:!M!I! %8!,! "M!.! #M! "N! !M!.! !M!.! !+!~! !.!M!.! ':!M! $M! $M!Z!$! !M!.! "D! "M! "?!M! (
412 !7!8! !+!I! ".! "$!=! ":!$! "+! !M!.! !O! !M!I!M".! !=!~! ",!O! '=!M! $$!,! #N!:! ":!8!.! !D!~! !,!M!.! !:!M!.! &
413 !:!,!.! &Z" #D! !.!8!."M!.! !8!?!Z!M!.!M! #Z!~! !?!M!Z!.! %~!O!.!8!$!N!8!O!I!:!~! !+! #M!.! !.!M!.! !+!M! ".!~!M!+! $
414 !.! 'D!I! #?!M!.!M!,! !.!Z! !.!8! #M&O!I!?! (~!I!M"." !M!Z!.! !M!N!.! "+!$!.! "M!.! !M!?!.! "8!M! $
415 (O!8! $M! !M!.! ".!:! !+!=! #M! #.!M! !+" *$!M":!.! !M!~! "M!7! #M! #7!Z! "M"$!M!.! !.! #
416 '$!Z! #.!7!+!M! $.!,! !+!:! #N! #.!M!.!+!M! +D!M! #=!N! ":!O! #=!M! #Z!D! $M!I! %
417 $,! ".! $.!M" %$!.! !?!~! "+!7!." !.!M!,! !M! *,!N!M!.$M!?! "D!,! #M!.! #N! +
418 ,M!Z! &M! "I!,! "M! %I!M! !?!=!.! (Z!8!M! $:!M!.! !,!M! $D! #.!M!.! )
419 +8!O! &.!8! "I!,! !~!M! &N!M! !M!D! '?!N!O!." $?!7! "?!~! #M!.! #I!D!.! (
420 3M!,! "N!.! !D" &.!+!M!.! !M":!.":!M!7!M!D! 'M!.! "M!.! "M!,! $I! )
421 3I! #M! "M!,! !:! &.!M" ".!,! !.!$!M!I! #.! !:! !.!M!?! "N!+! ".! /
422 1M!,! #.!M!8!M!=!.! +~!N"O!Z"~! *+!M!.! "M! 2
423 0.!M! &M!.! 8:! %.!M!Z! "M!=! *O!,! %
424 0?!$! &N! )." .,! %."M! ":!M!.! 0
425 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0
426 CATHY
427 App::Ack::__pic($x);
428 }
429
430 sub __pic {
431 my($compressed) = @_;
432 $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg;
433 App::Ack::print( $compressed );
434 exit 0;
435 }
436
437
438 sub show_help {
439 my $help_arg = shift || 0;
440
441 return show_help_types() if $help_arg =~ /^types?/;
442
443 App::Ack::print( <<"END_OF_HELP" );
444 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
445
446 Search for PATTERN in each source file in the tree from the current
447 directory on down. If any files or directories are specified, then
448 only those files and directories are checked. ack may also search
449 STDIN, but only if no file or directory arguments are specified,
450 or if one of them is "-".
451
452 Default switches may be specified in ACK_OPTIONS environment variable or
453 an .ackrc file. If you want no dependency on the environment, turn it
454 off with --noenv.
455
456 Example: ack -i select
457
458 Searching:
459 -i, --ignore-case Ignore case distinctions in PATTERN
460 --[no]smart-case Ignore case distinctions in PATTERN,
461 only if PATTERN contains no upper case.
462 Ignored if -i is specified
463 -v, --invert-match Invert match: select non-matching lines
464 -w, --word-regexp Force PATTERN to match only whole words
465 -Q, --literal Quote all metacharacters; PATTERN is literal
466
467 Search output:
468 --lines=NUM Only print line(s) NUM of each file
469 -l, --files-with-matches Only print filenames containing matches
470 -L, --files-without-matches Only print filenames with no matches
471 --output=expr Output the evaluation of expr for each line
472 (turns off text highlighting)
473 -o Show only the part of a line matching PATTERN
474 Same as --output='\$&'
475 --passthru Print all lines, whether matching or not
476 --match PATTERN Specify PATTERN explicitly.
477 -m, --max-count=NUM Stop searching in each file after NUM matches
478 -1 Stop searching after one match of any kind
479 -H, --with-filename Print the filename for each match (default:
480 on unless explicitly searching a single file)
481 -h, --no-filename Suppress the prefixing filename on output
482 -c, --count Show number of lines matching per file
483 --[no]column Show the column number of the first match
484
485 -A NUM, --after-context=NUM Print NUM lines of trailing context after
486 matching lines.
487 -B NUM, --before-context=NUM Print NUM lines of leading context before
488 matching lines.
489 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
490
491 --print0 Print null byte as separator between filenames,
492 only works with -f, -g, -l, -L or -c.
493
494 -s Suppress error messages about nonexistent or
495 unreadable files.
496
497
498 File presentation:
499 --pager=COMMAND Pipes all ack output through COMMAND. For
500 example, --pager="less -R". Ignored if output
501 is redirected.
502 --nopager Do not send output through a pager. Cancels
503 any setting in ~/.ackrc, ACK_PAGER or
504 ACK_PAGER_COLOR.
505 --[no]heading Print a filename heading above each file's
506 results. (default: on when used interactively)
507 --[no]break Print a break between results from different
508 files. (default: on when used interactively)
509 --group Same as --heading --break
510 --nogroup Same as --noheading --nobreak
511 --[no]color Highlight the matching text (default: on unless
512 output is redirected, or on Windows)
513 --[no]colour Same as --[no]color
514 --color-filename=COLOR
515 --color-match=COLOR
516 --color-lineno=COLOR Set the color for filenames, matches, and line
517 numbers.
518 --flush Flush output immediately, even when ack is used
519 non-interactively (when output goes to a pipe or
520 file).
521
522
523 File finding:
524 -f Only print the files selected, without
525 searching. The PATTERN must not be specified.
526 -g Same as -f, but only select files matching
527 PATTERN.
528 --sort-files Sort the found files lexically.
529 --show-types Show which types each file has.
530 --files-from=FILE Read the list of files to search from FILE.
531 -x Read the list of files to search from STDIN.
532
533 File inclusion/exclusion:
534 --[no]ignore-dir=name Add/remove directory from list of ignored dirs
535 --[no]ignore-directory=name Synonym for ignore-dir
536 --ignore-file=filter Add filter for ignoring files
537 -r, -R, --recurse Recurse into subdirectories (default: on)
538 -n, --no-recurse No descending into subdirectories
539 --[no]follow Follow symlinks. Default is off.
540 -k, --known-types Include only files of types that ack recognizes.
541
542 --type=X Include only X files, where X is a recognized
543 filetype.
544 --type=noX Exclude X files.
545 See "ack --help-types" for supported filetypes.
546
547 File type specification:
548 --type-set TYPE:FILTER:FILTERARGS
549 Files with the given FILTERARGS applied to the
550 given FILTER are recognized as being of type
551 TYPE. This replaces an existing definition for
552 type TYPE.
553 --type-add TYPE:FILTER:FILTERARGS
554 Files with the given FILTERARGS applied to the
555 given FILTER are recognized as being type TYPE.
556 --type-del TYPE Removes all filters associated with TYPE.
557
558
559 Miscellaneous:
560 --[no]env Ignore environment variables and global ackrc
561 files. --env is legal but redundant.
562 --ackrc=filename Specify an ackrc file to use
563 --ignore-ack-defaults Ignore default definitions included with ack.
564 --create-ackrc Outputs a default ackrc for your customization
565 to standard output.
566 --help, -? This help
567 --help-types Display all known types
568 --dump Dump information on which options are loaded
569 from which RC files
570 --[no]filter Force ack to treat standard input as a pipe
571 (--filter) or tty (--nofilter)
572 --man Man page
573 --version Display version & copyright
574 --thpppt Bill the Cat
575 --bar The warning admiral
576 --cathy Chocolate! Chocolate! Chocolate!
577
578 Exit status is 0 if match, 1 if no match.
579
580 This is version $VERSION of ack.
581 END_OF_HELP
582
583 return;
584 }
585
586
587
588 sub show_help_types {
589 App::Ack::print( <<'END_OF_HELP' );
590 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
591
592 The following is the list of filetypes supported by ack. You can
593 specify a file type with the --type=TYPE format, or the --TYPE
594 format. For example, both --type=perl and --perl work.
595
596 Note that some extensions may appear in multiple types. For example,
597 .pod files are both Perl and Parrot.
598
599 END_OF_HELP
600
601 my @types = filetypes_supported();
602 my $maxlen = 0;
603 for ( @types ) {
604 $maxlen = length if $maxlen < length;
605 }
606 for my $type ( sort @types ) {
607 next if $type =~ /^-/; # Stuff to not show
608 my $ext_list = $mappings{$type};
609
610 if ( ref $ext_list ) {
611 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
612 }
613 App::Ack::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
614 }
615
616 return;
617 }
618
619 sub show_man {
620 require Pod::Usage;
621
622 Pod::Usage::pod2usage({
623 -input => $App::Ack::orig_program_name,
624 -verbose => 2,
625 -exitval => 0,
626 });
627
628 return;
629 }
630
631
632 sub get_version_statement {
633 require Config;
634
635 my $copyright = get_copyright();
636 my $this_perl = $Config::Config{perlpath};
637 if ($^O ne 'VMS') {
638 my $ext = $Config::Config{_exe};
639 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
640 }
641 my $ver = sprintf( '%vd', $^V );
642
643 my $git_revision = $GIT_REVISION ? " (git commit $GIT_REVISION)" : '';
644
645 return <<"END_OF_VERSION";
646 ack ${VERSION}${git_revision}
647 Running under Perl $ver at $this_perl
648
649 $copyright
650
651 This program is free software. You may modify or distribute it
652 under the terms of the Artistic License v2.0.
653 END_OF_VERSION
654 }
655
656
657 sub print_version_statement {
658 App::Ack::print( get_version_statement() );
659
660 return;
661 }
662
663
664 sub get_copyright {
665 return $COPYRIGHT;
666 }
667
668
669 # print subs added in order to make it easy for a third party
670 # module (such as App::Wack) to redefine the display methods
671 # and show the results in a different way.
672 sub print { print {$fh} @_; return; }
673 sub print_first_filename { App::Ack::print( $_[0], "\n" ); return; }
674 sub print_blank_line { App::Ack::print( "\n" ); return; }
675 sub print_separator { App::Ack::print( "--\n" ); return; }
676 sub print_filename { App::Ack::print( $_[0], $_[1] ); return; }
677 sub print_line_no { App::Ack::print( $_[0], $_[1] ); return; }
678 sub print_column_no { App::Ack::print( $_[0], $_[1] ); return; }
679 sub print_count {
680 my $filename = shift;
681 my $nmatches = shift;
682 my $ors = shift;
683 my $count = shift;
684 my $show_filename = shift;
685
686 if ($show_filename) {
687 App::Ack::print( $filename );
688 App::Ack::print( ':', $nmatches ) if $count;
689 }
690 else {
691 App::Ack::print( $nmatches ) if $count;
692 }
693 App::Ack::print( $ors );
694
695 return;
696 }
697
698 sub print_count0 {
699 my $filename = shift;
700 my $ors = shift;
701 my $show_filename = shift;
702
703 if ($show_filename) {
704 App::Ack::print( $filename, ':0', $ors );
705 }
706 else {
707 App::Ack::print( '0', $ors );
708 }
709
710 return;
711 }
712
713 sub set_up_pager {
714 my $command = shift;
715
716 return if App::Ack::output_to_pipe();
717
718 my $pager;
719 if ( not open( $pager, '|-', $command ) ) {
720 App::Ack::die( qq{Unable to pipe to pager "$command": $!} );
721 }
722 $fh = $pager;
723
724 return;
725 }
726
727
728 sub output_to_pipe {
729 return $output_to_pipe;
730 }
731
732
733 sub exit_from_ack {
734 my $nmatches = shift;
735
736 my $rc = $nmatches ? 0 : 1;
737 exit $rc;
738 }
739
740
741
742 1; # End of App::Ack
743 package App::Ack::Resource;
744
745
746 use warnings;
747 use strict;
748 use overload
749 '""' => 'name';
750
751 sub FAIL {
752 require Carp;
753 Carp::confess( 'Must be overloaded' );
754 }
755
756
757 sub new {
758 return FAIL();
759 }
760
761
762 sub name {
763 return FAIL();
764 }
765
766
767 sub is_binary {
768 return FAIL();
769 }
770
771
772 sub open {
773 return FAIL();
774 }
775
776
777 sub needs_line_scan {
778 return FAIL();
779 }
780
781
782 sub reset {
783 return FAIL();
784 }
785
786
787 sub close {
788 return FAIL();
789 }
790
791
792 sub clone {
793 return FAIL();
794 }
795
796
797 sub firstliney {
798 return FAIL();
799 }
800
801 1;
802 package App::Ack::Resources;
803
804
805
806 use warnings;
807 use strict;
808
809
810 sub from_argv {
811 my $class = shift;
812 my $opt = shift;
813 my $start = shift;
814
815 my $self = bless {}, $class;
816
817 my $file_filter = undef;
818 my $descend_filter = $opt->{descend_filter};
819
820 if( $opt->{n} ) {
821 $descend_filter = sub {
822 return 0;
823 };
824 }
825
826 $self->{iter} =
827 File::Next::files( {
828 file_filter => $opt->{file_filter},
829 descend_filter => $descend_filter,
830 error_handler => sub { my $msg = shift; App::Ack::warn( $msg ) },
831 sort_files => $opt->{sort_files},
832 follow_symlinks => $opt->{follow},
833 }, @{$start} );
834
835 return $self;
836 }
837
838
839 sub from_file {
840 my $class = shift;
841 my $opt = shift;
842 my $file = shift;
843
844 my $iter =
845 File::Next::from_file( {
846 error_handler => sub { my $msg = shift; App::Ack::warn( $msg ) },
847 warning_handler => sub { my $msg = shift; App::Ack::warn( $msg ) },
848 sort_files => $opt->{sort_files},
849 }, $file ) or return undef;
850
851 return bless {
852 iter => $iter,
853 }, $class;
854 }
855
856 # This is for reading input lines from STDIN, not the list of files from STDIN
857 sub from_stdin {
858 my $class = shift;
859 my $opt = shift;
860
861 my $self = bless {}, $class;
862
863 my $has_been_called = 0;
864
865 $self->{iter} = sub {
866 if ( !$has_been_called ) {
867 $has_been_called = 1;
868 return '-';
869 }
870 return;
871 };
872
873 return $self;
874 }
875
876 sub next {
877 my $self = shift;
878
879 my $file = $self->{iter}->() or return;
880
881 return App::Ack::Resource::Basic->new( $file );
882 }
883
884 1;
885 package App::Ack::Resource::Basic;
886
887
888 use warnings;
889 use strict;
890
891 use Fcntl ();
892
893 BEGIN {
894 our @ISA = 'App::Ack::Resource';
895 }
896
897
898 sub new {
899 my $class = shift;
900 my $filename = shift;
901
902 my $self = bless {
903 filename => $filename,
904 fh => undef,
905 opened => 0,
906 }, $class;
907
908 if ( $self->{filename} eq '-' ) {
909 $self->{fh} = *STDIN;
910 $self->{opened} = 1;
911 }
912
913 return $self;
914 }
915
916
917 sub name {
918 return $_[0]->{filename};
919 }
920
921
922
923 sub needs_line_scan {
924 my $self = shift;
925 my $opt = shift;
926
927 return 1 if $opt->{v};
928
929 my $size = -s $self->{fh};
930 if ( $size == 0 ) {
931 return 0;
932 }
933 elsif ( $size > 100_000 ) {
934 return 1;
935 }
936
937 my $buffer;
938 my $rc = sysread( $self->{fh}, $buffer, $size );
939 if ( !defined($rc) && $App::Ack::report_bad_filenames ) {
940 App::Ack::warn( "$self->{filename}: $!" );
941 return 1;
942 }
943 return 0 unless $rc && ( $rc == $size );
944
945 my $regex = $opt->{regex};
946 return $buffer =~ /$regex/m;
947 }
948
949
950 sub reset {
951 my $self = shift;
952
953 # return if we haven't opened the file yet
954 if ( !defined($self->{fh}) ) {
955 return;
956 }
957
958 if( !seek( $self->{fh}, 0, 0 ) && $App::Ack::report_bad_filenames ) {
959 App::Ack::warn( "$self->{filename}: $!" );
960 }
961
962 return;
963 }
964
965
966 sub close {
967 my $self = shift;
968
969 # return if we haven't opened the file yet
970 if ( !defined($self->{fh}) ) {
971 return;
972 }
973
974 if ( !close($self->{fh}) && $App::Ack::report_bad_filenames ) {
975 App::Ack::warn( $self->name() . ": $!" );
976 }
977
978 $self->{opened} = 0;
979
980 return;
981 }
982
983
984 sub clone {
985 my ( $self ) = @_;
986
987 return __PACKAGE__->new($self->name);
988 }
989
990 sub firstliney {
991 my ( $self ) = @_;
992
993 my $fh = $self->open();
994
995 unless(exists $self->{firstliney}) {
996 my $buffer = '';
997 my $rc = sysread( $fh, $buffer, 250 );
998 unless($rc) { # XXX handle this better?
999 $buffer = '';
1000 }
1001 $buffer =~ s/[\r\n].*//s;
1002 $self->{firstliney} = $buffer;
1003 $self->reset;
1004 }
1005
1006 $self->close;
1007
1008 return $self->{firstliney};
1009 }
1010
1011 sub open {
1012 my ( $self ) = @_;
1013
1014 return $self->{fh} if $self->{opened};
1015
1016 unless ( open $self->{fh}, '<', $self->{filename} ) {
1017 return;
1018 }
1019
1020 $self->{opened} = 1;
1021
1022 return $self->{fh};
1023 }
1024
1025 1;
1026 package App::Ack::ConfigDefault;
1027
1028 use warnings;
1029 use strict;
1030
1031 sub options {
1032 my @options = split( /\n/, _options_block() );
1033 @options = grep { /./ && !/^#/ } @options;
1034
1035 return @options;
1036 }
1037
1038 sub _options_block {
1039 return <<'HERE';
1040 # This is the default ackrc for ack 2.0
1041
1042 # There are four different ways to match
1043 #
1044 # is: Match the filename exactly
1045 #
1046 # ext: Match the extension of the filename exactly
1047 #
1048 # match: Match the filename against a Perl regular expression
1049 #
1050 # firstlinematch: Match the first 250 characters of the first line
1051 # of text against a Perl regular expression. This is only for
1052 # the --type-add option.
1053
1054
1055 ### Directories to ignore
1056
1057 # Bazaar
1058 --ignore-directory=is:.bzr
1059
1060 # Codeville
1061 --ignore-directory=is:.cdv
1062
1063 # Interface Builder
1064 --ignore-directory=is:~.dep
1065 --ignore-directory=is:~.dot
1066 --ignore-directory=is:~.nib
1067 --ignore-directory=is:~.plst
1068
1069 # Git
1070 --ignore-directory=is:.git
1071
1072 # Mercurial
1073 --ignore-directory=is:.hg
1074
1075 # quilt
1076 --ignore-directory=is:.pc
1077
1078 # Subversion
1079 --ignore-directory=is:.svn
1080
1081 # Monotone
1082 --ignore-directory=is:_MTN
1083
1084 # CVS
1085 --ignore-directory=is:CVS
1086
1087 # RCS
1088 --ignore-directory=is:RCS
1089
1090 # SCCS
1091 --ignore-directory=is:SCCS
1092
1093 # darcs
1094 --ignore-directory=is:_darcs
1095
1096 # Vault/Fortress
1097 --ignore-directory=is:_sgbak
1098
1099 # autoconf
1100 --ignore-directory=is:autom4te.cache
1101
1102 # Perl module building
1103 --ignore-directory=is:blib
1104 --ignore-directory=is:_build
1105
1106 # Perl Devel::Cover module's output directory
1107 --ignore-directory=is:cover_db
1108
1109 # Node modules created by npm
1110 --ignore-directory=is:node_modules
1111
1112 # CMake cache
1113 --ignore-directory=is:CMakeFiles
1114
1115 ### Files to ignore
1116
1117 # Backup files
1118 --ignore-file=ext:bak
1119 --ignore-file=match:/~$/
1120
1121 # Emacs swap files
1122 --ignore-file=match:/^#.+#$/
1123
1124 # vi/vim swap files
1125 --ignore-file=match:/[._].*\.swp$/
1126
1127 # core dumps
1128 --ignore-file=match:/core\.\d+$/
1129
1130 # minified Javascript
1131 --ignore-file=match:/[.-]min[.]js$/
1132 --ignore-file=match:/[.]js[.]min$/
1133
1134 # minified CSS
1135 --ignore-file=match:/[.]min[.]css$/
1136 --ignore-file=match:/[.]css[.]min$/
1137
1138 # PDFs, because they pass Perl's -T detection
1139 --ignore-file=ext:pdf
1140
1141 # Common graphics, just as an optimization
1142 --ignore-file=ext:gif,jpg,jpeg,png
1143
1144
1145 ### Filetypes defined
1146
1147 # Perl http://perl.org/
1148 --type-add=perl:ext:pl,pm,pod,t,psgi
1149 --type-add=perl:firstlinematch:/^#!.*\bperl/
1150
1151 # Perl tests
1152 --type-add=perltest:ext:t
1153
1154 # Makefiles http://www.gnu.org/s/make/
1155 --type-add=make:ext:mk
1156 --type-add=make:ext:mak
1157 --type-add=make:is:makefile
1158 --type-add=make:is:Makefile
1159 --type-add=make:is:GNUmakefile
1160
1161 # Rakefiles http://rake.rubyforge.org/
1162 --type-add=rake:is:Rakefile
1163
1164 # CMake http://www.cmake.org/
1165 --type-add=cmake:is:CMakeLists.txt
1166 --type-add=cmake:ext:cmake
1167
1168 # Actionscript
1169 --type-add=actionscript:ext:as,mxml
1170
1171 # Ada http://www.adaic.org/
1172 --type-add=ada:ext:ada,adb,ads
1173
1174 # ASP http://msdn.microsoft.com/en-us/library/aa286483.aspx
1175 --type-add=asp:ext:asp
1176
1177 # ASP.Net http://www.asp.net/
1178 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
1179
1180 # Assembly
1181 --type-add=asm:ext:asm,s
1182
1183 # Batch
1184 --type-add=batch:ext:bat,cmd
1185
1186 # ColdFusion http://en.wikipedia.org/wiki/ColdFusion
1187 --type-add=cfmx:ext:cfc,cfm,cfml
1188
1189 # Clojure http://clojure.org/
1190 --type-add=clojure:ext:clj
1191
1192 # C
1193 # .xs are Perl C files
1194 --type-add=cc:ext:c,h,xs
1195
1196 # C header files
1197 --type-add=hh:ext:h
1198
1199 # CoffeeScript http://coffeescript.org/
1200 --type-add=coffeescript:ext:coffee
1201
1202 # C++
1203 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
1204
1205 # C#
1206 --type-add=csharp:ext:cs
1207
1208 # CSS http://www.w3.org/Style/CSS/
1209 --type-add=css:ext:css
1210
1211 # Dart http://www.dartlang.org/
1212 --type-add=dart:ext:dart
1213
1214 # Delphi http://en.wikipedia.org/wiki/Embarcadero_Delphi
1215 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
1216
1217 # Elixir http://elixir-lang.org/
1218 --type-add=elixir:ext:ex,exs
1219
1220 # Emacs Lisp http://www.gnu.org/software/emacs
1221 --type-add=elisp:ext:el
1222
1223 # Erlang http://www.erlang.org/
1224 --type-add=erlang:ext:erl,hrl
1225
1226 # Fortran http://en.wikipedia.org/wiki/Fortran
1227 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
1228
1229 # Google Go http://golang.org/
1230 --type-add=go:ext:go
1231
1232 # Groovy http://groovy.codehaus.org/
1233 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
1234
1235 # Haskell http://www.haskell.org/
1236 --type-add=haskell:ext:hs,lhs
1237
1238 # HTML
1239 --type-add=html:ext:htm,html
1240
1241 # Java http://www.oracle.com/technetwork/java/index.html
1242 --type-add=java:ext:java,properties
1243
1244 # JavaScript
1245 --type-add=js:ext:js
1246
1247 # JSP http://www.oracle.com/technetwork/java/javaee/jsp/index.html
1248 --type-add=jsp:ext:jsp,jspx,jhtm,jhtml
1249
1250 # JSON http://www.json.org/
1251 --type-add=json:ext:json
1252
1253 # Less http://www.lesscss.org/
1254 --type-add=less:ext:less
1255
1256 # Common Lisp http://common-lisp.net/
1257 --type-add=lisp:ext:lisp,lsp
1258
1259 # Lua http://www.lua.org/
1260 --type-add=lua:ext:lua
1261 --type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
1262
1263 # Objective-C
1264 --type-add=objc:ext:m,h
1265
1266 # Objective-C++
1267 --type-add=objcpp:ext:mm,h
1268
1269 # OCaml http://caml.inria.fr/
1270 --type-add=ocaml:ext:ml,mli
1271
1272 # Matlab http://en.wikipedia.org/wiki/MATLAB
1273 --type-add=matlab:ext:m
1274
1275 # Parrot http://www.parrot.org/
1276 --type-add=parrot:ext:pir,pasm,pmc,ops,pod,pg,tg
1277
1278 # PHP http://www.php.net/
1279 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
1280 --type-add=php:firstlinematch:/^#!.*\bphp/
1281
1282 # Plone http://plone.org/
1283 --type-add=plone:ext:pt,cpt,metadata,cpy,py
1284
1285 # Python http://www.python.org/
1286 --type-add=python:ext:py
1287 --type-add=python:firstlinematch:/^#!.*\bpython/
1288
1289 # R http://www.r-project.org/
1290 --type-add=rr:ext:R
1291
1292 # Ruby http://www.ruby-lang.org/
1293 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
1294 --type-add=ruby:is:Rakefile
1295 --type-add=ruby:firstlinematch:/^#!.*\bruby/
1296
1297 # Rust http://www.rust-lang.org/
1298 --type-add=rust:ext:rs
1299
1300 # Sass http://sass-lang.com
1301 --type-add=sass:ext:sass,scss
1302
1303 # Scala http://www.scala-lang.org/
1304 --type-add=scala:ext:scala
1305
1306 # Scheme http://groups.csail.mit.edu/mac/projects/scheme/
1307 --type-add=scheme:ext:scm,ss
1308
1309 # Shell
1310 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
1311 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
1312
1313 # Smalltalk http://www.smalltalk.org/
1314 --type-add=smalltalk:ext:st
1315
1316 # SQL http://www.iso.org/iso/catalogue_detail.htm?csnumber=45498
1317 --type-add=sql:ext:sql,ctl
1318
1319 # Tcl http://www.tcl.tk/
1320 --type-add=tcl:ext:tcl,itcl,itk
1321
1322 # LaTeX http://www.latex-project.org/
1323 --type-add=tex:ext:tex,cls,sty
1324
1325 # Template Toolkit http://template-toolkit.org/
1326 --type-add=tt:ext:tt,tt2,ttml
1327
1328 # Visual Basic
1329 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
1330
1331 # Verilog
1332 --type-add=verilog:ext:v,vh,sv
1333
1334 # VHDL http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
1335 --type-add=vhdl:ext:vhd,vhdl
1336
1337 # Vim http://www.vim.org/
1338 --type-add=vim:ext:vim
1339
1340 # XML http://www.w3.org/TR/REC-xml/
1341 --type-add=xml:ext:xml,dtd,xsl,xslt,ent
1342 --type-add=xml:firstlinematch:/<[?]xml/
1343
1344 # YAML http://yaml.org/
1345 --type-add=yaml:ext:yaml,yml
1346 HERE
1347 }
1348
1349 1;
1350 package App::Ack::ConfigFinder;
1351
1352
1353 use strict;
1354 use warnings;
1355
1356 use Cwd 3.00 ();
1357 use File::Spec 3.00;
1358
1359 use if ($^O eq 'MSWin32'), 'Win32';
1360
1361
1362 sub new {
1363 my ( $class ) = @_;
1364
1365 return bless {}, $class;
1366 }
1367
1368 sub _remove_redundancies {
1369 my ( @configs ) = @_;
1370
1371 if ( $App::Ack::is_windows ) {
1372 # inode stat always returns 0 on windows, so just check filenames.
1373 my (%seen, @uniq);
1374
1375 foreach my $path (@configs) {
1376 push @uniq, $path unless $seen{$path};
1377 $seen{$path} = 1;
1378 }
1379
1380 return @uniq;
1381 }
1382
1383 else {
1384
1385 my %dev_and_inode_seen;
1386
1387 foreach my $path ( @configs ) {
1388 my ( $dev, $inode ) = (stat $path)[0, 1];
1389
1390 if( defined($dev) ) {
1391 if( $dev_and_inode_seen{"$dev:$inode"} ) {
1392 undef $path;
1393 }
1394 else {
1395 $dev_and_inode_seen{"$dev:$inode"} = 1;
1396 }
1397 }
1398 }
1399
1400 return grep { defined() } @configs;
1401
1402 }
1403 }
1404
1405 sub _check_for_ackrc {
1406 return unless defined $_[0];
1407
1408 my @files = grep { -f }
1409 map { File::Spec->catfile(@_, $_) }
1410 qw(.ackrc _ackrc);
1411
1412 die File::Spec->catdir(@_) . " contains both .ackrc and _ackrc.\n" .
1413 "Please remove one of those files.\n"
1414 if @files > 1;
1415
1416 return wantarray ? @files : $files[0];
1417 } # end _check_for_ackrc
1418
1419
1420 sub find_config_files {
1421 my @config_files;
1422
1423 if ( $App::Ack::is_windows ) {
1424 push @config_files, map { File::Spec->catfile($_, 'ackrc') } (
1425 Win32::GetFolderPath(Win32::CSIDL_COMMON_APPDATA()),
1426 Win32::GetFolderPath(Win32::CSIDL_APPDATA()),
1427 );
1428 }
1429 else {
1430 push @config_files, '/etc/ackrc';
1431 }
1432
1433
1434 if ( $ENV{'ACKRC'} && -f $ENV{'ACKRC'} ) {
1435 push @config_files, $ENV{'ACKRC'};
1436 }
1437 else {
1438 push @config_files, _check_for_ackrc($ENV{'HOME'});
1439 }
1440
1441 my @dirs = File::Spec->splitdir(Cwd::getcwd());
1442 while(@dirs) {
1443 my $ackrc = _check_for_ackrc(@dirs);
1444 if(defined $ackrc) {
1445 push @config_files, $ackrc;
1446 last;
1447 }
1448 pop @dirs;
1449 }
1450
1451 # XXX we only test for existence here, so if the file is
1452 # deleted out from under us, this will fail later. =(
1453 return _remove_redundancies( @config_files );
1454 }
1455
1456
1457 sub read_rcfile {
1458 my $file = shift;
1459
1460 return unless defined $file && -e $file;
1461
1462 my @lines;
1463
1464 open( my $fh, '<', $file ) or App::Ack::die( "Unable to read $file: $!" );
1465 while ( my $line = <$fh> ) {
1466 chomp $line;
1467 $line =~ s/^\s+//;
1468 $line =~ s/\s+$//;
1469
1470 next if $line eq '';
1471 next if $line =~ /^#/;
1472
1473 push( @lines, $line );
1474 }
1475 close $fh;
1476
1477 return @lines;
1478 }
1479
1480 1;
1481 package App::Ack::ConfigLoader;
1482
1483 use strict;
1484 use warnings;
1485
1486 use Carp 1.04 ();
1487 use Getopt::Long 2.35 ();
1488 use Text::ParseWords 3.1 ();
1489
1490
1491 my @INVALID_COMBINATIONS;
1492
1493 BEGIN {
1494 my @context = qw( -A -B -C --after-context --before-context --context );
1495 my @pretty = qw( --heading --group --break );
1496 my @filename = qw( -h -H --with-filename --no-filename );
1497
1498 @INVALID_COMBINATIONS = (
1499 # XXX normalize
1500 [qw(-l)] => [@context, @pretty, @filename, qw(-L -o --passthru --output --max-count --column -f -g --show-types)],
1501 [qw(-L)] => [@context, @pretty, @filename, qw(-l -o --passthru --output --max-count --column -f -g --show-types -c --count)],
1502 [qw(--line)] => [@context, @pretty, @filename, qw(-l --files-with-matches --files-without-matches -L -o --passthru --match -m --max-count -1 -c --count --column --print0 -f -g --show-types)],
1503 [qw(-o)] => [@context, qw(--output -c --count --column --column -f --show-types)],
1504 [qw(--passthru)] => [@context, qw(--output --column -m --max-count -1 -c --count -f -g)],
1505 [qw(--output)] => [@context, qw(-c --count -f -g)],
1506 [qw(--match)] => [qw(-f -g)],
1507 [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
1508 [qw(-h --no-filename)] => [qw(-H --with-filename -f -g --group --heading)],
1509 [qw(-H --with-filename)] => [qw(-h --no-filename -f -g)],
1510 [qw(-c --count)] => [@context, @pretty, qw(--column -f -g)],
1511 [qw(--column)] => [qw(-f -g)],
1512 [@context] => [qw(-f -g)],
1513 [qw(-f)] => [qw(-g), @pretty],
1514 [qw(-g)] => [qw(-f), @pretty],
1515 );
1516 }
1517
1518 sub process_filter_spec {
1519 my ( $spec ) = @_;
1520
1521 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
1522 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
1523
1524 return ( $type_name,
1525 App::Ack::Filter->create_filter($ext_type, split(/,/, $arguments)) );
1526 }
1527 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
1528 my ( $type_name, $extensions ) = ( $1, $2 );
1529
1530 my @extensions = split(/,/, $extensions);
1531 foreach my $extension ( @extensions ) {
1532 $extension =~ s/^[.]//;
1533 }
1534
1535 return ( $type_name, App::Ack::Filter->create_filter('ext', @extensions) );
1536 }
1537 else {
1538 Carp::croak "invalid filter specification '$spec'";
1539 }
1540 }
1541
1542 sub uninvert_filter {
1543 my ( $opt, @filters ) = @_;
1544
1545 return unless defined $opt->{filters} && @filters;
1546
1547 # Loop through all the registered filters. If we hit one that
1548 # matches this extension and it's inverted, we need to delete it from
1549 # the options.
1550 for ( my $i = 0; $i < @{ $opt->{filters} }; $i++ ) {
1551 my $opt_filter = @{ $opt->{filters} }[$i];
1552
1553 # XXX Do a real list comparison? This just checks string equivalence.
1554 if ( $opt_filter->is_inverted() && "$opt_filter->{filter}" eq "@filters" ) {
1555 splice @{ $opt->{filters} }, $i, 1;
1556 $i--;
1557 }
1558 }
1559 }
1560
1561 sub process_filetypes {
1562 my ( $opt, $arg_sources ) = @_;
1563
1564 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
1565 Getopt::Long::Configure(
1566 'no_ignore_case',
1567 'no_auto_abbrev',
1568 'pass_through',
1569 );
1570 my %additional_specs;
1571
1572 my $add_spec = sub {
1573 my ( undef, $spec ) = @_;
1574
1575 my ( $name, $filter ) = process_filter_spec($spec);
1576
1577 push @{ $App::Ack::mappings{$name} }, $filter;
1578
1579 $additional_specs{$name . '!'} = sub {
1580 my ( undef, $value ) = @_;
1581
1582 my @filters = @{ $App::Ack::mappings{$name} };
1583 if ( not $value ) {
1584 @filters = map { $_->invert() } @filters;
1585 }
1586 else {
1587 uninvert_filter( $opt, @filters );
1588 }
1589
1590 push @{ $opt->{'filters'} }, @filters;
1591 };
1592 };
1593
1594 my $set_spec = sub {
1595 my ( undef, $spec ) = @_;
1596
1597 my ( $name, $filter ) = process_filter_spec($spec);
1598
1599 $App::Ack::mappings{$name} = [ $filter ];
1600
1601 $additional_specs{$name . '!'} = sub {
1602 my ( undef, $value ) = @_;
1603
1604 my @filters = @{ $App::Ack::mappings{$name} };
1605 if ( not $value ) {
1606 @filters = map { $_->invert() } @filters;
1607 }
1608
1609 push @{ $opt->{'filters'} }, @filters;
1610 };
1611 };
1612
1613 my $delete_spec = sub {
1614 my ( undef, $name ) = @_;
1615
1616 delete $App::Ack::mappings{$name};
1617 delete $additional_specs{$name . '!'};
1618 };
1619
1620 my %type_arg_specs = (
1621 'type-add=s' => $add_spec,
1622 'type-set=s' => $set_spec,
1623 'type-del=s' => $delete_spec,
1624 );
1625
1626 for ( my $i = 0; $i < @{$arg_sources}; $i += 2) {
1627 my ( $source_name, $args ) = @{$arg_sources}[ $i, $i + 1];
1628
1629 if ( ref($args) ) {
1630 # $args are modified in place, so no need to munge $arg_sources
1631 local @ARGV = @{$args};
1632 Getopt::Long::GetOptions(%type_arg_specs);
1633 @{$args} = @ARGV;
1634 }
1635 else {
1636 ( undef, $arg_sources->[$i + 1] ) =
1637 Getopt::Long::GetOptionsFromString($args, %type_arg_specs);
1638 }
1639 }
1640
1641 $additional_specs{'k|known-types'} = sub {
1642 my ( undef, $value ) = @_;
1643
1644 my @filters = map { @{$_} } values(%App::Ack::mappings);
1645
1646 push @{ $opt->{'filters'} }, @filters;
1647 };
1648
1649 return \%additional_specs;
1650 }
1651
1652 sub removed_option {
1653 my ( $option, $explanation ) = @_;
1654
1655 $explanation ||= '';
1656 return sub {
1657 warn "Option '$option' is not valid in ack 2\n$explanation";
1658 exit 1;
1659 };
1660 }
1661
1662 sub get_arg_spec {
1663 my ( $opt, $extra_specs ) = @_;
1664
1665 my $dash_a_explanation = <<EOT;
1666 This is because we now have -k/--known-types which makes it only select files
1667 of known types, rather than any text file (which is the behavior of ack 1.x).
1668 You may have options in a .ackrc, or in the ACKRC_OPTIONS environment variable.
1669 Try using the --dump flag.
1670 EOT
1671
1672 return {
1673 1 => sub { $opt->{1} = $opt->{m} = 1 },
1674 'A|after-context=i' => \$opt->{after_context},
1675 'B|before-context=i'
1676 => \$opt->{before_context},
1677 'C|context:i' => sub { shift; my $val = shift; $opt->{before_context} = $opt->{after_context} = ($val || 2) },
1678 'a' => removed_option('-a', $dash_a_explanation),
1679 'all' => removed_option('--all', $dash_a_explanation),
1680 'break!' => \$opt->{break},
1681 c => \$opt->{count},
1682 'color|colour!' => \$opt->{color},
1683 'color-match=s' => \$ENV{ACK_COLOR_MATCH},
1684 'color-filename=s' => \$ENV{ACK_COLOR_FILENAME},
1685 'color-lineno=s' => \$ENV{ACK_COLOR_LINENO},
1686 'column!' => \$opt->{column},
1687 count => \$opt->{count},
1688 'create-ackrc' => sub { print "$_\n" for ( '--ignore-ack-defaults', App::Ack::ConfigDefault::options() ); exit; },
1689 'env!' => sub {
1690 my ( undef, $value ) = @_;
1691
1692 if ( !$value ) {
1693 $opt->{noenv_seen} = 1;
1694 }
1695 },
1696 f => \$opt->{f},
1697 'files-from=s' => \$opt->{files_from},
1698 'filter!' => \$App::Ack::is_filter_mode,
1699 flush => \$opt->{flush},
1700 'follow!' => \$opt->{follow},
1701 g => \$opt->{g},
1702 G => removed_option('-G'),
1703 'group!' => sub { shift; $opt->{heading} = $opt->{break} = shift },
1704 'heading!' => \$opt->{heading},
1705 'h|no-filename' => \$opt->{h},
1706 'H|with-filename' => \$opt->{H},
1707 'i|ignore-case' => \$opt->{i},
1708 'ignore-directory|ignore-dir=s' # XXX Combine this version with the negated version below
1709 => sub {
1710 my ( undef, $dir ) = @_;
1711
1712 $dir = App::Ack::remove_dir_sep( $dir );
1713 if ( $dir !~ /^(?:is|match):/ ) {
1714 $dir = 'is:' . $dir;
1715 }
1716 push @{ $opt->{idirs} }, $dir;
1717 },
1718 'ignore-file=s' => sub {
1719 my ( undef, $file ) = @_;
1720 push @{ $opt->{ifiles} }, $file;
1721 },
1722 'lines=s' => sub { shift; my $val = shift; push @{$opt->{lines}}, $val },
1723 'l|files-with-matches'
1724 => \$opt->{l},
1725 'L|files-without-matches'
1726 => \$opt->{L},
1727 'm|max-count=i' => \$opt->{m},
1728 'match=s' => \$opt->{regex},
1729 'n|no-recurse' => \$opt->{n},
1730 o => sub { $opt->{output} = '$&' },
1731 'output=s' => \$opt->{output},
1732 'pager:s' => sub {
1733 my ( undef, $value ) = @_;
1734
1735 $opt->{pager} = $value || $ENV{PAGER};
1736 },
1737 'noignore-directory|noignore-dir=s'
1738 => sub {
1739 my ( undef, $dir ) = @_;
1740
1741 # XXX can you do --noignore-dir=match,...?
1742 $dir = App::Ack::remove_dir_sep( $dir );
1743 if ( $dir !~ /^(?:is|match):/ ) {
1744 $dir = 'is:' . $dir;
1745 }
1746 if ( $dir !~ /^(?:is|match):/ ) {
1747 Carp::croak("invalid noignore-directory argument: '$dir'");
1748 }
1749
1750 @{ $opt->{idirs} } = grep {
1751 $_ ne $dir
1752 } @{ $opt->{idirs} };
1753
1754 push @{ $opt->{no_ignore_dirs} }, $dir;
1755 },
1756 'nopager' => sub { $opt->{pager} = undef },
1757 'passthru' => \$opt->{passthru},
1758 'print0' => \$opt->{print0},
1759 'Q|literal' => \$opt->{Q},
1760 'r|R|recurse' => sub { $opt->{n} = 0 },
1761 's' => \$opt->{dont_report_bad_filenames},
1762 'show-types' => \$opt->{show_types},
1763 'smart-case!' => \$opt->{smart_case},
1764 'sort-files' => \$opt->{sort_files},
1765 'type=s' => sub {
1766 my ( $getopt, $value ) = @_;
1767
1768 my $cb_value = 1;
1769 if ( $value =~ s/^no// ) {
1770 $cb_value = 0;
1771 }
1772
1773 my $callback = $extra_specs->{ $value . '!' };
1774
1775 if ( $callback ) {
1776 $callback->( $getopt, $cb_value );
1777 }
1778 else {
1779 Carp::croak( "Unknown type '$value'" );
1780 }
1781 },
1782 'u' => removed_option('-u'),
1783 'unrestricted' => removed_option('--unrestricted'),
1784 'v|invert-match' => \$opt->{v},
1785 'w|word-regexp' => \$opt->{w},
1786 'x' => sub { $opt->{files_from} = '-' },
1787
1788 'version' => sub { App::Ack::print_version_statement(); exit; },
1789 'help|?:s' => sub { shift; App::Ack::show_help(@_); exit; },
1790 'help-types' => sub { App::Ack::show_help_types(); exit; },
1791 'man' => sub { App::Ack::show_man(); exit; },
1792 $extra_specs ? %{$extra_specs} : (),
1793 }; # arg_specs
1794 }
1795
1796 sub process_other {
1797 my ( $opt, $extra_specs, $arg_sources ) = @_;
1798
1799 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
1800 Getopt::Long::Configure(
1801 'bundling',
1802 'no_ignore_case',
1803 );
1804
1805 my $argv_source;
1806 my $is_help_types_active;
1807
1808 for ( my $i = 0; $i < @{$arg_sources}; $i += 2 ) {
1809 my ( $source_name, $args ) = @{$arg_sources}[ $i, $i + 1 ];
1810
1811 if ( $source_name eq 'ARGV' ) {
1812 $argv_source = $args;
1813 last;
1814 }
1815 }
1816
1817 if ( $argv_source ) { # This *should* always be true, but you never know...
1818 my @copy = @{$argv_source};
1819 local @ARGV = @copy;
1820
1821 Getopt::Long::Configure('pass_through');
1822
1823 Getopt::Long::GetOptions(
1824 'help-types' => \$is_help_types_active,
1825 );
1826
1827 Getopt::Long::Configure('no_pass_through');
1828 }
1829
1830 my $arg_specs = get_arg_spec($opt, $extra_specs);
1831
1832 for ( my $i = 0; $i < @{$arg_sources}; $i += 2) {
1833 my ($source_name, $args) = @{$arg_sources}[$i, $i + 1];
1834
1835 my $ret;
1836 if ( ref($args) ) {
1837 local @ARGV = @{$args};
1838 $ret = Getopt::Long::GetOptions( %{$arg_specs} );
1839 @{$args} = @ARGV;
1840 }
1841 else {
1842 ( $ret, $arg_sources->[$i + 1] ) =
1843 Getopt::Long::GetOptionsFromString( $args, %{$arg_specs} );
1844 }
1845 if ( !$ret ) {
1846 if ( !$is_help_types_active ) {
1847 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
1848 App::Ack::die( "Invalid option $where" );
1849 }
1850 }
1851 if ( $opt->{noenv_seen} ) {
1852 App::Ack::die( "--noenv found in $source_name" );
1853 }
1854 }
1855
1856 # XXX We need to check on a -- in the middle of a non-ARGV source
1857
1858 return;
1859 }
1860
1861 sub should_dump_options {
1862 my ( $sources ) = @_;
1863
1864 for(my $i = 0; $i < @{$sources}; $i += 2) {
1865 my ( $name, $options ) = @{$sources}[$i, $i + 1];
1866 if($name eq 'ARGV') {
1867 my $dump;
1868 local @ARGV = @{$options};
1869 Getopt::Long::Configure('default', 'pass_through', 'no_auto_help', 'no_auto_version');
1870 Getopt::Long::GetOptions(
1871 'dump' => \$dump,
1872 );
1873 @{$options} = @ARGV;
1874 return $dump;
1875 }
1876 }
1877 return;
1878 }
1879
1880 sub explode_sources {
1881 my ( $sources ) = @_;
1882
1883 my @new_sources;
1884
1885 Getopt::Long::Configure('default', 'pass_through', 'no_auto_help', 'no_auto_version');
1886
1887 my %opt;
1888 my $arg_spec = get_arg_spec(\%opt);
1889
1890 my $add_type = sub {
1891 my ( undef, $arg ) = @_;
1892
1893 # XXX refactor?
1894 if ( $arg =~ /(\w+)=/) {
1895 $arg_spec->{$1} = sub {};
1896 }
1897 else {
1898 ( $arg ) = split /:/, $arg;
1899 $arg_spec->{$arg} = sub {};
1900 }
1901 };
1902
1903 my $del_type = sub {
1904 my ( undef, $arg ) = @_;
1905
1906 delete $arg_spec->{$arg};
1907 };
1908
1909 for(my $i = 0; $i < @{$sources}; $i += 2) {
1910 my ( $name, $options ) = @{$sources}[$i, $i + 1];
1911 if ( ref($options) ne 'ARRAY' ) {
1912 $sources->[$i + 1] = $options =
1913 [ Text::ParseWords::shellwords($options) ];
1914 }
1915 for ( my $j = 0; $j < @{$options}; $j++ ) {
1916 next unless $options->[$j] =~ /^-/;
1917 my @chunk = ( $options->[$j] );
1918 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
1919 $j--;
1920
1921 my @copy = @chunk;
1922 local @ARGV = @chunk;
1923 Getopt::Long::GetOptions(
1924 'type-add=s' => $add_type,
1925 'type-set=s' => $add_type,
1926 'type-del=s' => $del_type,
1927 );
1928 Getopt::Long::GetOptions( %{$arg_spec} );
1929
1930 push @new_sources, $name, \@copy;
1931 }
1932 }
1933
1934 return \@new_sources;
1935 }
1936
1937 sub compare_opts {
1938 my ( $a, $b ) = @_;
1939
1940 my $first_a = $a->[0];
1941 my $first_b = $b->[0];
1942
1943 $first_a =~ s/^--?//;
1944 $first_b =~ s/^--?//;
1945
1946 return $first_a cmp $first_b;
1947 }
1948
1949 sub dump_options {
1950 my ( $sources ) = @_;
1951
1952 $sources = explode_sources($sources);
1953
1954 my %opts_by_source;
1955 my @source_names;
1956
1957 for(my $i = 0; $i < @{$sources}; $i += 2) {
1958 my ( $name, $contents ) = @{$sources}[$i, $i + 1];
1959 if ( not $opts_by_source{$name} ) {
1960 $opts_by_source{$name} = [];
1961 push @source_names, $name;
1962 }
1963 push @{$opts_by_source{$name}}, $contents;
1964 }
1965
1966 foreach my $name (@source_names) {
1967 my $contents = $opts_by_source{$name};
1968
1969 print $name, "\n";
1970 print '=' x length($name), "\n";
1971 print ' ', join(' ', @{$_}), "\n" foreach sort { compare_opts($a, $b) } @{$contents};
1972 }
1973
1974 return;
1975 }
1976
1977 sub remove_default_options_if_needed {
1978 my ( $sources ) = @_;
1979
1980 my $default_index;
1981
1982 foreach my $index ( 0 .. $#$sources ) {
1983 if ( $sources->[$index] eq 'Defaults' ) {
1984 $default_index = $index;
1985 last;
1986 }
1987 }
1988
1989 return $sources unless defined $default_index;
1990
1991 my $should_remove = 0;
1992
1993 # Start with default options, minus some annoying ones.
1994 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version');
1995 Getopt::Long::Configure(
1996 'no_ignore_case',
1997 'no_auto_abbrev',
1998 'pass_through',
1999 );
2000
2001 foreach my $index ( $default_index + 2 .. $#$sources ) {
2002 next if $index % 2 != 0;
2003
2004 my ( $name, $args ) = @{$sources}[ $index, $index + 1 ];
2005
2006 if (ref($args)) {
2007 local @ARGV = @{$args};
2008 Getopt::Long::GetOptions(
2009 'ignore-ack-defaults' => \$should_remove,
2010 );
2011 @{$args} = @ARGV;
2012 }
2013 else {
2014 ( undef, $sources->[$index + 1] ) = Getopt::Long::GetOptionsFromString($args,
2015 'ignore-ack-defaults' => \$should_remove,
2016 );
2017 }
2018 }
2019
2020 Getopt::Long::Configure('default');
2021 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version');
2022
2023 return $sources unless $should_remove;
2024
2025 my @copy = @{$sources};
2026 splice @copy, $default_index, 2;
2027 return \@copy;
2028 }
2029
2030 sub check_for_mutually_exclusive_options {
2031 my ( $arg_sources ) = @_;
2032
2033 my %mutually_exclusive_with;
2034 my @copy = @{$arg_sources};
2035
2036 for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
2037 my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
2038
2039 foreach my $l_opt ( @{$lhs} ) {
2040 foreach my $r_opt ( @{$rhs} ) {
2041 push @{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
2042 push @{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
2043 }
2044 }
2045 }
2046
2047 while( @copy ) {
2048 my %set_opts;
2049
2050 my ( $source_name, $args ) = splice @copy, 0, 2;
2051 $args = ref($args) ? [ @{$args} ] : [ Text::ParseWords::shellwords($args) ];
2052
2053 foreach my $opt ( @{$args} ) {
2054 next unless $opt =~ /^[-+]/;
2055 last if $opt eq '--';
2056
2057 if( $opt =~ /^(.*)=/ ) {
2058 $opt = $1;
2059 }
2060 elsif ( $opt =~ /^(-[^-]).+/ ) {
2061 $opt = $1;
2062 }
2063
2064 $set_opts{ $opt } = 1;
2065
2066 my $mutex_opts = $mutually_exclusive_with{ $opt };
2067
2068 next unless $mutex_opts;
2069
2070 foreach my $mutex_opt ( @{$mutex_opts} ) {
2071 if($set_opts{ $mutex_opt }) {
2072 die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
2073 }
2074 }
2075 }
2076 }
2077 }
2078
2079 sub process_args {
2080 my $arg_sources = \@_;
2081
2082 my %opt = (
2083 pager => $ENV{ACK_PAGER_COLOR} || $ENV{ACK_PAGER},
2084 );
2085
2086 check_for_mutually_exclusive_options($arg_sources);
2087
2088 $arg_sources = remove_default_options_if_needed($arg_sources);
2089
2090 if ( should_dump_options($arg_sources) ) {
2091 dump_options($arg_sources);
2092 exit(0);
2093 }
2094
2095 my $type_specs = process_filetypes(\%opt, $arg_sources);
2096 process_other(\%opt, $type_specs, $arg_sources);
2097 while ( @{$arg_sources} ) {
2098 my ( $source_name, $args ) = splice( @{$arg_sources}, 0, 2 );
2099
2100 # All of our sources should be transformed into an array ref
2101 if ( ref($args) ) {
2102 if ( $source_name eq 'ARGV' ) {
2103 @ARGV = @{$args};
2104 }
2105 elsif (@{$args}) {
2106 Carp::croak "source '$source_name' has extra arguments!";
2107 }
2108 }
2109 else {
2110 Carp::croak 'The impossible has occurred!';
2111 }
2112 }
2113 my $filters = ($opt{filters} ||= []);
2114
2115 # Throw the default filter in if no others are selected.
2116 if ( not grep { !$_->is_inverted() } @{$filters} ) {
2117 push @{$filters}, App::Ack::Filter::Default->new();
2118 }
2119 return \%opt;
2120 }
2121
2122
2123 sub retrieve_arg_sources {
2124 my @arg_sources;
2125
2126 my $noenv;
2127 my $ackrc;
2128
2129 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version');
2130 Getopt::Long::Configure('pass_through');
2131 Getopt::Long::Configure('no_auto_abbrev');
2132
2133 Getopt::Long::GetOptions(
2134 'noenv' => \$noenv,
2135 'ackrc=s' => \$ackrc,
2136 );
2137
2138 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version');
2139
2140 my @files;
2141
2142 if ( !$noenv ) {
2143 my $finder = App::Ack::ConfigFinder->new;
2144 @files = $finder->find_config_files;
2145 }
2146 if ( $ackrc ) {
2147 # We explicitly use open so we get a nice error message.
2148 # XXX This is a potential race condition!.
2149 if(open my $fh, '<', $ackrc) {
2150 close $fh;
2151 }
2152 else {
2153 die "Unable to load ackrc '$ackrc': $!"
2154 }
2155 push( @files, $ackrc );
2156 }
2157
2158 push @arg_sources, Defaults => [ App::Ack::ConfigDefault::options() ];
2159
2160 foreach my $file ( @files) {
2161 my @lines = App::Ack::ConfigFinder::read_rcfile($file);
2162 push ( @arg_sources, $file, \@lines ) if @lines;
2163 }
2164
2165 if ( $ENV{ACK_OPTIONS} && !$noenv ) {
2166 push( @arg_sources, 'ACK_OPTIONS' => $ENV{ACK_OPTIONS} );
2167 }
2168
2169 push( @arg_sources, 'ARGV' => [ @ARGV ] );
2170
2171 return @arg_sources;
2172 }
2173
2174 1; # End of App::Ack::ConfigLoader
2175 package App::Ack::Filter;
2176
2177 use strict;
2178 use warnings;
2179 use overload
2180 '""' => 'to_string';
2181
2182 use Carp 1.04 ();
2183
2184 my %filter_types;
2185
2186
2187 sub create_filter {
2188 my ( undef, $type, @args ) = @_;
2189
2190 if ( my $package = $filter_types{$type} ) {
2191 return $package->new(@args);
2192 }
2193 Carp::croak "Unknown filter type '$type'";
2194 }
2195
2196
2197 sub register_filter {
2198 my ( undef, $type, $package ) = @_;
2199
2200 $filter_types{$type} = $package;
2201
2202 return;
2203 }
2204
2205
2206 sub invert {
2207 my ( $self ) = @_;
2208
2209 return App::Ack::Filter::Inverse->new( $self );
2210 }
2211
2212
2213 sub is_inverted {
2214 return 0;
2215 }
2216
2217
2218 sub to_string {
2219 my ( $self ) = @_;
2220
2221 return '(unimplemented to_string)';
2222 }
2223
2224
2225 sub inspect {
2226 my ( $self ) = @_;
2227
2228 return ref($self);
2229 }
2230
2231 1;
2232 package App::Ack::Filter::Extension;
2233
2234 use strict;
2235 use warnings;
2236 BEGIN {
2237 our @ISA = 'App::Ack::Filter';
2238 }
2239
2240
2241 sub new {
2242 my ( $class, @extensions ) = @_;
2243
2244 my $exts = join('|', map { "\Q$_\E"} @extensions);
2245 my $re = qr/[.](?:$exts)$/i;
2246
2247 return bless {
2248 extensions => \@extensions,
2249 regex => $re,
2250 groupname => 'ExtensionGroup',
2251 }, $class;
2252 }
2253
2254 sub create_group {
2255 return App::Ack::Filter::ExtensionGroup->new();
2256 }
2257
2258 sub filter {
2259 my ( $self, $resource ) = @_;
2260
2261 my $re = $self->{'regex'};
2262
2263 return $resource->name =~ /$re/;
2264 }
2265
2266 sub inspect {
2267 my ( $self ) = @_;
2268
2269 my $re = $self->{'regex'};
2270
2271 return ref($self) . " - $re";
2272 }
2273
2274 sub to_string {
2275 my ( $self ) = @_;
2276
2277 my $exts = $self->{'extensions'};
2278
2279 return join(' ', map { ".$_" } @{$exts});
2280 }
2281
2282 BEGIN {
2283 App::Ack::Filter->register_filter(ext => __PACKAGE__);
2284 }
2285
2286 1;
2287 package App::Ack::Filter::FirstLineMatch;
2288
2289 use strict;
2290 use warnings;
2291 BEGIN {
2292 our @ISA = 'App::Ack::Filter';
2293 }
2294
2295 sub new {
2296 my ( $class, $re ) = @_;
2297
2298 $re =~ s{^/|/$}{}g; # XXX validate?
2299 $re = qr{$re}i;
2300
2301 return bless {
2302 regex => $re,
2303 }, $class;
2304 }
2305
2306 # This test reads the first 250 characters of a file, then just uses the
2307 # first line found in that. This prevents reading something like an entire
2308 # .min.js file (which might be only one "line" long) into memory.
2309
2310 sub filter {
2311 my ( $self, $resource ) = @_;
2312
2313 my $re = $self->{'regex'};
2314
2315 my $line = $resource->firstliney;
2316
2317 return $line =~ /$re/;
2318 }
2319
2320 sub inspect {
2321 my ( $self ) = @_;
2322
2323 my $re = $self->{'regex'};
2324
2325 return ref($self) . " - $re";
2326 }
2327
2328 sub to_string {
2329 my ( $self ) = @_;
2330
2331 (my $re = $self->{regex}) =~ s{\([^:]*:(.*)\)$}{$1};
2332
2333 return "first line matches /$re/";
2334 }
2335
2336 BEGIN {
2337 App::Ack::Filter->register_filter(firstlinematch => __PACKAGE__);
2338 }
2339
2340 1;
2341 package App::Ack::Filter::Is;
2342
2343 use strict;
2344 use warnings;
2345 BEGIN {
2346 our @ISA = 'App::Ack::Filter';
2347 }
2348
2349 use File::Spec 3.00 ();
2350
2351 sub new {
2352 my ( $class, $filename ) = @_;
2353
2354 return bless {
2355 filename => $filename,
2356 groupname => 'IsGroup',
2357 }, $class;
2358 }
2359
2360 sub create_group {
2361 return App::Ack::Filter::IsGroup->new();
2362 }
2363
2364 sub filter {
2365 my ( $self, $resource ) = @_;
2366
2367 my $filename = $self->{'filename'};
2368 my $base = (File::Spec->splitpath($resource->name))[2];
2369
2370 return $base eq $filename;
2371 }
2372
2373 sub inspect {
2374 my ( $self ) = @_;
2375
2376 my $filename = $self->{'filename'};
2377
2378 return ref($self) . " - $filename";
2379 }
2380
2381 sub to_string {
2382 my ( $self ) = @_;
2383
2384 my $filename = $self->{'filename'};
2385
2386 return $filename;
2387 }
2388
2389 BEGIN {
2390 App::Ack::Filter->register_filter(is => __PACKAGE__);
2391 }
2392
2393 1;
2394 package App::Ack::Filter::Match;
2395
2396 use strict;
2397 use warnings;
2398 BEGIN {
2399 our @ISA = 'App::Ack::Filter';
2400 }
2401
2402 use File::Spec 3.00;
2403
2404 sub new {
2405 my ( $class, $re ) = @_;
2406
2407 $re =~ s{^/|/$}{}g; # XXX validate?
2408 $re = qr/$re/i;
2409
2410 return bless {
2411 regex => $re,
2412 }, $class;
2413 }
2414
2415 sub filter {
2416 my ( $self, $resource ) = @_;
2417
2418 my $re = $self->{'regex'};
2419 my $base = (File::Spec->splitpath($resource->name))[2];
2420
2421 return $base =~ /$re/;
2422 }
2423
2424 sub inspect {
2425 my ( $self ) = @_;
2426
2427 my $re = $self->{'regex'};
2428
2429 print ref($self) . " - $re";
2430 }
2431
2432 sub to_string {
2433 my ( $self ) = @_;
2434
2435 my $re = $self->{'regex'};
2436
2437 return "filename matches $re";
2438 }
2439
2440 BEGIN {
2441 App::Ack::Filter->register_filter(match => __PACKAGE__);
2442 }
2443
2444 1;
2445 package App::Ack::Filter::Default;
2446
2447 use strict;
2448 use warnings;
2449 BEGIN {
2450 our @ISA = 'App::Ack::Filter';
2451 }
2452
2453 sub new {
2454 my ( $class ) = @_;
2455
2456 return bless {}, $class;
2457 }
2458
2459 sub filter {
2460 my ( $self, $resource ) = @_;
2461
2462 return -T $resource->name;
2463 }
2464
2465 1;
2466 package App::Ack::Filter::Inverse;
2467
2468 use strict;
2469 use warnings;
2470 BEGIN {
2471 our @ISA = 'App::Ack::Filter';
2472 }
2473
2474 sub new {
2475 my ( $class, $filter ) = @_;
2476
2477 return bless {
2478 filter => $filter,
2479 }, $class;
2480 }
2481
2482 sub filter {
2483 my ( $self, $resource ) = @_;
2484
2485 my $filter = $self->{'filter'};
2486 return !$filter->filter( $resource );
2487 }
2488
2489 sub invert {
2490 my $self = shift;
2491
2492 return $self->{'filter'};
2493 }
2494
2495 sub is_inverted {
2496 return 1;
2497 }
2498
2499 sub inspect {
2500 my ( $self ) = @_;
2501
2502 my $filter = $self->{'filter'};
2503
2504 return "!$filter";
2505 }
2506
2507 1;
2508 package App::Ack::Filter::Collection;
2509
2510 use strict;
2511 use warnings;
2512 BEGIN {
2513 our @ISA = 'App::Ack::Filter';
2514 }
2515
2516 use File::Spec 3.00 ();
2517
2518 sub new {
2519 my ( $class ) = @_;
2520
2521 return bless {
2522 groups => {},
2523 ungrouped => [],
2524 }, $class;
2525 }
2526
2527 sub filter {
2528 my ( $self, $resource ) = @_;
2529
2530 for my $group (values %{$self->{'groups'}}) {
2531 if ($group->filter($resource)) {
2532 return 1;
2533 }
2534 }
2535
2536 for my $filter (@{$self->{'ungrouped'}}) {
2537 if ($filter->filter($resource)) {
2538 return 1;
2539 }
2540 }
2541
2542 return 0;
2543 }
2544
2545 sub add {
2546 my ( $self, $filter ) = @_;
2547
2548 if (exists $filter->{'groupname'}) {
2549 my $groups = $self->{'groups'};
2550 my $group_name = $filter->{'groupname'};
2551
2552 my $group;
2553 if (exists $groups->{$group_name}) {
2554 $group = $groups->{$group_name};
2555 }
2556 else {
2557 $group = $groups->{$group_name} = $filter->create_group();
2558 }
2559
2560 $group->add($filter);
2561 }
2562 else {
2563 push @{$self->{'ungrouped'}}, $filter;
2564 }
2565
2566 return;
2567 }
2568
2569 sub inspect {
2570 my ( $self ) = @_;
2571
2572 return ref($self) . " - $self";
2573 }
2574
2575 sub to_string {
2576 my ( $self ) = @_;
2577
2578 my $ungrouped = $self->{'ungrouped'};
2579
2580 return join(', ', map { "($_)" } @{$ungrouped});
2581 }
2582
2583 1;
2584 package App::Ack::Filter::IsGroup;
2585
2586 use strict;
2587 use warnings;
2588 BEGIN {
2589 our @ISA = 'App::Ack::Filter';
2590 }
2591
2592 use File::Spec 3.00 ();
2593
2594 sub new {
2595 my ( $class ) = @_;
2596
2597 return bless {
2598 data => {},
2599 }, $class;
2600 }
2601
2602 sub add {
2603 my ( $self, $filter ) = @_;
2604
2605 $self->{data}->{ $filter->{filename} } = 1;
2606 }
2607
2608 sub filter {
2609 my ( $self, $resource ) = @_;
2610
2611 my $data = $self->{'data'};
2612 my $base = (File::Spec->splitpath($resource->name))[2];
2613
2614 return exists $data->{$base};
2615 }
2616
2617 sub inspect {
2618 my ( $self ) = @_;
2619
2620 return ref($self) . " - $self";
2621 }
2622
2623 sub to_string {
2624 my ( $self ) = @_;
2625
2626 return join(' ', keys %{$self->{data}});
2627 }
2628
2629 1;
2630 package App::Ack::Filter::ExtensionGroup;
2631
2632 use strict;
2633 use warnings;
2634 BEGIN {
2635 our @ISA = 'App::Ack::Filter';
2636 }
2637
2638 use File::Spec 3.00 ();
2639
2640 sub new {
2641 my ( $class ) = @_;
2642
2643 return bless {
2644 data => {},
2645 }, $class;
2646 }
2647
2648 sub add {
2649 my ( $self, $filter ) = @_;
2650
2651 my $data = $self->{'data'};
2652 my $extensions = $filter->{'extensions'};
2653
2654 foreach my $ext (@{$extensions}) {
2655 $data->{lc $ext} = 1;
2656 }
2657 }
2658
2659 sub filter {
2660 my ( $self, $resource ) = @_;
2661
2662 if ($resource->name =~ /[.]([^.]*)$/) {
2663 return exists $self->{'data'}->{lc $1};
2664 }
2665
2666 return 0;
2667 }
2668
2669 sub inspect {
2670 my ( $self ) = @_;
2671
2672 return ref($self) . " - $self";
2673 }
2674
2675 sub to_string {
2676 my ( $self ) = @_;
2677
2678 my $data = $self->{'data'};
2679
2680 return join(' ', map { ".$_" } (keys %$data));
2681 }
2682
2683 1;
2684 package main;
2685
2686 use strict;
2687 use warnings;
2688
2689 use 5.008008;
2690
2691
2692 # XXX Don't make this so brute force
2693 # See also: https://github.com/petdance/ack2/issues/89
2694
2695 use Getopt::Long 2.35 ();
2696
2697 use Carp 1.04 ();
2698
2699 our $VERSION = '2.10';
2700 # Check http://beyondgrep.com/ for updates
2701
2702 # These are all our globals.
2703
2704 MAIN: {
2705 $App::Ack::orig_program_name = $0;
2706 $0 = join(' ', 'ack', $0);
2707 if ( $App::Ack::VERSION ne $main::VERSION ) {
2708 App::Ack::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
2709 }
2710
2711 # Do preliminary arg checking;
2712 my $env_is_usable = 1;
2713 for my $arg ( @ARGV ) {
2714 last if ( $arg eq '--' );
2715
2716 # Get the --thpppt, --bar, --cathy checking out of the way.
2717 $arg =~ /^--th[pt]+t+$/ and App::Ack::_thpppt($arg);
2718 $arg eq '--bar' and App::Ack::_bar();
2719 $arg eq '--cathy' and App::Ack::_cathy();
2720
2721 # See if we want to ignore the environment. (Don't tell Al Gore.)
2722 $arg eq '--env' and $env_is_usable = 1;
2723 $arg eq '--noenv' and $env_is_usable = 0;
2724 }
2725
2726 if ( !$env_is_usable ) {
2727 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
2728 delete @ENV{@keys};
2729 }
2730 load_colors();
2731
2732 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version');
2733 Getopt::Long::Configure('pass_through', 'no_auto_abbrev');
2734 Getopt::Long::GetOptions(
2735 'help' => sub { App::Ack::show_help(); exit; },
2736 'version' => sub { App::Ack::print_version_statement(); exit; },
2737 'man' => sub { App::Ack::show_man(); exit; },
2738 );
2739 Getopt::Long::Configure('default', 'no_auto_help', 'no_auto_version');
2740
2741 if ( !@ARGV ) {
2742 App::Ack::show_help();
2743 exit 1;
2744 }
2745
2746 main();
2747 }
2748
2749 sub _compile_descend_filter {
2750 my ( $opt ) = @_;
2751
2752 my $idirs = $opt->{idirs};
2753 my $dont_ignore_dirs = $opt->{no_ignore_dirs};
2754
2755 # if we have one or more --noignore-dir directives, we can't ignore
2756 # entire subdirectory hierarchies, so we return an "accept all"
2757 # filter and scrutinize the files more in _compile_file_filter
2758 return if $dont_ignore_dirs;
2759 return unless $idirs && @{$idirs};
2760
2761 my %ignore_dirs;
2762
2763 foreach my $idir (@{$idirs}) {
2764 if ( $idir =~ /^(\w+):(.*)/ ) {
2765 if ( $1 eq 'is') {
2766 $ignore_dirs{$2} = 1;
2767 }
2768 else {
2769 Carp::croak( 'Non-is filters are not yet supported for --ignore-dir' );
2770 }
2771 }
2772 else {
2773 Carp::croak( qq{Invalid filter specification "$idir"} );
2774 }
2775 }
2776
2777 return sub {
2778 return !exists $ignore_dirs{$_} && !exists $ignore_dirs{$File::Next::dir};
2779 };
2780 }
2781
2782 sub _compile_file_filter {
2783 my ( $opt, $start ) = @_;
2784
2785 my $ifiles = $opt->{ifiles};
2786 $ifiles ||= [];
2787
2788 my $ifiles_filters = App::Ack::Filter::Collection->new();
2789
2790 foreach my $filter_spec (@{$ifiles}) {
2791 if ( $filter_spec =~ /^(\w+):(.+)/ ) {
2792 my ($how,$what) = ($1,$2);
2793 my $filter = App::Ack::Filter->create_filter($how, split(/,/, $what));
2794 $ifiles_filters->add($filter);
2795 }
2796 else {
2797 Carp::croak( qq{Invalid filter specification "$filter_spec"} );
2798 }
2799 }
2800
2801 my $filters = $opt->{'filters'} || [];
2802 my $direct_filters = App::Ack::Filter::Collection->new();
2803 my $inverse_filters = App::Ack::Filter::Collection->new();
2804
2805 foreach my $filter (@{$filters}) {
2806 if ($filter->is_inverted()) {
2807 # We want to check if files match the uninverted filters
2808 $inverse_filters->add($filter->invert());
2809 }
2810 else {
2811 $direct_filters->add($filter);
2812 }
2813 }
2814
2815 my %is_member_of_starting_set = map { (get_file_id($_) => 1) } @{$start};
2816
2817 my $ignore_dir_list = $opt->{idirs};
2818 my $dont_ignore_dir_list = $opt->{no_ignore_dirs};
2819
2820 my %ignore_dir_set;
2821 my %dont_ignore_dir_set;
2822
2823 foreach my $filter (@{ $ignore_dir_list }) {
2824 if ( $filter =~ /^(\w+):(.*)/ ) {
2825 if ( $1 eq 'is' ) {
2826 $ignore_dir_set{ $2 } = 1;
2827 } else {
2828 Carp::croak( 'Non-is filters are not yet supported for --ignore-dir' );
2829 }
2830 } else {
2831 Carp::croak( qq{Invalid filter specification "$filter"} );
2832 }
2833 }
2834 foreach my $filter (@{ $dont_ignore_dir_list }) {
2835 if ( $filter =~ /^(\w+):(.*)/ ) {
2836 if ( $1 eq 'is' ) {
2837 $dont_ignore_dir_set{ $2 } = 1;
2838 } else {
2839 Carp::croak( 'Non-is filters are not yet supported for --ignore-dir' );
2840 }
2841 } else {
2842 Carp::croak( qq{Invalid filter specification "$filter"} );
2843 }
2844 }
2845
2846 return sub {
2847 # ack always selects files that are specified on the command
2848 # line, regardless of filetype. If you want to ack a JPEG,
2849 # and say "ack foo whatever.jpg" it will do it for you.
2850 return 1 if $is_member_of_starting_set{ get_file_id($File::Next::name) };
2851
2852 if ( $dont_ignore_dir_list ) {
2853 my ( undef, $dirname ) = File::Spec->splitpath($File::Next::name);
2854 my @dirs = File::Spec->splitdir($dirname);
2855
2856 my $is_ignoring = 0;
2857
2858 foreach my $dir ( @dirs ) {
2859 if ( $ignore_dir_set{ $dir } ) {
2860 $is_ignoring = 1;
2861 }
2862 elsif ( $dont_ignore_dir_set{ $dir } ) {
2863 $is_ignoring = 0;
2864 }
2865 }
2866 if ( $is_ignoring ) {
2867 return 0;
2868 }
2869 }
2870
2871 # Ignore named pipes found in directory searching. Named
2872 # pipes created by subprocesses get specified on the command
2873 # line, so the rule of "always select whatever is on the
2874 # command line" wins.
2875 return 0 if -p $File::Next::name;
2876
2877 # we can't handle unreadable filenames; report them
2878 unless ( -r _ ) {
2879 if ( $App::Ack::report_bad_filenames ) {
2880 App::Ack::warn( "${File::Next::name}: cannot open file for reading" );
2881 }
2882 return 0;
2883 }
2884
2885 my $resource = App::Ack::Resource::Basic->new($File::Next::name);
2886 return 0 if ! $resource;
2887 if ( $ifiles_filters->filter($resource) ) {
2888 return 0;
2889 }
2890
2891 my $match_found = $direct_filters->filter($resource);
2892
2893 # Don't bother invoking inverse filters unless we consider the current resource a match
2894 if ( $match_found && $inverse_filters->filter( $resource ) ) {
2895 $match_found = 0;
2896 }
2897 return $match_found;
2898 };
2899 }
2900
2901 sub show_types {
2902 my $resource = shift;
2903 my $ors = shift;
2904
2905 my @types = filetypes( $resource );
2906 my $types = join( ',', @types );
2907 my $arrow = @types ? ' => ' : ' =>';
2908 App::Ack::print( $resource->name, $arrow, join( ',', @types ), $ors );
2909
2910 return;
2911 }
2912
2913 # Set default colors, load Term::ANSIColor
2914 sub load_colors {
2915 eval 'use Term::ANSIColor 1.10 ()';
2916 eval 'use Win32::Console::ANSI' if $App::Ack::is_windows;
2917
2918 $ENV{ACK_COLOR_MATCH} ||= 'black on_yellow';
2919 $ENV{ACK_COLOR_FILENAME} ||= 'bold green';
2920 $ENV{ACK_COLOR_LINENO} ||= 'bold yellow';
2921
2922 return;
2923 }
2924
2925 sub filetypes {
2926 my ( $resource ) = @_;
2927
2928 my @matches;
2929
2930 foreach my $k (keys %App::Ack::mappings) {
2931 my $filters = $App::Ack::mappings{$k};
2932
2933 foreach my $filter (@{$filters}) {
2934 # clone the resource
2935 my $clone = $resource->clone;
2936 if ( $filter->filter($clone) ) {
2937 push @matches, $k;
2938 last;
2939 }
2940 }
2941 }
2942
2943 # http://search.cpan.org/dist/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm
2944 @matches = sort @matches;
2945 return @matches;
2946 }
2947
2948 # Returns a (fairly) unique identifier for a file.
2949 # Use this function to compare two files to see if they're
2950 # equal (ie. the same file, but with a different path/links/etc).
2951 sub get_file_id {
2952 my ( $filename ) = @_;
2953
2954 if ( $App::Ack::is_windows ) {
2955 return File::Next::reslash( $filename );
2956 }
2957 else {
2958 # XXX is this the best method? it always hits the FS
2959 if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
2960 return join(':', $dev, $inode);
2961 }
2962 else {
2963 # XXX this could be better
2964 return $filename;
2965 }
2966 }
2967 }
2968
2969 # Returns a regex object based on a string and command-line options.
2970 # Dies when the regex $str is undefined (i.e. not given on command line).
2971
2972 sub build_regex {
2973 my $str = shift;
2974 my $opt = shift;
2975
2976 defined $str or App::Ack::die( 'No regular expression found.' );
2977
2978 $str = quotemeta( $str ) if $opt->{Q};
2979 if ( $opt->{w} ) {
2980 $str = "\\b$str" if $str =~ /^\w/;
2981 $str = "$str\\b" if $str =~ /\w$/;
2982 }
2983
2984 my $regex_is_lc = $str eq lc $str;
2985 if ( $opt->{i} || ($opt->{smart_case} && $regex_is_lc) ) {
2986 $str = "(?i)$str";
2987 }
2988
2989 my $re = eval { qr/$str/ };
2990 if ( !$re ) {
2991 die "Invalid regex '$str':\n $@";
2992 }
2993
2994 return $re;
2995
2996 }
2997
2998 {
2999
3000 my @before_ctx_lines;
3001 my @after_ctx_lines;
3002 my $is_iterating;
3003
3004 my $has_printed_something;
3005
3006 BEGIN {
3007 $has_printed_something = 0;
3008 }
3009
3010 sub print_matches_in_resource {
3011 my ( $resource, $opt ) = @_;
3012
3013 my $passthru = $opt->{passthru};
3014 my $max_count = $opt->{m} || -1;
3015 my $nmatches = 0;
3016 my $filename = $resource->name;
3017 my $break = $opt->{break};
3018 my $heading = $opt->{heading};
3019 my $ors = $opt->{print0} ? "\0" : "\n";
3020 my $color = $opt->{color};
3021 my $print_filename = $opt->{show_filename};
3022
3023 my $has_printed_for_this_resource = 0;
3024
3025 $is_iterating = 1;
3026
3027 local $opt->{before_context} = $opt->{output} ? 0 : $opt->{before_context};
3028 local $opt->{after_context} = $opt->{output} ? 0 : $opt->{after_context};
3029
3030 my $n_before_ctx_lines = $opt->{before_context} || 0;
3031 my $n_after_ctx_lines = $opt->{after_context} || 0;
3032
3033 @after_ctx_lines = @before_ctx_lines = ();
3034
3035 my $fh = $resource->open();
3036 if ( !$fh ) {
3037 if ( $App::Ack::report_bad_filenames ) {
3038 App::Ack::warn( "$filename: $!" );
3039 }
3040 return 0;
3041 }
3042
3043 my $display_filename = $filename;
3044 if ( $print_filename && $heading && $color ) {
3045 $display_filename = Term::ANSIColor::colored($display_filename, $ENV{ACK_COLOR_FILENAME});
3046 }
3047
3048 # check for context before the main loop, so we don't
3049 # pay for it if we don't need it
3050 if ( $n_before_ctx_lines || $n_after_ctx_lines ) {
3051 my $current_line = <$fh>; # prime the first line of input
3052
3053 while ( defined $current_line ) {
3054 while ( (@after_ctx_lines < $n_after_ctx_lines) && defined($_ = <$fh>) ) {
3055 push @after_ctx_lines, $_;
3056 }
3057
3058 local $_ = $current_line;
3059 my $former_dot_period = $.;
3060 $. -= @after_ctx_lines;
3061
3062 if ( does_match($opt, $_) ) {
3063 if ( !$has_printed_for_this_resource ) {
3064 if ( $break && $has_printed_something ) {
3065 App::Ack::print_blank_line();
3066 }
3067 if ( $print_filename && $heading ) {
3068 App::Ack::print_filename( $display_filename, $ors );
3069 }
3070 }
3071 print_line_with_context($opt, $filename, $_, $.);
3072 $has_printed_for_this_resource = 1;
3073 $nmatches++;
3074 $max_count--;
3075 }
3076 elsif ( $passthru ) {
3077 chomp; # XXX proper newline handling?
3078 # XXX inline this call?
3079 if ( $break && !$has_printed_for_this_resource && $has_printed_something ) {
3080 App::Ack::print_blank_line();
3081 }
3082 print_line_with_options($opt, $filename, $_, $., ':');
3083 $has_printed_for_this_resource = 1;
3084 }
3085 last unless $max_count != 0;
3086
3087 # I tried doing this with local(), but for some reason,
3088 # $. continued to have its new value after the exit of the
3089 # enclosing block. I'm guessing that $. has some extra
3090 # magic associated with it or something. If someone can
3091 # tell me why this happened, I would love to know!
3092 $. = $former_dot_period; # XXX this won't happen on an exception
3093
3094 if ( $n_before_ctx_lines ) {
3095 push @before_ctx_lines, $current_line;
3096 shift @before_ctx_lines while @before_ctx_lines > $n_before_ctx_lines;
3097 }
3098 if ( $n_after_ctx_lines ) {
3099 $current_line = shift @after_ctx_lines;
3100 }
3101 else {
3102 $current_line = <$fh>;
3103 }
3104 }
3105 }
3106 else {
3107 local $_;
3108
3109 while ( <$fh> ) {
3110 if ( does_match($opt, $_) ) {
3111 if ( !$has_printed_for_this_resource ) {
3112 if ( $break && $has_printed_something ) {
3113 App::Ack::print_blank_line();
3114 }
3115 if ( $print_filename && $heading ) {
3116 App::Ack::print_filename( $display_filename, $ors );
3117 }
3118 }
3119 print_line_with_context($opt, $filename, $_, $.);
3120 $has_printed_for_this_resource = 1;
3121 $nmatches++;
3122 $max_count--;
3123 }
3124 elsif ( $passthru ) {
3125 chomp; # XXX proper newline handling?
3126 if ( $break && !$has_printed_for_this_resource && $has_printed_something ) {
3127 App::Ack::print_blank_line();
3128 }
3129 print_line_with_options($opt, $filename, $_, $., ':');
3130 $has_printed_for_this_resource = 1;
3131 }
3132 last unless $max_count != 0;
3133 }
3134 }
3135
3136 $is_iterating = 0; # XXX this won't happen on an exception
3137 # then again, do we care? ack doesn't really
3138 # handle exceptions anyway.
3139
3140 return $nmatches;
3141 }
3142
3143 sub print_line_with_options {
3144 my ( $opt, $filename, $line, $line_no, $separator ) = @_;
3145
3146 $has_printed_something = 1;
3147
3148 my $print_filename = $opt->{show_filename};
3149 my $print_column = $opt->{column};
3150 my $ors = $opt->{print0} ? "\0" : "\n";
3151 my $heading = $opt->{heading};
3152 my $output_expr = $opt->{output};
3153 my $color = $opt->{color};
3154
3155 my @line_parts;
3156
3157 if( $color ) {
3158 $filename = Term::ANSIColor::colored($filename,
3159 $ENV{ACK_COLOR_FILENAME});
3160 $line_no = Term::ANSIColor::colored($line_no,
3161 $ENV{ACK_COLOR_LINENO});
3162 }
3163
3164 if($print_filename) {
3165 if( $heading ) {
3166 push @line_parts, $line_no;
3167 }
3168 else {
3169 push @line_parts, $filename, $line_no;
3170 }
3171
3172 if( $print_column ) {
3173 push @line_parts, get_match_column();
3174 }
3175 }
3176 if( $output_expr ) {
3177 while ( $line =~ /$opt->{regex}/og ) {
3178 my $output = eval $output_expr;
3179 App::Ack::print( join( $separator, @line_parts, $output ), $ors );
3180 }
3181 }
3182 else {
3183 if ( $color ) {
3184 $line =~ /$opt->{regex}/o; # this match is redundant, but we need
3185 # to perfom it in order to get if
3186 # capture groups are set
3187
3188 if ( @+ > 1 ) { # if we have captures
3189 while ( $line =~ /$opt->{regex}/og ) {
3190 my $offset = 0; # additional offset for when we add stuff
3191 my $previous_match_end = 0;
3192
3193 for ( my $i = 1; $i < @+; $i++ ) {
3194 my ( $match_start, $match_end ) = ( $-[$i], $+[$i] );
3195
3196 next unless defined($match_start);
3197 next if $match_start < $previous_match_end;
3198
3199 my $substring = substr( $line,
3200 $offset + $match_start, $match_end - $match_start );
3201 my $substitution = Term::ANSIColor::colored( $substring,
3202 $ENV{ACK_COLOR_MATCH} );
3203
3204 substr( $line, $offset + $match_start,
3205 $match_end - $match_start, $substitution );
3206
3207 $previous_match_end = $match_end; # offsets do not need to be applied
3208 $offset += length( $substitution ) - length( $substring );
3209 }
3210
3211 pos($line) = $+[0] + $offset;
3212 }
3213 }
3214 else {
3215 my $matched = 0; # flag; if matched, need to escape afterwards
3216
3217 while ( $line =~ /$opt->{regex}/og ) {
3218
3219 $matched = 1;
3220 my ( $match_start, $match_end ) = ($-[0], $+[0]);
3221 next unless defined($match_start);
3222
3223 my $substring = substr( $line, $match_start,
3224 $match_end - $match_start );
3225 my $substitution = Term::ANSIColor::colored( $substring,
3226 $ENV{ACK_COLOR_MATCH} );
3227
3228 substr( $line, $match_start, $match_end - $match_start,
3229 $substitution );
3230
3231 pos($line) = $match_end +
3232 (length( $substitution ) - length( $substring ));
3233 }
3234 # XXX why do we do this?
3235 $line .= "\033[0m\033[K" if $matched;
3236 }
3237 }
3238
3239 push @line_parts, $line;
3240 App::Ack::print( join( $separator, @line_parts ), $ors );
3241 }
3242
3243 return;
3244 }
3245
3246 sub iterate {
3247 my ( $resource, $opt, $cb ) = @_;
3248
3249 $is_iterating = 1;
3250
3251 local $opt->{before_context} = $opt->{output} ? 0 : $opt->{before_context};
3252 local $opt->{after_context} = $opt->{output} ? 0 : $opt->{after_context};
3253
3254 my $n_before_ctx_lines = $opt->{before_context} || 0;
3255 my $n_after_ctx_lines = $opt->{after_context} || 0;
3256
3257 @after_ctx_lines = @before_ctx_lines = ();
3258
3259 my $fh = $resource->open();
3260 if ( !$fh ) {
3261 if ( $App::Ack::report_bad_filenames ) {
3262 # XXX direct access to filename
3263 App::Ack::warn( "$resource->{filename}: $!" );
3264 }
3265 return;
3266 }
3267
3268 # check for context before the main loop, so we don't
3269 # pay for it if we don't need it
3270 if ( $n_before_ctx_lines || $n_after_ctx_lines ) {
3271 my $current_line = <$fh>; # prime the first line of input
3272
3273 while ( defined $current_line ) {
3274 while ( (@after_ctx_lines < $n_after_ctx_lines) && defined($_ = <$fh>) ) {
3275 push @after_ctx_lines, $_;
3276 }
3277
3278 local $_ = $current_line;
3279 my $former_dot_period = $.;
3280 $. -= @after_ctx_lines;
3281
3282 last unless $cb->();
3283
3284 # I tried doing this with local(), but for some reason,
3285 # $. continued to have its new value after the exit of the
3286 # enclosing block. I'm guessing that $. has some extra
3287 # magic associated with it or something. If someone can
3288 # tell me why this happened, I would love to know!
3289 $. = $former_dot_period; # XXX this won't happen on an exception
3290
3291 if ( $n_before_ctx_lines ) {
3292 push @before_ctx_lines, $current_line;
3293 shift @before_ctx_lines while @before_ctx_lines > $n_before_ctx_lines;
3294 }
3295 if ( $n_after_ctx_lines ) {
3296 $current_line = shift @after_ctx_lines;
3297 }
3298 else {
3299 $current_line = <$fh>;
3300 }
3301 }
3302 }
3303 else {
3304 local $_;
3305
3306 while ( <$fh> ) {
3307 last unless $cb->();
3308 }
3309 }
3310
3311 $is_iterating = 0; # XXX this won't happen on an exception
3312 # then again, do we care? ack doesn't really
3313 # handle exceptions anyway.
3314
3315 return;
3316 }
3317
3318 sub get_context {
3319 if ( not $is_iterating ) {
3320 Carp::croak( 'get_context() called outside of iterate()' );
3321 }
3322
3323 return (
3324 scalar(@before_ctx_lines) ? \@before_ctx_lines : undef,
3325 scalar(@after_ctx_lines) ? \@after_ctx_lines : undef,
3326 );
3327 }
3328
3329 }
3330
3331 {
3332
3333 my $is_first_match;
3334 my $previous_file_processed;
3335 my $previous_line_printed;
3336
3337 BEGIN {
3338 $is_first_match = 1;
3339 $previous_line_printed = -1;
3340 }
3341
3342 sub print_line_with_context {
3343 my ( $opt, $filename, $matching_line, $line_no ) = @_;
3344
3345 my $heading = $opt->{heading};
3346
3347 if( !defined($previous_file_processed) ||
3348 $previous_file_processed ne $filename ) {
3349 $previous_file_processed = $filename;
3350 $previous_line_printed = -1;
3351
3352 if( $heading ) {
3353 $is_first_match = 1;
3354 }
3355 }
3356
3357 my $ors = $opt->{print0} ? "\0" : "\n";
3358 my $match_word = $opt->{w};
3359 my $is_tracking_context = $opt->{after_context} || $opt->{before_context};
3360 my $output_expr = $opt->{output};
3361
3362 $matching_line =~ s/[\r\n]+$//g;
3363
3364 my ( $before_context, $after_context ) = get_context();
3365
3366 if ( $before_context ) {
3367 my $first_line = $. - @{$before_context};
3368
3369 if ( $first_line <= $previous_line_printed ) {
3370 splice @{$before_context}, 0, $previous_line_printed - $first_line + 1;
3371 $first_line = $. - @{$before_context};
3372 }
3373 if ( @{$before_context} ) {
3374 my $offset = @{$before_context};
3375
3376 if( !$is_first_match && $previous_line_printed != $first_line - 1 ) {
3377 App::Ack::print('--', $ors);
3378 }
3379 foreach my $line (@{$before_context}) {
3380 my $context_line_no = $. - $offset;
3381 if ( $context_line_no <= $previous_line_printed ) {
3382 next;
3383 }
3384
3385 chomp $line;
3386 print_line_with_options($opt, $filename, $line, $context_line_no, '-');
3387 $previous_line_printed = $context_line_no;
3388 $offset--;
3389 }
3390 }
3391 }
3392
3393 if ( $. > $previous_line_printed ) {
3394 if( $is_tracking_context && !$is_first_match && $previous_line_printed != $. - 1 ) {
3395 App::Ack::print('--', $ors);
3396 }
3397
3398 print_line_with_options($opt, $filename, $matching_line, $line_no, ':');
3399 $previous_line_printed = $.;
3400 }
3401
3402 if($after_context) {
3403 my $offset = 1;
3404 foreach my $line (@{$after_context}) {
3405 # XXX improve this!
3406 if ( $previous_line_printed >= $. + $offset ) {
3407 $offset++;
3408 next;
3409 }
3410 chomp $line;
3411 my $separator = ($opt->{regex} && does_match( $opt, $line )) ? ':' : '-';
3412 print_line_with_options($opt, $filename, $line, $. + $offset, $separator);
3413 $previous_line_printed = $. + $offset;
3414 $offset++;
3415 }
3416 }
3417
3418 $is_first_match = 0;
3419
3420 return;
3421 }
3422
3423 }
3424
3425 {
3426
3427 my $match_column_number;
3428
3429 # does_match() MUST have an $opt->{regex} set.
3430
3431 sub does_match {
3432 my ( $opt, $line ) = @_;
3433
3434 $match_column_number = undef;
3435
3436 if ( $opt->{v} ) {
3437 return ( $line !~ /$opt->{regex}/o );
3438 }
3439 else {
3440 if ( $line =~ /$opt->{regex}/o ) {
3441 # @- = @LAST_MATCH_START
3442 # @+ = @LAST_MATCH_END
3443 $match_column_number = $-[0] + 1;
3444 return 1;
3445 }
3446 else {
3447 return;
3448 }
3449 }
3450 }
3451
3452 sub get_match_column {
3453 return $match_column_number;
3454 }
3455
3456 }
3457
3458 sub resource_has_match {
3459 my ( $resource, $opt ) = @_;
3460
3461 my $has_match = 0;
3462 my $fh = $resource->open();
3463 if ( !$fh ) {
3464 if ( $App::Ack::report_bad_filenames ) {
3465 # XXX direct access to filename
3466 App::Ack::warn( "$resource->{filename}: $!" );
3467 }
3468 }
3469 else {
3470 my $opt_v = $opt->{v};
3471 my $re = $opt->{regex};
3472 while ( <$fh> ) {
3473 if (/$re/o xor $opt_v) {
3474 $has_match = 1;
3475 last;
3476 }
3477 }
3478 close $fh;
3479 }
3480
3481 return $has_match;
3482 }
3483
3484 sub count_matches_in_resource {
3485 my ( $resource, $opt ) = @_;
3486
3487 my $nmatches = 0;
3488 my $fh = $resource->open();
3489 if ( !$fh ) {
3490 if ( $App::Ack::report_bad_filenames ) {
3491 # XXX direct access to filename
3492 App::Ack::warn( "$resource->{filename}: $!" );
3493 }
3494 }
3495 else {
3496 my $opt_v = $opt->{v};
3497 my $re = $opt->{regex};
3498 while ( <$fh> ) {
3499 ++$nmatches if (/$re/o xor $opt_v);
3500 }
3501 close $fh;
3502 }
3503
3504 return $nmatches;
3505 }
3506
3507 sub main {
3508 my @arg_sources = App::Ack::ConfigLoader::retrieve_arg_sources();
3509
3510 my $opt = App::Ack::ConfigLoader::process_args( @arg_sources );
3511
3512 $App::Ack::report_bad_filenames = !$opt->{dont_report_bad_filenames};
3513
3514 if ( $opt->{flush} ) {
3515 $| = 1;
3516 }
3517
3518 if ( not defined $opt->{color} ) {
3519 my $windows_color = 1;
3520 if ( $App::Ack::is_windows ) {
3521 $windows_color = eval { require Win32::Console::ANSI; }
3522 }
3523 $opt->{color} = !App::Ack::output_to_pipe() && $windows_color;
3524 }
3525 if ( not defined $opt->{heading} and not defined $opt->{break} ) {
3526 $opt->{heading} = $opt->{break} = !App::Ack::output_to_pipe();
3527 }
3528
3529 if ( defined($opt->{H}) || defined($opt->{h}) ) {
3530 $opt->{show_filename}= $opt->{H} && !$opt->{h};
3531 }
3532
3533 if ( my $output = $opt->{output} ) {
3534 $output =~ s{\\}{\\\\}g;
3535 $output =~ s{"}{\\"}g;
3536 $opt->{output} = qq{"$output"};
3537 }
3538
3539 my $resources;
3540 if ( $App::Ack::is_filter_mode && !$opt->{files_from} ) { # probably -x
3541 $resources = App::Ack::Resources->from_stdin( $opt );
3542 my $regex = $opt->{regex};
3543 $regex = shift @ARGV if not defined $regex;
3544 $opt->{regex} = build_regex( $regex, $opt );
3545 }
3546 else {
3547 if ( $opt->{f} || $opt->{lines} ) {
3548 if ( $opt->{regex} ) {
3549 App::Ack::warn( "regex ($opt->{regex}) specified with -f or --lines" );
3550 App::Ack::exit_from_ack( 0 ); # XXX the 0 is misleading
3551 }
3552 }
3553 else {
3554 my $regex = $opt->{regex};
3555 $regex = shift @ARGV if not defined $regex;
3556 $opt->{regex} = build_regex( $regex, $opt );
3557 }
3558 my @start;
3559 if ( not defined $opt->{files_from} ) {
3560 @start = @ARGV;
3561 }
3562 if ( !exists($opt->{show_filename}) ) {
3563 unless(@start == 1 && !(-d $start[0])) {
3564 $opt->{show_filename} = 1;
3565 }
3566 }
3567
3568 if ( defined $opt->{files_from} ) {
3569 $resources = App::Ack::Resources->from_file( $opt, $opt->{files_from} );
3570 exit 1 unless $resources;
3571 }
3572 else {
3573 @start = ('.') unless @start;
3574 foreach my $target (@start) {
3575 if ( !-e $target && $App::Ack::report_bad_filenames) {
3576 App::Ack::warn( "$target: No such file or directory" );
3577 }
3578 }
3579
3580 $opt->{file_filter} = _compile_file_filter($opt, \@start);
3581 $opt->{descend_filter} = _compile_descend_filter($opt);
3582
3583 $resources = App::Ack::Resources->from_argv( $opt, \@start );
3584 }
3585 }
3586 App::Ack::set_up_pager( $opt->{pager} ) if defined $opt->{pager};
3587
3588 my $print_filenames = $opt->{show_filename};
3589 my $max_count = $opt->{m};
3590 my $ors = $opt->{print0} ? "\0" : "\n";
3591 my $only_first = $opt->{1};
3592
3593 my $nmatches = 0;
3594 my $total_count = 0;
3595 RESOURCES:
3596 while ( my $resource = $resources->next ) {
3597 # XXX this variable name combined with what we're trying
3598 # to do makes no sense.
3599
3600 # XXX Combine the -f and -g functions
3601 if ( $opt->{f} ) {
3602 # XXX printing should probably happen inside of App::Ack
3603 if ( $opt->{show_types} ) {
3604 show_types( $resource, $ors );
3605 }
3606 else {
3607 App::Ack::print( $resource->name, $ors );
3608 }
3609 ++$nmatches;
3610 last RESOURCES if defined($max_count) && $nmatches >= $max_count;
3611 }
3612 elsif ( $opt->{g} ) {
3613 my $is_match = ( $resource->name =~ /$opt->{regex}/o );
3614 if ( $opt->{v} ? !$is_match : $is_match ) {
3615 if ( $opt->{show_types} ) {
3616 show_types( $resource, $ors );
3617 }
3618 else {
3619 App::Ack::print( $resource->name, $ors );
3620 }
3621 ++$nmatches;
3622 last RESOURCES if defined($max_count) && $nmatches >= $max_count;
3623 }
3624 }
3625 elsif ( $opt->{lines} ) {
3626 my $print_filename = $opt->{show_filename};
3627 my $passthru = $opt->{passthru};
3628
3629 my %line_numbers;
3630 foreach my $line ( @{ $opt->{lines} } ) {
3631 my @lines = split /,/, $line;
3632 @lines = map {
3633 /^(\d+)-(\d+)$/
3634 ? ( $1 .. $2 )
3635 : $_
3636 } @lines;
3637 @line_numbers{@lines} = (1) x @lines;
3638 }
3639
3640 my $filename = $resource->name;
3641
3642 local $opt->{color} = 0;
3643
3644 iterate($resource, $opt, sub {
3645 chomp;
3646
3647 if ( $line_numbers{$.} ) {
3648 print_line_with_context($opt, $filename, $_, $.);
3649 }
3650 elsif ( $passthru ) {
3651 print_line_with_options($opt, $filename, $_, $., ':');
3652 }
3653 return 1;
3654 });
3655 }
3656 elsif ( $opt->{count} ) {
3657 my $matches_for_this_file = count_matches_in_resource( $resource, $opt );
3658
3659 unless ( $opt->{show_filename} ) {
3660 $total_count += $matches_for_this_file;
3661 next RESOURCES;
3662 }
3663
3664 if ( !$opt->{l} || $matches_for_this_file > 0) {
3665 if ( $print_filenames ) {
3666 App::Ack::print( $resource->name, ':', $matches_for_this_file, $ors );
3667 }
3668 else {
3669 App::Ack::print( $matches_for_this_file, $ors );
3670 }
3671 }
3672 }
3673 elsif ( $opt->{l} || $opt->{L} ) {
3674 my $is_match = resource_has_match( $resource, $opt );
3675
3676 if ( $opt->{L} ? !$is_match : $is_match ) {
3677 App::Ack::print( $resource->name, $ors );
3678 ++$nmatches;
3679
3680 last RESOURCES if $only_first;
3681 last RESOURCES if defined($max_count) && $nmatches >= $max_count;
3682 }
3683 }
3684 else {
3685 $nmatches += print_matches_in_resource( $resource, $opt );
3686 if ( $nmatches && $only_first ) {
3687 last RESOURCES;
3688 }
3689 }
3690 }
3691
3692 if ( $opt->{count} && !$opt->{show_filename} ) {
3693 App::Ack::print( $total_count, "\n" );
3694 }
3695
3696 close $App::Ack::fh;
3697 App::Ack::exit_from_ack( $nmatches );
3698 }
3699
3700
3701
3702 =head1 NAME
3703
3704 ack - grep-like text finder
3705
3706 =head1 SYNOPSIS
3707
3708 ack [options] PATTERN [FILE...]
3709 ack -f [options] [DIRECTORY...]
3710
3711 =head1 DESCRIPTION
3712
3713 Ack is designed as a replacement for 99% of the uses of F<grep>.
3714
3715 Ack searches the named input FILEs (or standard input if no files
3716 are named, or the file name - is given) for lines containing a match
3717 to the given PATTERN. By default, ack prints the matching lines.
3718
3719 PATTERN is a Perl regular expression. Perl regular expressions
3720 are commonly found in other programming languages, but for the particulars
3721 of their behavior, please consult
3722 L<http://perldoc.perl.org/perlreref.html|perlreref>. If you don't know
3723 how to use regular expression but are interested in learning, you may
3724 consult L<http://perldoc.perl.org/perlretut.html|perlretut>. If you do not
3725 need or want ack to use regular expressions, please see the
3726 C<-Q>/C<--literal> option.
3727
3728 Ack can also list files that would be searched, without actually
3729 searching them, to let you take advantage of ack's file-type filtering
3730 capabilities.
3731
3732 =head1 FILE SELECTION
3733
3734 If files are not specified for searching, either on the command
3735 line or piped in with the C<-x> option, I<ack> delves into
3736 subdirectories selecting files for searching.
3737
3738 I<ack> is intelligent about the files it searches. It knows about
3739 certain file types, based on both the extension on the file and,
3740 in some cases, the contents of the file. These selections can be
3741 made with the B<--type> option.
3742
3743 With no file selection, I<ack> searches through regular files that
3744 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
3745 options, either present in F<ackrc> files or on the command line.
3746
3747 The default options for I<ack> ignore certain files and directories. These
3748 include:
3749
3750 =over 4
3751
3752 =item * Backup files: Files matching F<#*#> or ending with F<~>.
3753
3754 =item * Coredumps: Files matching F<core.\d+>
3755
3756 =item * Version control directories like F<.svn> and F<.git>.
3757
3758 =back
3759
3760 Run I<ack> with the C<--dump> option to see what settings are set.
3761
3762 However, I<ack> always searches the files given on the command line,
3763 no matter what type. If you tell I<ack> to search in a coredump,
3764 it will search in a coredump.
3765
3766 =head1 DIRECTORY SELECTION
3767
3768 I<ack> descends through the directory tree of the starting directories
3769 specified. If no directories are specified, the current working directory is
3770 used. However, it will ignore the shadow directories used by
3771 many version control systems, and the build directories used by the
3772 Perl MakeMaker system. You may add or remove a directory from this
3773 list with the B<--[no]ignore-dir> option. The option may be repeated
3774 to add/remove multiple directories from the ignore list.
3775
3776 For a complete list of directories that do not get searched, run
3777 C<ack --dump>.
3778
3779 =head1 WHEN TO USE GREP
3780
3781 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
3782 throw I<grep> away, because there are times you'll still need it.
3783
3784 E.g., searching through huge files looking for regexes that can be
3785 expressed with I<grep> syntax should be quicker with I<grep>.
3786
3787 If your script or parent program uses I<grep> C<--quiet> or C<--silent>
3788 or needs exit 2 on IO error, use I<grep>.
3789
3790 =head1 OPTIONS
3791
3792 =over 4
3793
3794 =item B<--ackrc>
3795
3796 Specifies an ackrc file to load after all others; see L</"ACKRC LOCATION SEMANTICS">.
3797
3798 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
3799
3800 Print I<NUM> lines of trailing context after matching lines.
3801
3802 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
3803
3804 Print I<NUM> lines of leading context before matching lines.
3805
3806 =item B<--[no]break>
3807
3808 Print a break between results from different files. On by default
3809 when used interactively.
3810
3811 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
3812
3813 Print I<NUM> lines (default 2) of context around matching lines.
3814
3815 =item B<-c>, B<--count>
3816
3817 Suppress normal output; instead print a count of matching lines for
3818 each input file. If B<-l> is in effect, it will only show the
3819 number of lines for each file that has lines matching. Without
3820 B<-l>, some line counts may be zeroes.
3821
3822 If combined with B<-h> (B<--no-filename>) ack outputs only one total
3823 count.
3824
3825 =item B<--[no]color>, B<--[no]colour>
3826
3827 B<--color> highlights the matching text. B<--nocolor> suppresses
3828 the color. This is on by default unless the output is redirected.
3829
3830 On Windows, this option is off by default unless the
3831 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
3832 environment variable is used.
3833
3834 =item B<--color-filename=I<color>>
3835
3836 Sets the color to be used for filenames.
3837
3838 =item B<--color-match=I<color>>
3839
3840 Sets the color to be used for matches.
3841
3842 =item B<--color-lineno=I<color>>
3843
3844 Sets the color to be used for line numbers.
3845
3846 =item B<--[no]column>
3847
3848 Show the column number of the first match. This is helpful for
3849 editors that can place your cursor at a given position.
3850
3851 =item B<--create-ackrc>
3852
3853 Dumps the default ack options to standard output. This is useful for
3854 when you want to customize the defaults.
3855
3856 =item B<--dump>
3857
3858 Writes the list of options loaded and where they came from to standard
3859 output. Handy for debugging.
3860
3861 =item B<--[no]env>
3862
3863 B<--noenv> disables all environment processing. No F<.ackrc> is
3864 read and all environment variables are ignored. By default, F<ack>
3865 considers F<.ackrc> and settings in the environment.
3866
3867 =item B<--flush>
3868
3869 B<--flush> flushes output immediately. This is off by default
3870 unless ack is running interactively (when output goes to a pipe or
3871 file).
3872
3873 =item B<-f>
3874
3875 Only print the files that would be searched, without actually doing
3876 any searching. PATTERN must not be specified, or it will be taken
3877 as a path to search.
3878
3879 =item B<--files-from=I<FILE>>
3880
3881 The list of files to be searched is specified in I<FILE>. The list of
3882 files are separated by newlines. If I<FILE> is C<->, the list is loaded
3883 from standard input.
3884
3885 =item B<--[no]filter>
3886
3887 Forces ack to act as if it were receiving input via a pipe.
3888
3889 =item B<--[no]follow>
3890
3891 Follow or don't follow symlinks, other than whatever starting files
3892 or directories were specified on the command line.
3893
3894 This is off by default.
3895
3896 =item B<-g I<PATTERN>>
3897
3898 Print files where the relative path + filename matches I<PATTERN>.
3899
3900 =item B<--[no]group>
3901
3902 B<--group> groups matches by file name. This is the default
3903 when used interactively.
3904
3905 B<--nogroup> prints one result per line, like grep. This is the
3906 default when output is redirected.
3907
3908 =item B<-H>, B<--with-filename>
3909
3910 Print the filename for each match. This is the default unless searching
3911 a single explicitly specified file.
3912
3913 =item B<-h>, B<--no-filename>
3914
3915 Suppress the prefixing of filenames on output when multiple files are
3916 searched.
3917
3918 =item B<--[no]heading>
3919
3920 Print a filename heading above each file's results. This is the default
3921 when used interactively.
3922
3923 =item B<--help>, B<-?>
3924
3925 Print a short help statement.
3926
3927 =item B<--help-types>, B<--help=types>
3928
3929 Print all known types.
3930
3931 =item B<-i>, B<--ignore-case>
3932
3933 Ignore case distinctions in PATTERN
3934
3935 =item B<--ignore-ack-defaults>
3936
3937 Tells ack to completely ignore the default definitions provided with ack.
3938 This is useful in combination with B<--create-ackrc> if you I<really> want
3939 to customize ack.
3940
3941 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
3942
3943 Ignore directory (as CVS, .svn, etc are ignored). May be used
3944 multiple times to ignore multiple directories. For example, mason
3945 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
3946 option allows users to search directories which would normally be
3947 ignored (perhaps to research the contents of F<.svn/props> directories).
3948
3949 The I<DIRNAME> must always be a simple directory name. Nested
3950 directories like F<foo/bar> are NOT supported. You would need to
3951 specify B<--ignore-dir=foo> and then no files from any foo directory
3952 are taken into account by ack unless given explicitly on the command
3953 line.
3954
3955 =item B<--ignore-file=I<FILTERTYPE:FILTERARGS>>
3956
3957 Ignore files matching I<FILTERTYPE:FILTERARGS>. The filters are specified
3958 identically to file type filters as seen in L</"Defining your own types">.
3959
3960 =item B<-k>, B<--known-types>
3961
3962 Limit selected files to those with types that ack knows about. This is
3963 equivalent to the default behavior found in ack 1.
3964
3965 =item B<--lines=I<NUM>>
3966
3967 Only print line I<NUM> of each file. Multiple lines can be given with multiple
3968 B<--lines> options or as a comma separated list (B<--lines=3,5,7>). B<--lines=4-7>
3969 also works. The lines are always output in ascending order, no matter the
3970 order given on the command line.
3971
3972 =item B<-l>, B<--files-with-matches>
3973
3974 Only print the filenames of matching files, instead of the matching text.
3975
3976 =item B<-L>, B<--files-without-matches>
3977
3978 Only print the filenames of files that do I<NOT> match.
3979
3980 =item B<--match I<PATTERN>>
3981
3982 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
3983 regex as your first argument, e.g. when executing multiple searches over the
3984 same set of files.
3985
3986 # search for foo and bar in given files
3987 ack file1 t/file* --match foo
3988 ack file1 t/file* --match bar
3989
3990 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
3991
3992 Stop reading a file after I<NUM> matches.
3993
3994 =item B<--man>
3995
3996 Print this manual page.
3997
3998 =item B<-n>, B<--no-recurse>
3999
4000 No descending into subdirectories.
4001
4002 =item B<-o>
4003
4004 Show only the part of each line matching PATTERN (turns off text
4005 highlighting)
4006
4007 =item B<--output=I<expr>>
4008
4009 Output the evaluation of I<expr> for each line (turns off text
4010 highlighting)
4011 If PATTERN matches more than once then a line is output for each non-overlapping match.
4012 For more information please see the section L</"Examples of F<--output>">.
4013
4014 =item B<--pager=I<program>>, B<--nopager>
4015
4016 B<--pager> directs ack's output through I<program>. This can also be specified
4017 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
4018
4019 Using --pager does not suppress grouping and coloring like piping
4020 output on the command-line does.
4021
4022 B<--nopager> cancels any setting in ~/.ackrc, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
4023 No output will be sent through a pager.
4024
4025 =item B<--passthru>
4026
4027 Prints all lines, whether or not they match the expression. Highlighting
4028 will still work, though, so it can be used to highlight matches while
4029 still seeing the entire file, as in:
4030
4031 # Watch a log file, and highlight a certain IP address
4032 $ tail -f ~/access.log | ack --passthru 123.45.67.89
4033
4034 =item B<--print0>
4035
4036 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
4037 are output separated with a null byte instead of the usual newline. This is
4038 helpful when dealing with filenames that contain whitespace, e.g.
4039
4040 # remove all files of type html
4041 ack -f --html --print0 | xargs -0 rm -f
4042
4043 =item B<-Q>, B<--literal>
4044
4045 Quote all metacharacters in PATTERN, it is treated as a literal.
4046
4047 =item B<-r>, B<-R>, B<--recurse>
4048
4049 Recurse into sub-directories. This is the default and just here for
4050 compatibility with grep. You can also use it for turning B<--no-recurse> off.
4051
4052 =item B<-s>
4053
4054 Suppress error messages about nonexistent or unreadable files. This is taken
4055 from fgrep.
4056
4057 =item B<--[no]smart-case>, B<--no-smart-case>
4058
4059 Ignore case in the search strings if PATTERN contains no uppercase
4060 characters. This is similar to C<smartcase> in vim. This option is
4061 off by default, and ignored if C<-i> is specified.
4062
4063 B<-i> always overrides this option.
4064
4065 =item B<--sort-files>
4066
4067 Sorts the found files lexicographically. Use this if you want your file
4068 listings to be deterministic between runs of I<ack>.
4069
4070 =item B<--show-types>
4071
4072 Outputs the filetypes that ack associates with each file.
4073
4074 Works with B<-f> and B<-g> options.
4075
4076 =item B<--type=[no]TYPE>
4077
4078 Specify the types of files to include or exclude from a search.
4079 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
4080 also be specified as B<--perl>, and B<--type=noperl> can be done
4081 as B<--noperl>.
4082
4083 If a file is of both type "foo" and "bar", specifying --foo and
4084 --nobar will exclude the file, because an exclusion takes precedence
4085 over an inclusion.
4086
4087 Type specifications can be repeated and are ORed together.
4088
4089 See I<ack --help=types> for a list of valid types.
4090
4091 =item B<--type-add I<TYPE>:I<FILTER>:I<FILTERARGS>>
4092
4093 Files with the given FILTERARGS applied to the given FILTER
4094 are recognized as being of (the existing) type TYPE.
4095 See also L</"Defining your own types">.
4096
4097
4098 =item B<--type-set I<TYPE>:I<FILTER>:I<FILTERARGS>>
4099
4100 Files with the given FILTERARGS applied to the given FILTER are recognized as
4101 being of type TYPE. This replaces an existing definition for type TYPE. See
4102 also L</"Defining your own types">.
4103
4104 =item B<--type-del I<TYPE>>
4105
4106 The filters associated with TYPE are removed from Ack, and are no longer considered
4107 for searches.
4108
4109 =item B<-v>, B<--invert-match>
4110
4111 Invert match: select non-matching lines
4112
4113 =item B<--version>
4114
4115 Display version and copyright information.
4116
4117 =item B<-w>, B<--word-regexp>
4118
4119 Force PATTERN to match only whole words. The PATTERN is wrapped with
4120 C<\b> metacharacters.
4121
4122 =item B<-x>
4123
4124 An abbreviation for B<--files-from=->; the list of files to search are read
4125 from standard input, with one line per file.
4126
4127 =item B<-1>
4128
4129 Stops after reporting first match of any kind. This is different
4130 from B<--max-count=1> or B<-m1>, where only one match per file is
4131 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
4132 not.
4133
4134 =item B<--thpppt>
4135
4136 Display the all-important Bill The Cat logo. Note that the exact
4137 spelling of B<--thpppppt> is not important. It's checked against
4138 a regular expression.
4139
4140 =item B<--bar>
4141
4142 Check with the admiral for traps.
4143
4144 =item B<--cathy>
4145
4146 Chocolate, Chocolate, Chocolate!
4147
4148 =back
4149
4150 =head1 THE .ackrc FILE
4151
4152 The F<.ackrc> file contains command-line options that are prepended
4153 to the command line before processing. Multiple options may live
4154 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
4155 might look like this:
4156
4157 # Always sort the files
4158 --sort-files
4159
4160 # Always color, even if piping to a another program
4161 --color
4162
4163 # Use "less -r" as my pager
4164 --pager=less -r
4165
4166 Note that arguments with spaces in them do not need to be quoted,
4167 as they are not interpreted by the shell. Basically, each I<line>
4168 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
4169
4170 F<ack> looks in several locations for F<.ackrc> files; the searching
4171 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
4172 files are not considered if B<--noenv> is specified on the command line.
4173
4174 =head1 Defining your own types
4175
4176 ack allows you to define your own types in addition to the predefined
4177 types. This is done with command line options that are best put into
4178 an F<.ackrc> file - then you do not have to define your types over and
4179 over again. In the following examples the options will always be shown
4180 on one command line so that they can be easily copy & pasted.
4181
4182 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
4183 tells you, that perl files are files ending
4184 in .pl, .pm, .pod or .t. So what if you would like to include .xs
4185 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
4186 does this for you. B<--type-add> appends
4187 additional extensions to an existing type.
4188
4189 If you want to define a new type, or completely redefine an existing
4190 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
4191 the type I<eiffel> to include files with
4192 the extensions .e or .eiffel. So to search for all eiffel files
4193 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
4194 As usual, you can also write B<--type=eiffel>
4195 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
4196 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
4197 and I<.xs> files no longer belong to the type I<cc>.
4198
4199 When defining your own types in the F<.ackrc> file you have to use
4200 the following:
4201
4202 --type-set=eiffel:ext:e,eiffel
4203
4204 or writing on separate lines
4205
4206 --type-set
4207 eiffel:ext:e,eiffel
4208
4209 The following does B<NOT> work in the F<.ackrc> file:
4210
4211 --type-set eiffel:ext:e,eiffel
4212
4213
4214 In order to see all currently defined types, use I<--help-types>, e.g.
4215 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
4216
4217 In addition to filtering based on extension (like ack 1.x allowed), ack 2
4218 offers additional filter types. The generic syntax is
4219 I<--type-set TYPE:FILTER:FILTERARGS>; I<FILTERARGS> depends on the value
4220 of I<FILTER>.
4221
4222 =over 4
4223
4224 =item is:I<FILENAME>
4225
4226 I<is> filters match the target filename exactly. It takes exactly one
4227 argument, which is the name of the file to match.
4228
4229 Example:
4230
4231 --type-set make:is:Makefile
4232
4233 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
4234
4235 I<ext> filters match the extension of the target file against a list
4236 of extensions. No leading dot is needed for the extensions.
4237
4238 Example:
4239
4240 --type-set perl:ext:pl,pm,t
4241
4242 =item match:I<PATTERN>
4243
4244 I<match> filters match the target filename against a regular expression.
4245 The regular expression is made case insensitive for the search.
4246
4247 Example:
4248
4249 --type-set make:match:/(gnu)?makefile/
4250
4251 =item firstlinematch:I<PATTERN>
4252
4253 I<firstlinematch> matches the first line of the target file against a
4254 regular expression. Like I<match>, the regular expression is made
4255 case insensitive.
4256
4257 Example:
4258
4259 --type-add perl:firstlinematch:/perl/
4260
4261 =back
4262
4263 More filter types may be made available in the future.
4264
4265 =head1 ENVIRONMENT VARIABLES
4266
4267 For commonly-used ack options, environment variables can make life
4268 much easier. These variables are ignored if B<--noenv> is specified
4269 on the command line.
4270
4271 =over 4
4272
4273 =item ACKRC
4274
4275 Specifies the location of the user's F<.ackrc> file. If this file doesn't
4276 exist, F<ack> looks in the default location.
4277
4278 =item ACK_OPTIONS
4279
4280 This variable specifies default options to be placed in front of
4281 any explicit options on the command line.
4282
4283 =item ACK_COLOR_FILENAME
4284
4285 Specifies the color of the filename when it's printed in B<--group>
4286 mode. By default, it's "bold green".
4287
4288 The recognized attributes are clear, reset, dark, bold, underline,
4289 underscore, blink, reverse, concealed black, red, green, yellow,
4290 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
4291 on_magenta, on_cyan, and on_white. Case is not significant.
4292 Underline and underscore are equivalent, as are clear and reset.
4293 The color alone sets the foreground color, and on_color sets the
4294 background color.
4295
4296 This option can also be set with B<--color-filename>.
4297
4298 =item ACK_COLOR_MATCH
4299
4300 Specifies the color of the matching text when printed in B<--color>
4301 mode. By default, it's "black on_yellow".
4302
4303 This option can also be set with B<--color-match>.
4304
4305 See B<ACK_COLOR_FILENAME> for the color specifications.
4306
4307 =item ACK_COLOR_LINENO
4308
4309 Specifies the color of the line number when printed in B<--color>
4310 mode. By default, it's "bold yellow".
4311
4312 This option can also be set with B<--color-lineno>.
4313
4314 See B<ACK_COLOR_FILENAME> for the color specifications.
4315
4316 =item ACK_PAGER
4317
4318 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
4319 ack will send its output.
4320
4321 Using C<ACK_PAGER> does not suppress grouping and coloring like
4322 piping output on the command-line does, except that on Windows
4323 ack will assume that C<ACK_PAGER> does not support color.
4324
4325 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
4326
4327 =item ACK_PAGER_COLOR
4328
4329 Specifies a pager program that understands ANSI color sequences.
4330 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
4331 like piping output on the command-line does.
4332
4333 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
4334
4335 =back
4336
4337 =head1 ACK & OTHER TOOLS
4338
4339 =head2 Vim integration
4340
4341 F<ack> integrates easily with the Vim text editor. Set this in your
4342 F<.vimrc> to use F<ack> instead of F<grep>:
4343
4344 set grepprg=ack\ -k
4345
4346 That example uses C<-k> to search through only files of the types ack
4347 knows about, but you may use other default flags. Now you can search
4348 with F<ack> and easily step through the results in Vim:
4349
4350 :grep Dumper perllib
4351
4352 Miles Sterrett has written a Vim plugin for F<ack> which allows you to use
4353 C<:Ack> instead of C<:grep>, as well as several other advanced features.
4354
4355 L<https://github.com/mileszs/ack.vim>
4356
4357 =head2 Emacs integration
4358
4359 Phil Jackson put together an F<ack.el> extension that "provides a
4360 simple compilation mode ... has the ability to guess what files you
4361 want to search for based on the major-mode."
4362
4363 L<http://www.shellarchive.co.uk/content/emacs.html>
4364
4365 =head2 TextMate integration
4366
4367 Pedro Melo is a TextMate user who writes "I spend my day mostly
4368 inside TextMate, and the built-in find-in-project sucks with large
4369 projects. So I hacked a TextMate command that was using find +
4370 grep to use ack. The result is the Search in Project with ack, and
4371 you can find it here:
4372 L<http://www.simplicidade.org/notes/archives/2008/03/search_in_proje.html>"
4373
4374 =head2 Shell and Return Code
4375
4376 For greater compatibility with I<grep>, I<ack> in normal use returns
4377 shell return or exit code of 0 only if something is found and 1 if
4378 no match is found.
4379
4380 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
4381
4382 The I<grep> code 2 for errors is not used.
4383
4384 If C<-f> or C<-g> are specified, then 0 is returned if at least one
4385 file is found. If no files are found, then 1 is returned.
4386
4387 =cut
4388
4389 =head1 DEBUGGING ACK PROBLEMS
4390
4391 If ack gives you output you're not expecting, start with a few simple steps.
4392
4393 =head2 Use B<--noenv>
4394
4395 Your environment variables and F<.ackrc> may be doing things you're
4396 not expecting, or forgotten you specified. Use B<--noenv> to ignore
4397 your environment and F<.ackrc>.
4398
4399 =head2 Use B<-f> to see what files have been selected
4400
4401 Ack's B<-f> was originally added as a debugging tool. If ack is
4402 not finding matches you think it should find, run F<ack -f> to see
4403 what files have been selected. You can also add the C<--show-types>
4404 options to show the type of each file selected.
4405
4406 =head2 Use B<--dump>
4407
4408 This lists the ackrc files that are loaded and the options loaded
4409 from them.
4410 So for example you can find a list of directories that do not get searched or where filetypes are defined.
4411
4412 =head1 TIPS
4413
4414 =head2 Use the F<.ackrc> file.
4415
4416 The F<.ackrc> is the place to put all your options you use most of
4417 the time but don't want to remember. Put all your --type-add and
4418 --type-set definitions in it. If you like --smart-case, set it
4419 there, too. I also set --sort-files there.
4420
4421 =head2 Use F<-f> for working with big codesets
4422
4423 Ack does more than search files. C<ack -f --perl> will create a
4424 list of all the Perl files in a tree, ideal for sending into F<xargs>.
4425 For example:
4426
4427 # Change all "this" to "that" in all Perl files in a tree.
4428 ack -f --perl | xargs perl -p -i -e's/this/that/g'
4429
4430 or if you prefer:
4431
4432 perl -p -i -e's/this/that/g' $(ack -f --perl)
4433
4434 =head2 Use F<-Q> when in doubt about metacharacters
4435
4436 If you're searching for something with a regular expression
4437 metacharacter, most often a period in a filename or IP address, add
4438 the -Q to avoid false positives without all the backslashing. See
4439 the following example for more...
4440
4441 =head2 Use ack to watch log files
4442
4443 Here's one I used the other day to find trouble spots for a website
4444 visitor. The user had a problem loading F<troublesome.gif>, so I
4445 took the access log and scanned it with ack twice.
4446
4447 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
4448
4449 The first ack finds only the lines in the Apache log for the given
4450 IP. The second finds the match on my troublesome GIF, and shows
4451 the previous five lines from the log in each case.
4452
4453 =head2 Examples of F<--output>
4454
4455 Following variables are useful in the expansion string:
4456
4457 =over 4
4458
4459 =item C<$&>
4460
4461 The whole string matched by PATTERN.
4462
4463 =item C<$1>, C<$2>, ...
4464
4465 The contents of the 1st, 2nd ... bracketed group in PATTERN.
4466
4467 =item C<$`>
4468
4469 The string before the match.
4470
4471 =item C<$'>
4472
4473 The string after the match.
4474
4475 =back
4476
4477 For more details and other variables see
4478 L<http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions|perlvar>.
4479
4480 This example shows how to add text around a particular pattern
4481 (in this case adding _ around word with "e")
4482
4483 ack2.pl "\w*e\w*" quick.txt --output="$`_$&_$'"
4484 _The_ quick brown fox jumps over the lazy dog
4485 The quick brown fox jumps _over_ the lazy dog
4486 The quick brown fox jumps over _the_ lazy dog
4487
4488 This shows how to pick out particular parts of a match using ( ) within regular expression.
4489
4490 ack '=head(\d+)\s+(.*)' --output=' $1 : $2'
4491 input file contains "=head1 NAME"
4492 output "1 : NAME"
4493
4494 =head2 Share your knowledge
4495
4496 Join the ack-users mailing list. Send me your tips and I may add
4497 them here.
4498
4499 =head1 FAQ
4500
4501 =head2 Why isn't ack finding a match in (some file)?
4502
4503 Probably because it's of a type that ack doesn't recognize. ack's
4504 searching behavior is driven by filetype. B<If ack doesn't know
4505 what kind of file it is, ack ignores the file.>
4506
4507 Use the C<-f> switch to see a list of files that ack will search
4508 for you. You can use the C<--show-types> switch to show which type
4509 ack thinks each file is.
4510
4511 =head2 Wouldn't it be great if F<ack> did search & replace?
4512
4513 No, ack will always be read-only. Perl has a perfectly good way
4514 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
4515 switches.
4516
4517 You can certainly use ack to select your files to update. For
4518 example, to change all "foo" to "bar" in all PHP files, you can do
4519 this from the Unix shell:
4520
4521 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
4522
4523 =head2 Can I make ack recognize F<.xyz> files?
4524
4525 Yes! Please see L</"Defining your own types">. If you think
4526 that F<ack> should recognize a type by default, please see
4527 L</"ENHANCEMENTS">.
4528
4529 =head2 There's already a program/package called ack.
4530
4531 Yes, I know.
4532
4533 =head2 Why is it called ack if it's called ack-grep?
4534
4535 The name of the program is "ack". Some packagers have called it
4536 "ack-grep" when creating packages because there's already a package
4537 out there called "ack" that has nothing to do with this ack.
4538
4539 I suggest you make a symlink named F<ack> that points to F<ack-grep>
4540 because one of the crucial benefits of ack is having a name that's
4541 so short and simple to type.
4542
4543 To do that, run this with F<sudo> or as root:
4544
4545 ln -s /usr/bin/ack-grep /usr/bin/ack
4546
4547 Alternatively, you could use a shell alias:
4548
4549 # bash/zsh
4550 alias ack=ack-grep
4551
4552 # csh
4553 alias ack ack-grep
4554
4555 =head2 What does F<ack> mean?
4556
4557 Nothing. I wanted a name that was easy to type and that you could
4558 pronounce as a single syllable.
4559
4560 =head2 Can I do multi-line regexes?
4561
4562 No, ack does not support regexes that match multiple lines. Doing
4563 so would require reading in the entire file at a time.
4564
4565 If you want to see lines near your match, use the C<--A>, C<--B>
4566 and C<--C> switches for displaying context.
4567
4568 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
4569
4570 ack treats command line options beginning with C<+> or C<-> as options; if you
4571 would like to search for these, you may prefix your search term with C<--> or
4572 use the C<--match> option. (However, don't forget that C<+> is a regular
4573 expression metacharacter!)
4574
4575 =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex?
4576
4577 The Perl language limits the repetition quanitifier to 32K. You
4578 can search for C<.{32767}> but not C<.{32768}>.
4579
4580 =head1 ACKRC LOCATION SEMANTICS
4581
4582 Ack can load its configuration from many sources. This list
4583 specifies the sources Ack looks for configuration; each one
4584 that is found is loaded in the order specified here, and
4585 each one overrides options set in any of the sources preceding
4586 it. (For example, if I set --sort-files in my user ackrc, and
4587 --nosort-files on the command line, the command line takes
4588 precedence)
4589
4590 =over 4
4591
4592 =item *
4593
4594 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
4595 using C<--ignore-ack-defaults>.
4596
4597 =item * Global ackrc
4598
4599 Options are then loaded from the global ackrc. This is located at
4600 C</etc/ackrc> on Unix-like systems, and
4601 C<C:\Documents and Settings\All Users\Application Data\ackrc> on Windows.
4602 This can be omitted using C<--noenv>.
4603
4604 =item * User ackrc
4605
4606 Options are then loaded from the user's ackrc. This is located at
4607 C<$HOME/.ackrc> on Unix-like systems, and
4608 C<C:\Documents and Settings\$USER\Application Data\ackrc>. If a different
4609 ackrc is desired, it may be overridden with the C<$ACKRC> environment
4610 variable.
4611 This can be omitted using C<--noenv>.
4612
4613 =item * Project ackrc
4614
4615 Options are then loaded from the project ackrc. The project ackrc is
4616 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
4617 in the current directory, then the parent directory, then the grandparent
4618 directory, etc. This can be omitted using C<--noenv>.
4619
4620 =item * --ackrc
4621
4622 The C<--ackrc> option may be included on the command line to specify an
4623 ackrc file that can override all others. It is consulted even if C<--noenv>
4624 is present.
4625
4626 =item * ACK_OPTIONS
4627
4628 Options are then loaded from the environment variable C<ACK_OPTIONS>. This can
4629 be omitted using C<--noenv>.
4630
4631 =item * Command line
4632
4633 Options are then loaded from the command line.
4634
4635 =back
4636
4637 =head1 DIFFERENCES BETWEEN ACK 1.X AND ACK 2.X
4638
4639 A lot of changes were made for ack 2; here is a list of them.
4640
4641 =head2 GENERAL CHANGES
4642
4643 =over 4
4644
4645 =item *
4646
4647 When no selectors are specified, ack 1.x only searches through files that
4648 it can map to a file type. ack 2.x, by contrast, will search through
4649 every regular, non-binary file that is not explicitly ignored via
4650 B<--ignore-file> or B<--ignore-dir>. This is similar to the behavior of the
4651 B<-a/--all> option in ack 1.x.
4652
4653 =item *
4654
4655 A more flexible filter system has been added, so that more powerful file types
4656 may be created by the user. For details, please consult
4657 L</"Defining your own types">.
4658
4659 =item *
4660
4661 ack now loads multiple ackrc files; see L</"ACKRC LOCATION SEMANTICS"> for
4662 details.
4663
4664 =item *
4665
4666 ack's default filter definitions aren't special; you may tell ack to
4667 completely disregard them if you don't like them.
4668
4669 =back
4670
4671 =head2 REMOVED OPTIONS
4672
4673 =over 4
4674
4675 =item *
4676
4677 Because of the change in default search behavior, the B<-a/--all> and
4678 B<-u/--unrestricted> options have been removed. In addition, the
4679 B<-k/--known-types> option was added to cause ack to behave with
4680 the default search behavior of ack 1.x.
4681
4682 =item *
4683
4684 The B<-G> option has been removed. Two regular expressions on the
4685 command line was considered too confusing; to simulate B<-G>'s functionality,
4686 you may use the new B<-x> option to pipe filenames from one invocation of
4687 ack into another.
4688
4689 =item *
4690
4691 The B<--binary> option has been removed.
4692
4693 =item *
4694
4695 The B<--skipped> option has been removed.
4696
4697 =item *
4698
4699 The B<--text> option has been removed.
4700
4701 =item *
4702
4703 The B<--invert-file-match> option has been removed. Instead, you may
4704 use B<-v> with B<-g>.
4705
4706 =back
4707
4708 =head2 CHANGED OPTIONS
4709
4710 =over 4
4711
4712 =item *
4713
4714 The options that modify the regular expression's behavior (B<-i>, B<-w>,
4715 B<-Q>, and B<-v>) may now be used with B<-g>.
4716
4717 =back
4718
4719 =head2 ADDED OPTIONS
4720
4721 =over 4
4722
4723 =item *
4724
4725 B<--files-from> was added so that a user may submit a list of filenames as
4726 a list of files to search.
4727
4728 =item *
4729
4730 B<-x> was added to tell ack to accept a list of filenames via standard input;
4731 this list is the list of filenames that will be used for the search.
4732
4733 =item *
4734
4735 B<-s> was added to tell ack to suppress error messages about non-existent or
4736 unreadable files.
4737
4738 =item *
4739
4740 B<--ignore-directory> and B<--noignore-directory> were added as aliases for
4741 B<--ignore-dir> and B<--noignore-dir> respectively.
4742
4743 =item *
4744
4745 B<--ignore-file> was added so that users may specify patterns of files to
4746 ignore (ex. /.*~$/).
4747
4748 =item *
4749
4750 B<--dump> was added to allow users to easily find out which options are
4751 set where.
4752
4753 =item *
4754
4755 B<--create-ackrc> was added so that users may create custom ackrc files based
4756 on the default settings loaded by ack, and so that users may easily view those
4757 defaults.
4758
4759 =item *
4760
4761 B<--type-del> was added to selectively remove file type definitions.
4762
4763 =item *
4764
4765 B<--ignore-ack-defaults> was added so that users may ignore ack's default
4766 options in favor of their own.
4767
4768 =item *
4769
4770 B<--bar> was added so ack users may consult Admiral Ackbar.
4771
4772 =back
4773
4774 =head1 AUTHOR
4775
4776 Andy Lester, C<< <andy at petdance.com> >>
4777
4778 =head1 BUGS
4779
4780 Please report any bugs or feature requests to the issues list at
4781 Github: L<https://github.com/petdance/ack2/issues>
4782
4783 =head1 ENHANCEMENTS
4784
4785 All enhancement requests MUST first be posted to the ack-users
4786 mailing list at L<http://groups.google.com/group/ack-users>. I
4787 will not consider a request without it first getting seen by other
4788 ack users. This includes requests for new filetypes.
4789
4790 There is a list of enhancements I want to make to F<ack> in the ack
4791 issues list at Github: L<https://github.com/petdance/ack2/issues>
4792
4793 Patches are always welcome, but patches with tests get the most
4794 attention.
4795
4796 =head1 SUPPORT
4797
4798 Support for and information about F<ack> can be found at:
4799
4800 =over 4
4801
4802 =item * The ack homepage
4803
4804 L<http://beyondgrep.com/>
4805
4806 =item * The ack-users mailing list
4807
4808 L<http://groups.google.com/group/ack-users>
4809
4810 =item * The ack issues list at Github
4811
4812 L<https://github.com/petdance/ack2/issues>
4813
4814 =item * AnnoCPAN: Annotated CPAN documentation
4815
4816 L<http://annocpan.org/dist/ack>
4817
4818 =item * CPAN Ratings
4819
4820 L<http://cpanratings.perl.org/d/ack>
4821
4822 =item * Search CPAN
4823
4824 L<http://search.cpan.org/dist/ack>
4825
4826 =item * Git source repository
4827
4828 L<https://github.com/petdance/ack2>
4829
4830 =back
4831
4832 =head1 ACKNOWLEDGEMENTS
4833
4834 How appropriate to have I<ack>nowledgements!
4835
4836 Thanks to everyone who has contributed to ack in any way, including
4837 Michael Beijen,
4838 Alexandr Ciornii,
4839 Christian Walde,
4840 Charles Lee,
4841 Joe McMahon,
4842 John Warwick,
4843 David Steinbrunner,
4844 Kara Martens,
4845 Volodymyr Medvid,
4846 Ron Savage,
4847 Konrad Borowski,
4848 Dale Sedivic,
4849 Michael McClimon,
4850 Andrew Black,
4851 Ralph Bodenner,
4852 Shaun Patterson,
4853 Ryan Olson,
4854 Shlomi Fish,
4855 Karen Etheridge,
4856 Olivier Mengue,
4857 Matthew Wild,
4858 Scott Kyle,
4859 Nick Hooey,
4860 Bo Borgerson,
4861 Mark Szymanski,
4862 Marq Schneider,
4863 Packy Anderson,
4864 JR Boyens,
4865 Dan Sully,
4866 Ryan Niebur,
4867 Kent Fredric,
4868 Mike Morearty,
4869 Ingmar Vanhassel,
4870 Eric Van Dewoestine,
4871 Sitaram Chamarty,
4872 Adam James,
4873 Richard Carlsson,
4874 Pedro Melo,
4875 AJ Schuster,
4876 Phil Jackson,
4877 Michael Schwern,
4878 Jan Dubois,
4879 Christopher J. Madsen,
4880 Matthew Wickline,
4881 David Dyck,
4882 Jason Porritt,
4883 Jjgod Jiang,
4884 Thomas Klausner,
4885 Uri Guttman,
4886 Peter Lewis,
4887 Kevin Riggle,
4888 Ori Avtalion,
4889 Torsten Blix,
4890 Nigel Metheringham,
4891 GE<aacute>bor SzabE<oacute>,
4892 Tod Hagan,
4893 Michael Hendricks,
4894 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
4895 Piers Cawley,
4896 Stephen Steneker,
4897 Elias Lutfallah,
4898 Mark Leighton Fisher,
4899 Matt Diephouse,
4900 Christian Jaeger,
4901 Bill Sully,
4902 Bill Ricker,
4903 David Golden,
4904 Nilson Santos F. Jr,
4905 Elliot Shank,
4906 Merijn Broeren,
4907 Uwe Voelker,
4908 Rick Scott,
4909 Ask BjE<oslash>rn Hansen,
4910 Jerry Gay,
4911 Will Coleda,
4912 Mike O'Regan,
4913 Slaven ReziE<0x107>,
4914 Mark Stosberg,
4915 David Alan Pisoni,
4916 Adriano Ferreira,
4917 James Keenan,
4918 Leland Johnson,
4919 Ricardo Signes,
4920 Pete Krawczyk and
4921 Rob Hoelz.
4922
4923 =head1 COPYRIGHT & LICENSE
4924
4925 Copyright 2005-2013 Andy Lester.
4926
4927 This program is free software; you can redistribute it and/or modify
4928 it under the terms of the Artistic License v2.0.
4929
4930 See http://www.perlfoundation.org/artistic_license_2_0 or the LICENSE.md
4931 file that comes with the ack distribution.
4932
4933 =cut