3 # This file, ack, is generated code.
4 # Please DO NOT EDIT or send patches for it.
6 # Please take a look at the source from
7 # http://github.com/petdance/ack2
8 # and submit patches against the individual files
18 # XXX Don't make this so brute force
19 # See also: https://github.com/petdance/ack2/issues/89
21 use Getopt
::Long
2.36 ();
25 our $VERSION = '2.02';
26 # Check http://beyondgrep.com/ for updates
28 # These are all our globals.
31 $App::Ack
::orig_program_name
= $0;
32 $0 = join(' ', 'ack', $0);
33 if ( $App::Ack
::VERSION
ne $main::VERSION
) {
34 App
::Ack
::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
37 # Do preliminary arg checking;
38 my $env_is_usable = 1;
40 last if ( $_ eq '--' );
42 # Get the --thpppt and --bar checking out of the way.
43 /^--th[pt]+t+$/ && App
::Ack
::_thpppt
($_);
44 /^--bar$/ && App
::Ack
::_bar
();
46 # See if we want to ignore the environment. (Don't tell Al Gore.)
47 if ( /^--(no)?env$/ ) {
48 $env_is_usable = defined $1 ? 0 : 1;
51 if ( !$env_is_usable ) {
52 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
55 App
::Ack
::load_colors
();
57 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
58 Getopt
::Long
::Configure
('pass_through', 'no_auto_abbrev');
59 Getopt
::Long
::GetOptions
(
60 'help' => sub { App
::Ack
::show_help
(); exit; },
61 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
62 'man' => sub { App
::Ack
::show_man
(); exit; },
64 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
67 App
::Ack
::show_help
();
74 sub _compile_descend_filter
{
77 my $idirs = $opt->{idirs
};
78 my $dont_ignore_dirs = $opt->{no_ignore_dirs
};
80 # if we have one or more --noignore-dir directives, we can't ignore
81 # entire subdirectory hierarchies, so we return an "accept all"
82 # filter and scrutinize the files more in _compile_file_filter
83 return if $dont_ignore_dirs;
84 return unless $idirs && @{$idirs};
88 foreach my $idir (@{$idirs}) {
89 if ( $idir =~ /^(\w+):(.*)/ ) {
94 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
98 Carp
::croak
( qq{Invalid filter specification "$idir"} );
103 return !exists $ignore_dirs{$_} && !exists $ignore_dirs{$File::Next
::dir
};
107 sub _compile_file_filter
{
108 my ( $opt, $start ) = @_;
110 my $ifiles = $opt->{ifiles
};
113 my @ifiles_filters = map {
116 if ( /^(\w+):(.+)/ ) {
117 my ($how,$what) = ($1,$2);
118 $filter = App
::Ack
::Filter-
>create_filter($how, split(/,/, $what));
121 Carp
::croak
( qq{Invalid filter specification "$_"} );
126 my $filters = $opt->{'filters'} || [];
127 my $inverse_filters = [ grep { $_->is_inverted() } @{$filters} ];
128 @{$filters} = grep { !$_->is_inverted() } @{$filters};
130 my %is_member_of_starting_set = map { (App
::Ack
::get_file_id
($_) => 1) } @{$start};
132 my $ignore_dir_list = $opt->{idirs
};
133 my $dont_ignore_dir_list = $opt->{no_ignore_dirs
};
136 my %dont_ignore_dir_set;
138 foreach my $filter (@{ $ignore_dir_list }) {
139 if ( $filter =~ /^(\w+):(.*)/ ) {
141 $ignore_dir_set{ $2 } = 1;
143 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
146 Carp
::croak
( qq{Invalid filter specification "$filter"} );
149 foreach my $filter (@{ $dont_ignore_dir_list }) {
150 if ( $filter =~ /^(\w+):(.*)/ ) {
152 $dont_ignore_dir_set{ $2 } = 1;
154 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
157 Carp
::croak
( qq{Invalid filter specification "$filter"} );
162 # ack always selects files that are specified on the command
163 # line, regardless of filetype. If you want to ack a JPEG,
164 # and say "ack foo whatever.jpg" it will do it for you.
165 return 1 if $is_member_of_starting_set{ App
::Ack
::get_file_id
($File::Next
::name
) };
167 if ( $dont_ignore_dir_list ) {
168 my ( undef, $dirname ) = File
::Spec-
>splitpath($File::Next
::name
);
169 my @dirs = File
::Spec-
>splitdir($dirname);
173 foreach my $dir ( @dirs ) {
174 if ( $ignore_dir_set{ $dir } ) {
177 elsif ( $dont_ignore_dir_set{ $dir } ) {
181 if ( $is_ignoring ) {
186 # Ignore named pipes found in directory searching. Named
187 # pipes created by subprocesses get specified on the command
188 # line, so the rule of "always select whatever is on the
189 # command line" wins.
190 return 0 if -p
$File::Next
::name
;
192 foreach my $filter (@ifiles_filters) {
193 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
194 return 0 if ! $resource || $filter->filter($resource);
200 foreach my $filter (@{$filters}) {
201 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
202 return 0 if ! $resource;
203 if ($filter->filter($resource)) {
209 # Don't bother invoking inverse filters unless we consider the current resource a match
210 if ( $match_found && @{$inverse_filters} ) {
211 foreach my $filter ( @{$inverse_filters} ) {
212 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
213 return 0 if ! $resource;
214 if ( not $filter->filter( $resource ) ) {
225 my $resource = shift;
228 my @types = App
::Ack
::filetypes
( $resource );
229 my $types = join( ',', @types );
230 my $arrow = @types ? ' => ' : ' =>';
231 App
::Ack
::print( $resource->name, $arrow, join( ',', @types ), $ors );
237 my @arg_sources = App
::Ack
::retrieve_arg_sources
();
239 my $opt = App
::Ack
::ConfigLoader
::process_args
( @arg_sources );
241 $App::Ack
::report_bad_filenames
= !$opt->{dont_report_bad_filenames
};
243 if ( $opt->{flush
} ) {
247 if ( not defined $opt->{color
} ) {
248 $opt->{color
} = !App
::Ack
::output_to_pipe
() && !$App::Ack
::is_windows
;
250 if ( not defined $opt->{heading
} and not defined $opt->{break} ) {
251 $opt->{heading
} = $opt->{break} = !App
::Ack
::output_to_pipe
();
254 if ( defined($opt->{H
}) || defined($opt->{h
}) ) {
255 $opt->{show_filename
}= $opt->{H
} && !$opt->{h
};
258 if ( my $output = $opt->{output
} ) {
259 $output =~ s{\\}{\\\\}g;
260 $output =~ s{"}{\\"}g;
261 $opt->{output
} = qq{"$output"};
265 if ( $App::Ack
::is_filter_mode
&& !$opt->{files_from
} ) { # probably -x
266 $resources = App
::Ack
::Resources-
>from_stdin( $opt );
267 my $regex = $opt->{regex
};
268 $regex = shift @ARGV if not defined $regex;
269 $opt->{regex
} = App
::Ack
::build_regex
( $regex, $opt );
272 if ( $opt->{f
} || $opt->{lines
} ) {
273 if ( $opt->{regex
} ) {
274 App
::Ack
::warn( "regex ($opt->{regex}) specified with -f or --lines" );
275 App
::Ack
::exit_from_ack
( 0 ); # XXX the 0 is misleading
279 my $regex = $opt->{regex
};
280 $regex = shift @ARGV if not defined $regex;
281 $opt->{regex
} = App
::Ack
::build_regex
( $regex, $opt );
284 if ( not defined $opt->{files_from
} ) {
287 if ( !exists($opt->{show_filename
}) ) {
288 unless(@start == 1 && !(-d
$start[0])) {
289 $opt->{show_filename
} = 1;
293 if ( defined $opt->{files_from
} ) {
294 $resources = App
::Ack
::Resources-
>from_file( $opt, $opt->{files_from
} );
295 exit 1 unless $resources;
298 @start = ('.') unless @start;
299 foreach my $target (@start) {
300 if ( !-e
$target && $App::Ack
::report_bad_filenames
) {
301 App
::Ack
::warn( "$target: No such file or directory" );
305 $opt->{file_filter
} = _compile_file_filter
($opt, \
@start);
306 $opt->{descend_filter
} = _compile_descend_filter
($opt);
308 $resources = App
::Ack
::Resources-
>from_argv( $opt, \
@start );
311 App
::Ack
::set_up_pager
( $opt->{pager
} ) if defined $opt->{pager
};
313 my $print_filenames = $opt->{show_filename
};
314 my $max_count = $opt->{m
};
315 my $ors = $opt->{print0
} ? "\0" : "\n";
316 my $only_first = $opt->{1};
321 while ( my $resource = $resources->next ) {
322 # XXX this variable name combined with what we're trying
323 # to do makes no sense.
325 # XXX Combine the -f and -g functions
327 # XXX printing should probably happen inside of App::Ack
328 if ( $opt->{show_types
} ) {
329 show_types
( $resource, $ors );
332 App
::Ack
::print( $resource->name, $ors );
335 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
337 elsif ( $opt->{g
} ) {
338 my $is_match = ( $resource->name =~ /$opt->{regex}/o );
339 if ( $opt->{v
} ? !$is_match : $is_match ) {
340 if ( $opt->{show_types
} ) {
341 show_types
( $resource, $ors );
344 App
::Ack
::print( $resource->name, $ors );
347 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
350 elsif ( $opt->{lines
} ) {
351 my $print_filename = $opt->{show_filename
};
352 my $passthru = $opt->{passthru
};
355 foreach my $line ( @{ $opt->{lines
} } ) {
356 my @lines = split /,/, $line;
362 @line_numbers{@lines} = (1) x
@lines;
365 my $filename = $resource->name;
367 local $opt->{color
} = 0;
369 App
::Ack
::iterate
($resource, $opt, sub {
372 if ( $line_numbers{$.} ) {
373 App
::Ack
::print_line_with_context
($opt, $filename, $_, $.);
375 elsif ( $passthru ) {
376 App
::Ack
::print_line_with_options
($opt, $filename, $_, $., ':');
381 elsif ( $opt->{count
} ) {
382 my $matches_for_this_file = App
::Ack
::count_matches_in_resource
( $resource, $opt );
384 unless ( $opt->{show_filename
} ) {
385 $total_count += $matches_for_this_file;
389 if ( !$opt->{l
} || $matches_for_this_file > 0) {
390 if ( $print_filenames ) {
391 App
::Ack
::print( $resource->name, ':', $matches_for_this_file, $ors );
394 App
::Ack
::print( $matches_for_this_file, $ors );
398 elsif ( $opt->{l
} || $opt->{L
} ) {
399 my $is_match = App
::Ack
::resource_has_match
( $resource, $opt );
401 if ( $opt->{L
} ? !$is_match : $is_match ) {
402 App
::Ack
::print( $resource->name, $ors );
405 last RESOURCES
if $only_first;
406 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
410 $nmatches += App
::Ack
::print_matches_in_resource
( $resource, $opt );
411 if ( $nmatches && $only_first ) {
417 if ( $opt->{count
} && !$opt->{show_filename
} ) {
418 App
::Ack
::print( $total_count, "\n" );
422 App
::Ack
::exit_from_ack
( $nmatches );
428 ack - grep-like text finder
432 ack [options] PATTERN [FILE...]
433 ack -f [options] [DIRECTORY...]
437 Ack is designed as a replacement for 99% of the uses of F<grep>.
439 Ack searches the named input FILEs (or standard input if no files
440 are named, or the file name - is given) for lines containing a match
441 to the given PATTERN. By default, ack prints the matching lines.
443 PATTERN is a Perl regular expression. Perl regular expressions
444 are commonly found in other programming languages, but for the particulars
445 of their behavior, please consult
446 L<http://perldoc.perl.org/perlreref.html|perlreref>. If you don't know
447 how to use regular expression but are interested in learning, you may
448 consult L<http://perldoc.perl.org/perlretut.html|perlretut>. If you do not
449 need or want ack to use regular expressions, please see the
450 C<-Q>/C<--literal> option.
452 Ack can also list files that would be searched, without actually
453 searching them, to let you take advantage of ack's file-type filtering
456 =head1 FILE SELECTION
458 If files are not specified for searching, either on the command
459 line or piped in with the C<-x> option, I<ack> delves into
460 subdirectories selecting files for searching.
462 I<ack> is intelligent about the files it searches. It knows about
463 certain file types, based on both the extension on the file and,
464 in some cases, the contents of the file. These selections can be
465 made with the B<--type> option.
467 With no file selection, I<ack> searches through regular files that
468 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
469 options, either present in F<ackrc> files or on the command line.
471 The default options for I<ack> ignore certain files and directories. These
476 =item * Backup files: Files matching F<#*#> or ending with F<~>.
478 =item * Coredumps: Files matching F<core.\d+>
480 =item * Version control directories like F<.svn> and F<.git>.
484 Run I<ack> with the C<--dump> option to see what settings are set.
486 However, I<ack> always searches the files given on the command line,
487 no matter what type. If you tell I<ack> to search in a coredump,
488 it will search in a coredump.
490 =head1 DIRECTORY SELECTION
492 I<ack> descends through the directory tree of the starting directories
493 specified. If no directories are specified, the current working directory is
494 used. However, it will ignore the shadow directories used by
495 many version control systems, and the build directories used by the
496 Perl MakeMaker system. You may add or remove a directory from this
497 list with the B<--[no]ignore-dir> option. The option may be repeated
498 to add/remove multiple directories from the ignore list.
500 For a complete list of directories that do not get searched, run
503 =head1 WHEN TO USE GREP
505 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
506 throw I<grep> away, because there are times you'll still need it.
508 E.g., searching through huge files looking for regexes that can be
509 expressed with I<grep> syntax should be quicker with I<grep>.
511 If your script or parent program uses I<grep> C<--quiet> or C<--silent>
512 or needs exit 2 on IO error, use I<grep>.
518 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
520 Print I<NUM> lines of trailing context after matching lines.
522 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
524 Print I<NUM> lines of leading context before matching lines.
528 Print a break between results from different files. On by default
529 when used interactively.
531 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
533 Print I<NUM> lines (default 2) of context around matching lines.
535 =item B<-c>, B<--count>
537 Suppress normal output; instead print a count of matching lines for
538 each input file. If B<-l> is in effect, it will only show the
539 number of lines for each file that has lines matching. Without
540 B<-l>, some line counts may be zeroes.
542 If combined with B<-h> (B<--no-filename>) ack outputs only one total
545 =item B<--[no]color>, B<--[no]colour>
547 B<--color> highlights the matching text. B<--nocolor> supresses
548 the color. This is on by default unless the output is redirected.
550 On Windows, this option is off by default unless the
551 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
552 environment variable is used.
554 =item B<--color-filename=I<color>>
556 Sets the color to be used for filenames.
558 =item B<--color-match=I<color>>
560 Sets the color to be used for matches.
562 =item B<--color-lineno=I<color>>
564 Sets the color to be used for line numbers.
566 =item B<--[no]column>
568 Show the column number of the first match. This is helpful for
569 editors that can place your cursor at a given position.
571 =item B<--create-ackrc>
573 Dumps the default ack options to standard output. This is useful for
574 when you want to customize the defaults.
578 Writes the list of options loaded and where they came from to standard
579 output. Handy for debugging.
583 B<--noenv> disables all environment processing. No F<.ackrc> is
584 read and all environment variables are ignored. By default, F<ack>
585 considers F<.ackrc> and settings in the environment.
589 B<--flush> flushes output immediately. This is off by default
590 unless ack is running interactively (when output goes to a pipe or
595 Only print the files that would be searched, without actually doing
596 any searching. PATTERN must not be specified, or it will be taken
599 =item B<--files-from=I<FILE>>
601 The list of files to be searched is specified in I<FILE>. The list of
602 files are seperated by newlines. If I<FILE> is C<->, the list is loaded
605 =item B<--[no]filter>
607 Forces ack to act as if it were recieving input via a pipe.
609 =item B<--[no]follow>
611 Follow or don't follow symlinks, other than whatever starting files
612 or directories were specified on the command line.
614 This is off by default.
616 =item B<-g I<PATTERN>>
618 Print files where the relative path + filename matches I<PATTERN>.
622 B<--group> groups matches by file name. This is the default
623 when used interactively.
625 B<--nogroup> prints one result per line, like grep. This is the
626 default when output is redirected.
628 =item B<-H>, B<--with-filename>
630 Print the filename for each match. This is the default unless searching
631 a single explicitly specified file.
633 =item B<-h>, B<--no-filename>
635 Suppress the prefixing of filenames on output when multiple files are
638 =item B<--[no]heading>
640 Print a filename heading above each file's results. This is the default
641 when used interactively.
643 =item B<--help>, B<-?>
645 Print a short help statement.
647 =item B<--help-types>, B<--help=types>
649 Print all known types.
651 =item B<-i>, B<--ignore-case>
653 Ignore case distinctions in PATTERN
655 =item B<--ignore-ack-defaults>
657 Tells ack to completely ignore the default definitions provided with ack.
658 This is useful in combination with B<--create-ackrc> if you I<really> want
661 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
663 Ignore directory (as CVS, .svn, etc are ignored). May be used
664 multiple times to ignore multiple directories. For example, mason
665 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
666 option allows users to search directories which would normally be
667 ignored (perhaps to research the contents of F<.svn/props> directories).
669 The I<DIRNAME> must always be a simple directory name. Nested
670 directories like F<foo/bar> are NOT supported. You would need to
671 specify B<--ignore-dir=foo> and then no files from any foo directory
672 are taken into account by ack unless given explicitly on the command
675 =item B<--ignore-file=I<FILTERTYPE:FILTERARGS>>
677 Ignore files matching I<FILTERTYPE:FILTERARGS>. The filters are specified
678 identically to file type filters as seen in L</"Defining your own types">.
680 =item B<-k>, B<--known-types>
682 Limit selected files to those with types that ack knows about. This is
683 equivalent to the default behavior found in ack 1.
685 =item B<--lines=I<NUM>>
687 Only print line I<NUM> of each file. Multiple lines can be given with multiple
688 B<--lines> options or as a comma separated list (B<--lines=3,5,7>). B<--lines=4-7>
689 also works. The lines are always output in ascending order, no matter the
690 order given on the command line.
692 =item B<-l>, B<--files-with-matches>
694 Only print the filenames of matching files, instead of the matching text.
696 =item B<-L>, B<--files-without-matches>
698 Only print the filenames of files that do I<NOT> match.
700 =item B<--match I<PATTERN>>
702 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
703 regex as your first argument, e.g. when executing multiple searches over the
706 # search for foo and bar in given files
707 ack file1 t/file* --match foo
708 ack file1 t/file* --match bar
710 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
712 Stop reading a file after I<NUM> matches.
716 Print this manual page.
718 =item B<-n>, B<--no-recurse>
720 No descending into subdirectories.
724 Show only the part of each line matching PATTERN (turns off text
727 =item B<--output=I<expr>>
729 Output the evaluation of I<expr> for each line (turns off text
731 If PATTERN matches more than once then a line is output for each non-overlapping match.
732 For more information please see the section L</"Examples of F<--output>">.
734 =item B<--pager=I<program>>, B<--nopager>
736 B<--pager> directs ack's output through I<program>. This can also be specified
737 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
739 Using --pager does not suppress grouping and coloring like piping
740 output on the command-line does.
742 B<--nopager> cancels any setting in ~/.ackrc, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
743 No output will be sent through a pager.
747 Prints all lines, whether or not they match the expression. Highlighting
748 will still work, though, so it can be used to highlight matches while
749 still seeing the entire file, as in:
751 # Watch a log file, and highlight a certain IP address
752 $ tail -f ~/access.log | ack --passthru 123.45.67.89
756 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
757 are output separated with a null byte instead of the usual newline. This is
758 helpful when dealing with filenames that contain whitespace, e.g.
760 # remove all files of type html
761 ack -f --html --print0 | xargs -0 rm -f
763 =item B<-Q>, B<--literal>
765 Quote all metacharacters in PATTERN, it is treated as a literal.
767 =item B<-r>, B<-R>, B<--recurse>
769 Recurse into sub-directories. This is the default and just here for
770 compatibility with grep. You can also use it for turning B<--no-recurse> off.
774 Suppress error messages about nonexistent or unreadable files. This is taken
777 =item B<--[no]smart-case>, B<--no-smart-case>
779 Ignore case in the search strings if PATTERN contains no uppercase
780 characters. This is similar to C<smartcase> in vim. This option is
781 off by default, and ignored if C<-i> is specified.
783 B<-i> always overrides this option.
785 =item B<--sort-files>
787 Sorts the found files lexicographically. Use this if you want your file
788 listings to be deterministic between runs of I<ack>.
790 =item B<--show-types>
792 Outputs the filetypes that ack associates with each file.
794 Works with B<-f> and B<-g> options.
796 =item B<--type=[no]TYPE>
798 Specify the types of files to include or exclude from a search.
799 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
800 also be specified as B<--perl>, and B<--type=noperl> can be done
803 If a file is of both type "foo" and "bar", specifying --foo and
804 --nobar will exclude the file, because an exclusion takes precedence
807 Type specifications can be repeated and are ORed together.
809 See I<ack --help=types> for a list of valid types.
811 =item B<--type-add I<TYPE>:I<FILTER>:I<FILTERARGS>>
813 Files with the given FILTERARGS applied to the given FILTER
814 are recognized as being of (the existing) type TYPE.
815 See also L</"Defining your own types">.
818 =item B<--type-set I<TYPE>:I<FILTER>:I<FILTERARGS>>
820 Files with the given FILTERARGS applied to the given FILTER are recognized as
821 being of type TYPE. This replaces an existing definition for type TYPE. See
822 also L</"Defining your own types">.
824 =item B<--type-del I<TYPE>>
826 The filters associated with TYPE are removed from Ack, and are no longer considered
829 =item B<-v>, B<--invert-match>
831 Invert match: select non-matching lines
835 Display version and copyright information.
837 =item B<-w>, B<--word-regexp>
839 Force PATTERN to match only whole words. The PATTERN is wrapped with
840 C<\b> metacharacters.
844 An abbreviation for B<--files-from=->; the list of files to search are read
845 from standard input, with one line per file.
849 Stops after reporting first match of any kind. This is different
850 from B<--max-count=1> or B<-m1>, where only one match per file is
851 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
856 Display the all-important Bill The Cat logo. Note that the exact
857 spelling of B<--thpppppt> is not important. It's checked against
858 a regular expression.
862 Check with the admiral for traps.
866 =head1 THE .ackrc FILE
868 The F<.ackrc> file contains command-line options that are prepended
869 to the command line before processing. Multiple options may live
870 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
871 might look like this:
873 # Always sort the files
876 # Always color, even if piping to a another program
879 # Use "less -r" as my pager
882 Note that arguments with spaces in them do not need to be quoted,
883 as they are not interpreted by the shell. Basically, each I<line>
884 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
886 F<ack> looks in several locations for F<.ackrc> files; the searching
887 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
888 files are not considered if B<--noenv> is specified on the command line.
890 =head1 Defining your own types
892 ack allows you to define your own types in addition to the predefined
893 types. This is done with command line options that are best put into
894 an F<.ackrc> file - then you do not have to define your types over and
895 over again. In the following examples the options will always be shown
896 on one command line so that they can be easily copy & pasted.
898 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
899 tells you, that perl files are files ending
900 in .pl, .pm, .pod or .t. So what if you would like to include .xs
901 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
902 does this for you. B<--type-add> appends
903 additional extensions to an existing type.
905 If you want to define a new type, or completely redefine an existing
906 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
907 the type I<eiffel> to include files with
908 the extensions .e or .eiffel. So to search for all eiffel files
909 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
910 As usual, you can also write B<--type=eiffel>
911 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
912 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
913 and I<.xs> files no longer belong to the type I<cc>.
915 When defining your own types in the F<.ackrc> file you have to use
918 --type-set=eiffel:ext:e,eiffel
920 or writing on separate lines
925 The following does B<NOT> work in the F<.ackrc> file:
927 --type-set eiffel:ext:e,eiffel
930 In order to see all currently defined types, use I<--help-types>, e.g.
931 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
933 In addition to filtering based on extension (like ack 1.x allowed), ack 2
934 offers additional filter types. The generic syntax is
935 I<--type-set TYPE:FILTER:FILTERARGS>; I<FILTERARGS> depends on the value
942 I<is> filters match the target filename exactly. It takes exactly one
943 argument, which is the name of the file to match.
947 --type-set make:is:Makefile
949 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
951 I<ext> filters match the extension of the target file against a list
952 of extensions. No leading dot is needed for the extensions.
956 --type-set perl:ext:pl,pm,t
958 =item match:I<PATTERN>
960 I<match> filters match the target filename against a regular expression.
961 The regular expression is made case insensitive for the search.
965 --type-set make:match:/(gnu)?makefile/
967 =item firstlinematch:I<PATTERN>
969 I<firstlinematch> matches the first line of the target file against a
970 regular expression. Like I<match>, the regular expression is made
975 --type-add perl:firstlinematch:/perl/
979 More filter types may be made available in the future.
981 =head1 ENVIRONMENT VARIABLES
983 For commonly-used ack options, environment variables can make life
984 much easier. These variables are ignored if B<--noenv> is specified
991 Specifies the location of the user's F<.ackrc> file. If this file doesn't
992 exist, F<ack> looks in the default location.
996 This variable specifies default options to be placed in front of
997 any explicit options on the command line.
999 =item ACK_COLOR_FILENAME
1001 Specifies the color of the filename when it's printed in B<--group>
1002 mode. By default, it's "bold green".
1004 The recognized attributes are clear, reset, dark, bold, underline,
1005 underscore, blink, reverse, concealed black, red, green, yellow,
1006 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
1007 on_magenta, on_cyan, and on_white. Case is not significant.
1008 Underline and underscore are equivalent, as are clear and reset.
1009 The color alone sets the foreground color, and on_color sets the
1012 This option can also be set with B<--color-filename>.
1014 =item ACK_COLOR_MATCH
1016 Specifies the color of the matching text when printed in B<--color>
1017 mode. By default, it's "black on_yellow".
1019 This option can also be set with B<--color-match>.
1021 See B<ACK_COLOR_FILENAME> for the color specifications.
1023 =item ACK_COLOR_LINENO
1025 Specifies the color of the line number when printed in B<--color>
1026 mode. By default, it's "bold yellow".
1028 This option can also be set with B<--color-lineno>.
1030 See B<ACK_COLOR_FILENAME> for the color specifications.
1034 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
1035 ack will send its output.
1037 Using C<ACK_PAGER> does not suppress grouping and coloring like
1038 piping output on the command-line does, except that on Windows
1039 ack will assume that C<ACK_PAGER> does not support color.
1041 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
1043 =item ACK_PAGER_COLOR
1045 Specifies a pager program that understands ANSI color sequences.
1046 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
1047 like piping output on the command-line does.
1049 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
1053 =head1 ACK & OTHER TOOLS
1055 =head2 Vim integration
1057 F<ack> integrates easily with the Vim text editor. Set this in your
1058 F<.vimrc> to use F<ack> instead of F<grep>:
1062 That example uses C<-k> to search through only files of the types ack
1063 knows about, but you may use other default flags. Now you can search
1064 with F<ack> and easily step through the results in Vim:
1066 :grep Dumper perllib
1068 Miles Sterrett has written a Vim plugin for F<ack> which allows you to use
1069 C<:Ack> instead of C<:grep>, as well as several other advanced features.
1071 L<https://github.com/mileszs/ack.vim>
1073 =head2 Emacs integration
1075 Phil Jackson put together an F<ack.el> extension that "provides a
1076 simple compilation mode ... has the ability to guess what files you
1077 want to search for based on the major-mode."
1079 L<http://www.shellarchive.co.uk/content/emacs.html>
1081 =head2 TextMate integration
1083 Pedro Melo is a TextMate user who writes "I spend my day mostly
1084 inside TextMate, and the built-in find-in-project sucks with large
1085 projects. So I hacked a TextMate command that was using find +
1086 grep to use ack. The result is the Search in Project with ack, and
1087 you can find it here:
1088 L<http://www.simplicidade.org/notes/archives/2008/03/search_in_proje.html>"
1090 =head2 Shell and Return Code
1092 For greater compatibility with I<grep>, I<ack> in normal use returns
1093 shell return or exit code of 0 only if something is found and 1 if
1096 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
1098 The I<grep> code 2 for errors is not used.
1100 If C<-f> or C<-g> are specified, then 0 is returned if at least one
1101 file is found. If no files are found, then 1 is returned.
1105 =head1 DEBUGGING ACK PROBLEMS
1107 If ack gives you output you're not expecting, start with a few simple steps.
1109 =head2 Use B<--noenv>
1111 Your environment variables and F<.ackrc> may be doing things you're
1112 not expecting, or forgotten you specified. Use B<--noenv> to ignore
1113 your environment and F<.ackrc>.
1115 =head2 Use B<-f> to see what files have been selected
1117 Ack's B<-f> was originally added as a debugging tool. If ack is
1118 not finding matches you think it should find, run F<ack -f> to see
1119 what files have been selected. You can also add the C<--show-types>
1120 options to show the type of each file selected.
1122 =head2 Use B<--dump>
1124 This lists the ackrc files that are loaded and the options loaded
1126 So for example you can find a list of directories that do not get searched or where filetypes are defined.
1130 =head2 Use the F<.ackrc> file.
1132 The F<.ackrc> is the place to put all your options you use most of
1133 the time but don't want to remember. Put all your --type-add and
1134 --type-set definitions in it. If you like --smart-case, set it
1135 there, too. I also set --sort-files there.
1137 =head2 Use F<-f> for working with big codesets
1139 Ack does more than search files. C<ack -f --perl> will create a
1140 list of all the Perl files in a tree, ideal for sending into F<xargs>.
1143 # Change all "this" to "that" in all Perl files in a tree.
1144 ack -f --perl | xargs perl -p -i -e's/this/that/g'
1148 perl -p -i -e's/this/that/g' $(ack -f --perl)
1150 =head2 Use F<-Q> when in doubt about metacharacters
1152 If you're searching for something with a regular expression
1153 metacharacter, most often a period in a filename or IP address, add
1154 the -Q to avoid false positives without all the backslashing. See
1155 the following example for more...
1157 =head2 Use ack to watch log files
1159 Here's one I used the other day to find trouble spots for a website
1160 visitor. The user had a problem loading F<troublesome.gif>, so I
1161 took the access log and scanned it with ack twice.
1163 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
1165 The first ack finds only the lines in the Apache log for the given
1166 IP. The second finds the match on my troublesome GIF, and shows
1167 the previous five lines from the log in each case.
1169 =head2 Examples of F<--output>
1171 Following variables are useful in the expansion string:
1177 The whole string matched by PATTERN.
1179 =item C<$1>, C<$2>, ...
1181 The contents of the 1st, 2nd ... bracketed group in PATTERN.
1185 The string before the match.
1189 The string after the match.
1193 For more details and other variables see
1194 L<http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions|perlvar>.
1196 This example shows how to add text around a particular pattern
1197 (in this case adding _ around word with "e")
1199 ack2.pl "\w*e\w*" quick.txt --output="$`_$&_$'"
1200 _The_ quick brown fox jumps over the lazy dog
1201 The quick brown fox jumps _over_ the lazy dog
1202 The quick brown fox jumps over _the_ lazy dog
1204 This shows how to pick out particular parts of a match using ( ) within regular expression.
1206 ack '=head(\d+)\s+(.*)' --output=' $1 : $2'
1207 input file contains "=head1 NAME"
1210 =head2 Share your knowledge
1212 Join the ack-users mailing list. Send me your tips and I may add
1217 =head2 Why isn't ack finding a match in (some file)?
1219 Probably because it's of a type that ack doesn't recognize. ack's
1220 searching behavior is driven by filetype. B<If ack doesn't know
1221 what kind of file it is, ack ignores the file.>
1223 Use the C<-f> switch to see a list of files that ack will search
1226 If you want ack to search files that it doesn't recognize, use the
1229 If you want ack to search every file, even ones that it always
1230 ignores like coredumps and backup files, use the C<-u> switch.
1232 =head2 Why does ack ignore unknown files by default?
1234 ack is designed by a programmer, for programmers, for searching
1235 large trees of code. Most codebases have a lot files in them which
1236 aren't source files (like compiled object files, source control
1237 metadata, etc), and grep wastes a lot of time searching through all
1238 of those as well and returning matches from those files.
1240 That's why ack's behavior of not searching things it doesn't recognize
1241 is one of its greatest strengths: the speed you get from only
1242 searching the things that you want to be looking at.
1244 =head2 Wouldn't it be great if F<ack> did search & replace?
1246 No, ack will always be read-only. Perl has a perfectly good way
1247 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
1250 You can certainly use ack to select your files to update. For
1251 example, to change all "foo" to "bar" in all PHP files, you can do
1252 this from the Unix shell:
1254 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
1256 =head2 Can you make ack recognize F<.xyz> files?
1258 Yes! Please see L</"Defining your own types">. If you think
1259 that F<ack> should recognize a type by default, please see
1262 =head2 There's already a program/package called ack.
1266 =head2 Why is it called ack if it's called ack-grep?
1268 The name of the program is "ack". Some packagers have called it
1269 "ack-grep" when creating packages because there's already a package
1270 out there called "ack" that has nothing to do with this ack.
1272 I suggest you make a symlink named F<ack> that points to F<ack-grep>
1273 because one of the crucial benefits of ack is having a name that's
1274 so short and simple to type.
1276 To do that, run this with F<sudo> or as root:
1278 ln -s /usr/bin/ack-grep /usr/bin/ack
1280 Alternatively, you could use a shell alias:
1288 =head2 What does F<ack> mean?
1290 Nothing. I wanted a name that was easy to type and that you could
1291 pronounce as a single syllable.
1293 =head2 Can I do multi-line regexes?
1295 No, ack does not support regexes that match multiple lines. Doing
1296 so would require reading in the entire file at a time.
1298 If you want to see lines near your match, use the C<--A>, C<--B>
1299 and C<--C> switches for displaying context.
1301 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
1303 ack treats command line options beginning with C<+> or C<-> as options; if you
1304 would like to search for these, you may prefix your search term with C<--> or
1305 use the C<--match> option. (However, don't forget that C<+> is a regular
1306 expression metacharacter!)
1308 =head1 ACKRC LOCATION SEMANTICS
1310 Ack can load its configuration from many sources. This list
1311 specifies the sources Ack looks for configuration; each one
1312 that is found is loaded in the order specified here, and
1313 each one overrides options set in any of the sources preceding
1314 it. (For example, if I set --sort-files in my user ackrc, and
1315 --nosort-files on the command line, the command line takes
1322 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
1323 using C<--ignore-ack-defaults>.
1325 =item * Global ackrc
1327 Options are then loaded from the global ackrc. This is located at
1328 C</etc/ackrc> on Unix-like systems, and
1329 C<C:\Documents and Settings\All Users\Application Data> on Windows.
1330 This can be omitted using C<--noenv>.
1334 Options are then loaded from the user's ackrc. This is located at
1335 C<$HOME/.ackrc> on Unix-like systems, and
1336 C<C:\Documents and Settings\$USER\Application Data>. If a different
1337 ackrc is desired, it may be overriden with the C<$ACKRC> environment
1339 This can be omitted using C<--noenv>.
1341 =item * Project ackrc
1343 Options are then loaded from the project ackrc. The project ackrc is
1344 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
1345 in the current directory, then the parent directory, then the grandparent
1346 directory, etc. This can be omitted using C<--noenv>.
1350 Options are then loaded from the enviroment variable C<ACK_OPTIONS>. This can
1351 be omitted using C<--noenv>.
1353 =item * Command line
1355 Options are then loaded from the command line.
1359 =head1 DIFFERENCES BETWEEN ACK 1.X AND ACK 2.X
1361 A lot of changes were made for ack 2; here is a list of them.
1363 =head2 GENERAL CHANGES
1369 When no selectors are specified, ack 1.x only searches through files that
1370 it can map to a file type. ack 2.x, by constrast, will search through
1371 every regular, non-binary file that is not explicitly ignored via
1372 B<--ignore-file> or B<--ignore-dir>. This is similar to the behavior of the
1373 B<-a/--all> option in ack 1.x.
1377 A more flexible filter system has been added, so that more powerful file types
1378 may be created by the user. For details, please consult
1379 L</"Defining your own types">.
1383 ack now loads multiple ackrc files; see L</"ACKRC LOCATION SEMANTICS"> for
1388 ack's default filter definitions aren't special; you may tell ack to
1389 completely disregard them if you don't like them.
1393 =head2 REMOVED OPTIONS
1399 Because of the change in default search behavior, the B<-a/--all> and
1400 B<-u/--unrestricted> options have been removed. In addition, the
1401 B<-k/--known-types> option was added to cause ack to behave with
1402 the default search behavior of ack 1.x.
1406 The B<-G> option has been removed. Two regular expressions on the
1407 command line was considered too confusing; to simulate B<-G>'s functionality,
1408 you may use the new B<-x> option to pipe filenames from one invocation of
1413 The B<--binary> option has been removed.
1417 The B<--skipped> option has been removed.
1421 The B<--text> option has been removed.
1425 The B<--invert-file-match> option has been removed. Instead, you may
1426 use B<-v> with B<-g>.
1430 =head2 CHANGED OPTIONS
1436 The options that modify the regular expression's behavior (B<-i>, B<-w>,
1437 B<-Q>, and B<-v>) may now be used with B<-g>.
1441 =head2 ADDED OPTIONS
1447 B<--files-from> was added so that a user may submit a list of filenames as
1448 a list of files to search.
1452 B<-x> was added to tell ack to accept a list of filenames via standard input;
1453 this list is the list of filenames that will be used for the search.
1457 B<-s> was added to tell ack to suppress error messages about non-existent or
1462 B<--ignore-directory> and B<--noignore-directory> were added as aliases for
1463 B<--ignore-dir> and B<--noignore-dir> respectively.
1467 B<--ignore-file> was added so that users may specify patterns of files to
1468 ignore (ex. /.*~$/).
1472 B<--dump> was added to allow users to easily find out which options are
1477 B<--create-ackrc> was added so that users may create custom ackrc files based
1478 on the default settings loaded by ack, and so that users may easily view those
1483 B<--type-del> was added to selectively remove file type definitions.
1487 B<--ignore-ack-defaults> was added so that users may ignore ack's default
1488 options in favor of their own.
1492 B<--bar> was added so ack users may consult Admiral Ackbar.
1498 Andy Lester, C<< <andy at petdance.com> >>
1502 Please report any bugs or feature requests to the issues list at
1503 Github: L<https://github.com/petdance/ack2/issues>
1507 All enhancement requests MUST first be posted to the ack-users
1508 mailing list at L<http://groups.google.com/group/ack-users>. I
1509 will not consider a request without it first getting seen by other
1510 ack users. This includes requests for new filetypes.
1512 There is a list of enhancements I want to make to F<ack> in the ack
1513 issues list at Github: L<https://github.com/petdance/ack2/issues>
1515 Patches are always welcome, but patches with tests get the most
1520 Support for and information about F<ack> can be found at:
1524 =item * The ack homepage
1526 L<http://beyondgrep.com/>
1528 =item * The ack-users mailing list
1530 L<http://groups.google.com/group/ack-users>
1532 =item * The ack issues list at Github
1534 L<https://github.com/petdance/ack2/issues>
1536 =item * AnnoCPAN: Annotated CPAN documentation
1538 L<http://annocpan.org/dist/ack>
1540 =item * CPAN Ratings
1542 L<http://cpanratings.perl.org/d/ack>
1546 L<http://search.cpan.org/dist/ack>
1548 =item * Git source repository
1550 L<https://github.com/petdance/ack2>
1554 =head1 ACKNOWLEDGEMENTS
1556 How appropriate to have I<ack>nowledgements!
1558 Thanks to everyone who has contributed to ack in any way, including
1580 Eric Van Dewoestine,
1589 Christopher J. Madsen,
1601 GE<aacute>bor SzabE<oacute>,
1604 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
1608 Mark Leighton Fisher,
1614 Nilson Santos F. Jr,
1619 Ask BjE<oslash>rn Hansen,
1623 Slaven ReziE<0x107>,
1633 =head1 COPYRIGHT & LICENSE
1635 Copyright 2005-2013 Andy Lester.
1637 This program is free software; you can redistribute it and/or modify
1638 it under the terms of the Artistic License v2.0.
1640 See http://www.perlfoundation.org/artistic_license_2_0 or the LICENSE.md
1641 file that comes with the ack distribution.
1650 our $VERSION = '1.12';
1656 our $name; # name of the current file
1657 our $dir; # dir of the current file
1659 our %files_defaults;
1664 file_filter
=> undef,
1665 descend_filter
=> undef,
1666 error_handler
=> sub { CORE
::die @_ },
1667 warning_handler
=> sub { CORE
::warn @_ },
1668 sort_files
=> undef,
1669 follow_symlinks
=> 1,
1672 %skip_dirs = map {($_,1)} (File
::Spec-
>curdir, File
::Spec-
>updir);
1677 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
1679 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
1680 my $filter = $parms->{file_filter
};
1684 my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 );
1685 if ( -f
$fullpath || -p
$fullpath || $fullpath =~ m{^/dev/fd} ) {
1688 local $File::Next
::dir
= $dirname;
1689 local $File::Next
::name
= $fullpath;
1690 next if not $filter->();
1692 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
1695 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
1709 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
1711 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
1712 my $err = $parms->{error_handler
};
1713 my $warn = $parms->{error_handler
};
1715 my $filename = $queue[1];
1717 if ( !defined($filename) ) {
1718 $err->( 'Must pass a filename to from_file()' );
1723 if ( $filename eq '-' ) {
1727 if ( !open( $fh, '<', $filename ) ) {
1728 $err->( "Unable to open $filename: $!" );
1732 my $filter = $parms->{file_filter
};
1735 local $/ = $parms->{nul_separated
} ? "\x00" : $/;
1736 while ( my $fullpath = <$fh> ) {
1738 next unless $fullpath =~ /./;
1739 if ( not ( -f
$fullpath || -p _
) ) {
1740 $warn->( "$fullpath: No such file" );
1744 my ($volume,$dirname,$file) = File
::Spec-
>splitpath( $fullpath );
1747 local $File::Next
::dir
= $dirname;
1748 local $File::Next
::name
= $fullpath;
1749 next if not $filter->();
1751 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
1759 sub _bad_invocation
{
1760 my $good = (caller(1))[3];
1762 $bad =~ s/(.+)::/$1->/;
1763 return "$good must not be invoked as $bad";
1766 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
1767 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
1772 my @parts = split( /\//, $path );
1774 return $path if @parts < 2;
1776 return File
::Spec-
>catfile( @parts );
1782 my $defaults = shift;
1783 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
1785 my %passed_parms = %{$passed_parms};
1788 for my $key ( keys %{$defaults} ) {
1790 exists $passed_parms{$key}
1791 ? delete $passed_parms{$key}
1792 : $defaults->{$key};
1795 # Any leftover keys are bogus
1796 for my $badkey ( keys %passed_parms ) {
1797 my $sub = (caller(1))[3];
1798 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
1801 # If it's not a code ref, assume standard sort
1802 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
1803 $parms->{sort_files
} = \
&sort_standard
;
1808 my $start = reslash
( $_ );
1810 push @queue, ($start,undef,$start);
1813 push @queue, (undef,$start,$start);
1817 return ($parms,@queue);
1821 sub _candidate_files
{
1823 my $dirname = shift;
1826 if ( !opendir $dh, $dirname ) {
1827 $parms->{error_handler
}->( "$dirname: $!" );
1832 my $descend_filter = $parms->{descend_filter
};
1833 my $follow_symlinks = $parms->{follow_symlinks
};
1834 my $sort_sub = $parms->{sort_files
};
1836 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
1839 # Only do directory checking if we have a descend_filter
1840 my $fullpath = File
::Spec-
>catdir( $dirname, $file );
1841 if ( !$follow_symlinks ) {
1842 next if -l
$fullpath;
1846 if ( $descend_filter ) {
1847 if ( $has_stat ? (-d _
) : (-d
$fullpath) ) {
1848 local $File::Next
::dir
= $fullpath;
1850 next if not $descend_filter->();
1854 push( @newfiles, [ $dirname, $file, $fullpath ] );
1857 push( @newfiles, $dirname, $file, $fullpath );
1863 return map { @{$_} } sort $sort_sub @newfiles;
1870 1; # End of File::Next
1876 use Getopt
::Long
2.36 ();
1884 $COPYRIGHT = 'Copyright 2005-2013 Andy Lester.';
1885 $GIT_REVISION = q{f3c8827};
1900 our $is_filter_mode;
1901 our $output_to_pipe;
1907 use File
::Spec
1.00015 ();
1908 use File
::Glob
1.00015 ':glob';
1911 # These have to be checked before any filehandle diddling.
1912 $output_to_pipe = not -t
*STDOUT
;
1913 $is_filter_mode = -p STDIN
;
1915 $is_cygwin = ($^O eq 'cygwin');
1916 $is_windows = ($^O =~ /MSWin32/);
1917 $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File
::Spec-
>catfile( '', '' ) );
1921 sub retrieve_arg_sources
{
1927 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
1928 Getopt
::Long
::Configure
('pass_through');
1929 Getopt
::Long
::Configure
('no_auto_abbrev');
1931 Getopt
::Long
::GetOptions
(
1933 'ackrc=s' => \
$ackrc,
1936 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
1941 my $finder = App
::Ack
::ConfigFinder-
>new;
1942 @files = $finder->find_config_files;
1945 # we explicitly use open so we get a nice error message
1946 # XXX this is a potential race condition!
1947 if(open my $fh, '<', $ackrc) {
1951 die "Unable to load ackrc '$ackrc': $!"
1953 push( @files, $ackrc );
1956 push @arg_sources, Defaults
=> [ App
::Ack
::ConfigDefault
::options
() ];
1958 foreach my $file ( @files) {
1959 my @lines = read_rcfile
($file);
1960 push ( @arg_sources, $file, \
@lines ) if @lines;
1963 if ( $ENV{ACK_OPTIONS
} && !$noenv ) {
1964 push( @arg_sources, 'ACK_OPTIONS' => $ENV{ACK_OPTIONS
} );
1967 push( @arg_sources, 'ARGV' => [ @ARGV ] );
1969 return @arg_sources;
1975 return unless defined $file && -e
$file;
1979 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
1980 while ( my $line = <$fh> ) {
1985 next if $line eq '';
1986 next if $line =~ /^#/;
1988 push( @lines, $line );
1996 sub create_ignore_rules
{
2001 my @opts = @{$opts};
2005 for my $opt ( @opts ) {
2006 if ( $opt =~ /^(is|ext|regex),(.+)$/ ) {
2009 if ( $method eq 'regex' ) {
2010 push( @{$rules{regex
}}, qr/$arg/ );
2013 ++$rules{$method}{$arg};
2017 App
::Ack
::die( "Invalid argument for --$what: $opt" );
2025 sub remove_dir_sep
{
2027 $path =~ s/[$dir_sep_chars]$//;
2037 defined $str or App
::Ack
::die( 'No regular expression found.' );
2039 $str = quotemeta( $str ) if $opt->{Q
};
2041 $str = "\\b$str" if $str =~ /^\w/;
2042 $str = "$str\\b" if $str =~ /\w$/;
2045 my $regex_is_lc = $str eq lc $str;
2046 if ( $opt->{i
} || ($opt->{smart_case
} && $regex_is_lc) ) {
2057 die "Invalid regex '$str':\n $error";
2067 return unless defined $regex;
2069 eval { qr/$regex/ };
2071 (my $error = $@) =~ s/ at \S+ line \d+.*//;
2073 App
::Ack
::die( "Invalid regex '$regex':\n $error" );
2083 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2088 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2092 require File
::Basename
;
2093 return File
::Basename
::basename
( $0 );
2098 sub filetypes_supported
{
2099 return keys %mappings;
2103 my $y = q{_ /|,\\'!.x',=(www)=, U };
2104 $y =~ tr/,x!w/\nOo_/;
2109 my $y = _get_thpppt
();
2110 App
::Ack
::print( "$y ack $_[0]!\n" );
2118 3~!I#7#I"7#I!?!+!="+"="+!:!
2119 2?#I!7!I!?#I!7!I"+"=%+"=#
2120 1?"+!?*+!=#~"=!+#?"="+!
2121 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2122 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2124 ,,!?%I"?(+$=$~!=#:"~$:!~!
2125 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2126 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2127 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2128 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2129 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2130 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2131 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2132 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2133 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2134 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2135 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2136 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2137 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2138 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2139 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2140 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2141 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2142 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2143 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2144 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2145 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2146 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2147 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2148 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2149 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2150 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2151 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2152 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2153 7+:!,!~#,"=!7'I!?#I"7/+!7+
2154 77I!+!7!?!7!I"71+!7,
2157 $x =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2158 App
::Ack
::print( $x );
2164 my $help_arg = shift || 0;
2166 return show_help_types
() if $help_arg =~ /^types?/;
2168 App
::Ack
::print( <<"END_OF_HELP" );
2169 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2171 Search for PATTERN in each source file in the tree from the current
2172 directory on down. If any files or directories are specified, then
2173 only those files and directories are checked. ack may also search
2174 STDIN, but only if no file or directory arguments are specified,
2175 or if one of them is "-".
2177 Default switches may be specified in ACK_OPTIONS environment variable or
2178 an .ackrc file. If you want no dependency on the environment, turn it
2181 Example: ack -i select
2184 -i, --ignore-case Ignore case distinctions in PATTERN
2185 --[no]smart-case Ignore case distinctions in PATTERN,
2186 only if PATTERN contains no upper case.
2187 Ignored if -i is specified
2188 -v, --invert-match Invert match: select non-matching lines
2189 -w, --word-regexp Force PATTERN to match only whole words
2190 -Q, --literal Quote all metacharacters; PATTERN is literal
2193 --lines=NUM Only print line(s) NUM of each file
2194 -l, --files-with-matches Only print filenames containing matches
2195 -L, --files-without-matches Only print filenames with no matches
2196 --output=expr Output the evaluation of expr for each line
2197 (turns off text highlighting)
2198 -o Show only the part of a line matching PATTERN
2199 Same as --output='\$&'
2200 --passthru Print all lines, whether matching or not
2201 --match PATTERN Specify PATTERN explicitly.
2202 -m, --max-count=NUM Stop searching in each file after NUM matches
2203 -1 Stop searching after one match of any kind
2204 -H, --with-filename Print the filename for each match (default:
2205 on unless explicitly searching a single file)
2206 -h, --no-filename Suppress the prefixing filename on output
2207 -c, --count Show number of lines matching per file
2208 --[no]column Show the column number of the first match
2210 -A NUM, --after-context=NUM Print NUM lines of trailing context after matching
2212 -B NUM, --before-context=NUM Print NUM lines of leading context before matching
2214 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2216 --print0 Print null byte as separator between filenames,
2217 only works with -f, -g, -l, -L or -c.
2219 -s Suppress error messages about nonexistent or
2224 --pager=COMMAND Pipes all ack output through COMMAND. For example,
2225 --pager="less -R". Ignored if output is redirected.
2226 --nopager Do not send output through a pager. Cancels any
2227 setting in ~/.ackrc, ACK_PAGER or ACK_PAGER_COLOR.
2228 --[no]heading Print a filename heading above each file's results.
2229 (default: on when used interactively)
2230 --[no]break Print a break between results from different files.
2231 (default: on when used interactively)
2232 --group Same as --heading --break
2233 --nogroup Same as --noheading --nobreak
2234 --[no]color Highlight the matching text (default: on unless
2235 output is redirected, or on Windows)
2236 --[no]colour Same as --[no]color
2237 --color-filename=COLOR
2239 --color-lineno=COLOR Set the color for filenames, matches, and line numbers.
2240 --flush Flush output immediately, even when ack is used
2241 non-interactively (when output goes to a pipe or
2246 -f Only print the files selected, without searching.
2247 The PATTERN must not be specified.
2248 -g Same as -f, but only select files matching PATTERN.
2249 --sort-files Sort the found files lexically.
2250 --show-types Show which types each file has.
2251 --files-from=FILE Read the list of files to search from FILE.
2252 -x Read the list of files to search from STDIN.
2254 File inclusion/exclusion:
2255 --[no]ignore-dir=name Add/Remove directory from the list of ignored dirs
2256 --[no]ignore-directory=name Synonym for ignore-dir
2257 --ignore-file=filter Add filter for ignoring files
2258 -r, -R, --recurse Recurse into subdirectories (ack's default behavior)
2259 -n, --no-recurse No descending into subdirectories
2260 --[no]follow Follow symlinks. Default is off.
2261 -k, --known-types Include only files with types that ack recognizes.
2263 --type=X Include only X files, where X is a recognized filetype.
2264 --type=noX Exclude X files.
2265 See "ack --help-types" for supported filetypes.
2267 File type specification:
2268 --type-set TYPE:FILTER:FILTERARGS
2269 Files with the given FILTERARGS applied to the given
2270 FILTER are recognized as being of type TYPE. This
2271 replaces an existing definition for type TYPE.
2272 --type-add TYPE:FILTER:FILTERARGS
2273 Files with the given FILTERARGS applied to the given
2274 FILTER are recognized as being of type TYPE.
2275 --type-del TYPE Removes all filters associated with TYPE.
2279 --[no]env Ignore environment variables and global ackrc files. --env is legal but redundant.
2280 --ackrc=filename Specify an ackrc file to use
2281 --ignore-ack-defaults Ignore the default definitions that ack includes.
2282 --create-ackrc Outputs a default ackrc for your customization to standard output.
2283 --help, -? This help
2284 --help-types Display all known types
2285 --dump Dump information on which options are loaded from which RC files
2286 --[no]filter Force ack to treat standard input as a pipe (--filter) or tty (--nofilter)
2288 --version Display version & copyright
2289 --thpppt Bill the Cat
2290 --bar The warning admiral
2292 Exit status is 0 if match, 1 if no match.
2294 This is version $VERSION of ack.
2302 sub show_help_types
{
2303 App
::Ack
::print( <<'END_OF_HELP' );
2304 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2306 The following is the list of filetypes supported by ack. You can
2307 specify a file type with the --type=TYPE format, or the --TYPE
2308 format. For example, both --type=perl and --perl work.
2310 Note that some extensions may appear in multiple types. For example,
2311 .pod files are both Perl and Parrot.
2315 my @types = filetypes_supported
();
2318 $maxlen = length if $maxlen < length;
2320 for my $type ( sort @types ) {
2321 next if $type =~ /^-/; # Stuff to not show
2322 my $ext_list = $mappings{$type};
2324 if ( ref $ext_list ) {
2325 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
2327 App
::Ack
::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2336 Pod
::Usage
::pod2usage
({
2337 -input
=> $App::Ack
::orig_program_name
,
2346 sub get_version_statement
{
2349 my $copyright = get_copyright
();
2350 my $this_perl = $Config::Config
{perlpath
};
2352 my $ext = $Config::Config
{_exe
};
2353 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2355 my $ver = sprintf( '%vd', $^V );
2357 my $git_revision = $GIT_REVISION ? " (git commit $GIT_REVISION)" : '';
2359 return <<"END_OF_VERSION";
2360 ack ${VERSION}${git_revision}
2361 Running under Perl $ver at $this_perl
2365 This program is free software. You may modify or distribute it
2366 under the terms of the Artistic License v2.0.
2371 sub print_version_statement
{
2372 App
::Ack
::print( get_version_statement
() );
2384 eval 'use Term::ANSIColor 1.10 ()';
2386 $ENV{ACK_COLOR_MATCH
} ||= 'black on_yellow';
2387 $ENV{ACK_COLOR_FILENAME
} ||= 'bold green';
2388 $ENV{ACK_COLOR_LINENO
} ||= 'bold yellow';
2394 # print subs added in order to make it easy for a third party
2395 # module (such as App::Wack) to redefine the display methods
2396 # and show the results in a different way.
2397 sub print { print {$fh} @_; return; }
2398 sub print_first_filename
{ App
::Ack
::print( $_[0], "\n" ); return; }
2399 sub print_blank_line
{ App
::Ack
::print( "\n" ); return; }
2400 sub print_separator
{ App
::Ack
::print( "--\n" ); return; }
2401 sub print_filename
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2402 sub print_line_no
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2403 sub print_column_no
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2405 my $filename = shift;
2406 my $nmatches = shift;
2409 my $show_filename = shift;
2411 if ($show_filename) {
2412 App
::Ack
::print( $filename );
2413 App
::Ack
::print( ':', $nmatches ) if $count;
2416 App
::Ack
::print( $nmatches ) if $count;
2418 App
::Ack
::print( $ors );
2424 my $filename = shift;
2426 my $show_filename = shift;
2428 if ($show_filename) {
2429 App
::Ack
::print( $filename, ':0', $ors );
2432 App
::Ack
::print( '0', $ors );
2439 my $command = shift;
2441 return if App
::Ack
::output_to_pipe
();
2444 if ( not open( $pager, '|-', $command ) ) {
2445 App
::Ack
::die( qq{Unable to pipe to pager "$command": $!} );
2453 sub output_to_pipe
{
2454 return $output_to_pipe;
2459 my $nmatches = shift;
2461 my $rc = $nmatches ? 0 : 1;
2467 my @capture_indices;
2468 my $match_column_number;
2471 my ( $opt, $line ) = @_;
2473 my $re = $opt->{regex
};
2474 my $invert = $opt->{v
};
2478 $match_column_number = undef;
2479 @capture_indices = ();
2481 if ( $invert ? $line !~ /$re/ : $line =~ /$re/ ) {
2482 if ( not $invert ) {
2483 # @- = @LAST_MATCH_START
2484 # @+ = @LAST_MATCH_END
2485 $match_column_number = $-[0] + 1;
2488 @capture_indices = map {
2500 sub get_capture_indices
{
2501 return @capture_indices;
2504 sub get_match_column
{
2505 return $match_column_number;
2510 sub print_matches_in_resource
{
2511 my ( $resource, $opt ) = @_;
2513 my $passthru = $opt->{passthru
};
2514 my $max_count = $opt->{m
} || -1;
2516 my $filename = $resource->name;
2517 my $break = $opt->{break};
2518 my $heading = $opt->{heading
};
2519 my $ors = $opt->{print0
} ? "\0" : "\n";
2520 my $color = $opt->{color
};
2521 my $print_filename = $opt->{show_filename
};
2523 my $has_printed_for_this_resource = 0;
2525 App
::Ack
::iterate
($resource, $opt, sub {
2526 if ( App
::Ack
::does_match
($opt, $_) ) {
2527 if( !$has_printed_for_this_resource ) {
2528 if( $break && has_printed_something
() ) {
2529 App
::Ack
::print_blank_line
();
2531 if( $print_filename) {
2533 my $filename = $resource->name;
2535 $filename = Term
::ANSIColor
::colored
($filename,
2536 $ENV{ACK_COLOR_FILENAME
});
2538 App
::Ack
::print_filename
( $filename, $ors );
2542 App
::Ack
::print_line_with_context
($opt, $filename, $_, $.);
2543 $has_printed_for_this_resource = 1;
2547 elsif ( $passthru ) {
2549 if( $break && !$has_printed_for_this_resource && has_printed_something
() ) {
2550 App
::Ack
::print_blank_line
();
2552 App
::Ack
::print_line_with_options
($opt, $filename, $_, $., ':');
2553 $has_printed_for_this_resource = 1;
2555 return $max_count != 0;
2561 sub count_matches_in_resource
{
2562 my ( $resource, $opt ) = @_;
2566 App
::Ack
::iterate
( $resource, $opt, sub {
2567 ++$nmatches if App
::Ack
::does_match
($opt, $_);
2574 sub resource_has_match
{
2575 my ( $resource, $opt ) = @_;
2577 return count_matches_in_resource
($resource, $opt) > 0;
2582 my @before_ctx_lines;
2583 my @after_ctx_lines;
2587 if ( not $is_iterating ) {
2588 Carp
::croak
( 'get_context() called outside of iterate()' );
2592 scalar(@before_ctx_lines) ? \
@before_ctx_lines : undef,
2593 scalar(@after_ctx_lines) ? \
@after_ctx_lines : undef,
2598 my ( $resource, $opt, $cb ) = @_;
2602 local $opt->{before_context
} = $opt->{output
} ? 0 : $opt->{before_context
};
2603 local $opt->{after_context
} = $opt->{output
} ? 0 : $opt->{after_context
};
2605 my $n_before_ctx_lines = $opt->{before_context
} || 0;
2606 my $n_after_ctx_lines = $opt->{after_context
} || 0;
2609 @after_ctx_lines = @before_ctx_lines = ();
2611 if ( $resource->next_text() ) {
2612 $current_line = $_; # prime the first line of input
2615 while ( defined $current_line ) {
2616 while ( (@after_ctx_lines < $n_after_ctx_lines) && $resource->next_text() ) {
2617 push @after_ctx_lines, $_;
2620 local $_ = $current_line;
2621 my $former_dot_period = $.;
2622 $. = $. - @after_ctx_lines;
2624 last unless $cb->();
2626 # I tried doing this with local(), but for some reason,
2627 # $. continued to have its new value after the exit of the
2628 # enclosing block. I'm guessing that $. has some extra
2629 # magic associated with it or something. If someone can
2630 # tell me why this happened, I would love to know!
2631 $. = $former_dot_period; # XXX this won't happen on an exception
2633 push @before_ctx_lines, $current_line;
2634 if($n_after_ctx_lines) {
2635 $current_line = shift @after_ctx_lines;
2637 elsif($resource->next_text()) {
2641 undef $current_line;
2643 shift @before_ctx_lines while @before_ctx_lines > $n_before_ctx_lines;
2646 $is_iterating = 0; # XXX this won't happen on an exception
2647 # then again, do we care? ack doesn't really
2648 # handle exceptions anyway.
2655 my $has_printed_something;
2658 $has_printed_something = 0;
2661 sub has_printed_something
{
2662 return $has_printed_something;
2665 sub print_line_with_options
{
2666 my ( $opt, $filename, $line, $line_no, $separator ) = @_;
2668 $has_printed_something = 1;
2670 my $print_filename = $opt->{show_filename
};
2671 my $print_column = $opt->{column
};
2672 my $ors = $opt->{print0
} ? "\0" : "\n";
2673 my $heading = $opt->{heading
};
2674 my $output_expr = $opt->{output
};
2675 my $re = $opt->{regex
};
2676 my $color = $opt->{color
};
2681 $filename = Term
::ANSIColor
::colored
($filename,
2682 $ENV{ACK_COLOR_FILENAME
});
2683 $line_no = Term
::ANSIColor
::colored
($line_no,
2684 $ENV{ACK_COLOR_LINENO
});
2687 if($print_filename) {
2689 push @line_parts, $line_no;
2692 push @line_parts, $filename, $line_no;
2695 if( $print_column ) {
2696 push @line_parts, get_match_column
();
2699 if( $output_expr ) {
2700 # XXX avoid re-evaluation if we can
2701 while( $line =~ /$re/g ) {
2702 my $output = eval $output_expr;
2703 App
::Ack
::print( join( $separator, @line_parts, $output ), $ors );
2707 my @capture_indices = get_capture_indices
();
2708 if( @capture_indices ) {
2709 my $offset = 0; # additional offset for when we add stuff
2711 foreach my $index_pair ( @capture_indices ) {
2712 my ( $match_start, $match_end ) = @{$index_pair};
2714 my $substring = substr( $line,
2715 $offset + $match_start, $match_end - $match_start );
2716 my $substitution = Term
::ANSIColor
::colored
( $substring,
2717 $ENV{ACK_COLOR_MATCH
} );
2719 substr( $line, $offset + $match_start,
2720 $match_end - $match_start, $substitution );
2722 $offset += length( $substitution ) - length( $substring );
2726 # XXX I know $& is a no-no; fix it later
2727 if($line =~ s/$re/Term::ANSIColor::colored($&, $ENV{ACK_COLOR_MATCH})/ge) {
2728 $line .= "\033[0m\033[K";
2732 push @line_parts, $line;
2733 App
::Ack
::print( join( $separator, @line_parts ), $ors );
2742 my $previous_file_processed;
2743 my $previous_line_printed;
2746 $is_first_match = 1;
2747 $previous_line_printed = -1;
2750 sub print_line_with_context
{
2751 my ( $opt, $filename, $matching_line, $line_no ) = @_;
2753 my $heading = $opt->{heading
};
2755 if( !defined($previous_file_processed) ||
2756 $previous_file_processed ne $filename ) {
2757 $previous_file_processed = $filename;
2758 $previous_line_printed = -1;
2761 $is_first_match = 1;
2765 my $ors = $opt->{print0
} ? "\0" : "\n";
2766 my $match_word = $opt->{w
};
2767 my $re = $opt->{regex
};
2768 my $is_tracking_context = $opt->{after_context
} || $opt->{before_context
};
2769 my $output_expr = $opt->{output
};
2771 chomp $matching_line;
2773 my ( $before_context, $after_context ) = get_context
();
2775 if ( $before_context ) {
2776 my $first_line = $. - @{$before_context};
2778 if ( $first_line <= $previous_line_printed ) {
2779 splice @{$before_context}, 0, $previous_line_printed - $first_line + 1;
2780 $first_line = $. - @{$before_context};
2782 if ( @{$before_context} ) {
2783 my $offset = @{$before_context};
2785 if( !$is_first_match && $previous_line_printed != $first_line - 1 ) {
2786 App
::Ack
::print('--', $ors);
2788 foreach my $line (@{$before_context}) {
2789 my $context_line_no = $. - $offset;
2790 if ( $context_line_no <= $previous_line_printed ) {
2795 App
::Ack
::print_line_with_options
($opt, $filename, $line, $context_line_no, '-');
2796 $previous_line_printed = $context_line_no;
2802 if ( $. > $previous_line_printed ) {
2803 if( $is_tracking_context && !$is_first_match && $previous_line_printed != $. - 1 ) {
2804 App
::Ack
::print('--', $ors);
2807 App
::Ack
::print_line_with_options
($opt, $filename, $matching_line, $line_no, ':');
2808 $previous_line_printed = $.;
2811 if($after_context) {
2813 foreach my $line (@{$after_context}) {
2815 if ( $previous_line_printed >= $. + $offset ) {
2820 my $separator = App
::Ack
::does_match
( $opt, $line ) ? ':' : '-';
2821 App
::Ack
::print_line_with_options
($opt, $filename, $line, $. + $offset, $separator);
2822 $previous_line_printed = $. + $offset;
2827 $is_first_match = 0;
2834 # inefficient, but functional
2836 my ( $resource ) = @_;
2840 foreach my $k (keys %mappings) {
2841 my $filters = $mappings{$k};
2843 foreach my $filter (@{$filters}) {
2844 # clone the resource
2845 my $clone = $resource->clone;
2846 if ( $filter->filter($clone) ) {
2853 return sort @matches;
2856 # returns a (fairly) unique identifier for a file
2857 # use this function to compare two files to see if they're
2858 # equal (ie. the same file, but with a different path/links/etc)
2860 my ( $filename ) = @_;
2862 if ( $is_windows ) {
2863 return File
::Next
::reslash
( $filename );
2866 # XXX is this the best method? it always hits the FS
2867 if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
2868 return join(':', $dev, $inode);
2871 # XXX this could be better
2878 print "$_\n" for ( '--ignore-ack-defaults', App
::Ack
::ConfigDefault
::options
() );
2883 1; # End of App::Ack
2884 package App
::Ack
::Resource
;
2894 Carp
::confess
( 'Must be overloaded' );
2914 sub needs_line_scan
{
2939 package App
::Ack
::Resources
;
2952 my $self = bless {}, $class;
2954 my $file_filter = undef;
2955 my $descend_filter = $opt->{descend_filter
};
2958 $descend_filter = sub {
2964 File
::Next
::files
( {
2965 file_filter
=> $opt->{file_filter
},
2966 descend_filter
=> $descend_filter,
2967 error_handler
=> sub { my $msg = shift; App
::Ack
::warn( $msg ) },
2968 sort_files
=> $opt->{sort_files
},
2969 follow_symlinks
=> $opt->{follow
},
2982 File
::Next
::from_file
( {
2983 error_handler
=> sub { my $msg = shift; App
::Ack
::warn( $msg ) },
2984 warning_handler
=> sub { my $msg = shift; App
::Ack
::warn( $msg ) },
2985 sort_files
=> $opt->{sort_files
},
2986 }, $file ) or return undef;
2993 # This is for reading input lines from STDIN, not the list of files from STDIN
2998 my $self = bless {}, $class;
3000 my $has_been_called = 0;
3002 $self->{iter
} = sub {
3003 if ( !$has_been_called ) {
3004 $has_been_called = 1;
3016 my $file = $self->{iter
}->() or return;
3018 return App
::Ack
::Resource
::Basic-
>new( $file );
3022 package App
::Ack
::Resource
::Basic
;
3029 our @ISA = 'App::Ack::Resource';
3035 my $filename = shift;
3038 filename
=> $filename,
3043 if ( $self->{filename
} eq '-' ) {
3044 $self->{fh
} = *STDIN
;
3047 if ( !open( $self->{fh
}, '<', $self->{filename
} ) && $App::Ack
::report_bad_filenames
) {
3048 App
::Ack
::warn( "$self->{filename}: $!" );
3060 return $self->{filename
};
3065 sub needs_line_scan
{
3069 return 1 if $opt->{v
};
3071 my $size = -s
$self->{fh
};
3075 elsif ( $size > 100_000 ) {
3080 my $rc = sysread( $self->{fh
}, $buffer, $size );
3081 if ( !defined($rc) && $App::Ack
::report_bad_filenames
) {
3082 App
::Ack
::warn( "$self->{filename}: $!" );
3085 return 0 unless $rc && ( $rc == $size );
3087 my $regex = $opt->{regex
};
3088 return $buffer =~ /$regex/m;
3095 if( !seek( $self->{fh
}, 0, 0 ) && $App::Ack
::report_bad_filenames
) {
3096 App
::Ack
::warn( "$self->{filename}: $!" );
3104 if ( defined ($_ = readline $_[0]->{fh
}) ) {
3105 $. = ++$_[0]->{line
};
3106 s/[\r\n]+$//; # chomp may not handle this
3107 $_ .= "\n"; # add back newline (XXX make it native)
3118 if ( !close($self->{fh
}) && $App::Ack
::report_bad_filenames
) {
3119 App
::Ack
::warn( $self->name() . ": $!" );
3129 return __PACKAGE__-
>new($self->name);
3134 package App
::Ack
::Filter
;
3139 '""' => 'to_string';
3147 my ( undef, $type, @args ) = @_;
3149 if ( my $package = $filter_types{$type} ) {
3150 return $package->new(@args);
3152 Carp
::croak
"Unknown filter type '$type'";
3156 sub register_filter
{
3157 my ( undef, $type, $package ) = @_;
3159 $filter_types{$type} = $package;
3168 return App
::Ack
::Filter
::Inverse-
>new( $self );
3180 return '(unimplemented to_string)';
3191 package App
::Ack
::Filter
::Extension
;
3196 our @ISA = 'App::Ack::Filter';
3200 my ( $class, @extensions ) = @_;
3202 my $exts = join('|', map { "\Q$_\E"} @extensions);
3203 my $re = qr/[.](?:$exts)$/i;
3206 extensions
=> \
@extensions,
3212 my ( $self, $resource ) = @_;
3214 my $re = $self->{'regex'};
3216 return $resource->name =~ /$re/;
3222 my $re = $self->{'regex'};
3224 return ref($self) . " - $re";
3230 my $exts = $self->{'extensions'};
3232 return join(' ', map { ".$_" } @{$exts});
3236 App
::Ack
::Filter-
>register_filter(ext
=> __PACKAGE__
);
3240 package App
::Ack
::Filter
::FirstLineMatch
;
3245 our @ISA = 'App::Ack::Filter';
3249 my ( $class, $re ) = @_;
3251 $re =~ s{^/|/$}{}g; # XXX validate?
3259 # This test reads the first 250 characters of a file, then just uses the
3260 # first line found in that. This prevents reading something like an entire
3261 # .min.js file (which might be only one "line" long) into memory.
3264 my ( $self, $resource ) = @_;
3266 my $re = $self->{'regex'};
3269 my $rc = sysread( $resource->{fh
}, $buffer, 250 );
3271 $buffer =~ s/[\r\n].*//s;
3273 return $buffer =~ /$re/;
3279 my $re = $self->{'regex'};
3281 return ref($self) . " - $re";
3287 (my $re = $self->{regex
}) =~ s{\([^:]*:(.*)\)$}{$1};
3289 return "first line matches /$re/";
3293 App
::Ack
::Filter-
>register_filter(firstlinematch
=> __PACKAGE__
);
3297 package App
::Ack
::Filter
::Is
;
3302 our @ISA = 'App::Ack::Filter';
3305 use File
::Spec
3.00 ();
3308 my ( $class, $filename ) = @_;
3311 filename
=> $filename,
3316 my ( $self, $resource ) = @_;
3318 my $filename = $self->{'filename'};
3319 my $base = (File
::Spec-
>splitpath($resource->name))[2];
3321 return $base eq $filename;
3327 my $filename = $self->{'filename'};
3329 return ref($self) . " - $filename";
3335 my $filename = $self->{'filename'};
3339 App
::Ack
::Filter-
>register_filter(is => __PACKAGE__
);
3343 package App
::Ack
::Filter
::Match
;
3348 our @ISA = 'App::Ack::Filter';
3351 use File
::Spec
3.00;
3354 my ( $class, $re ) = @_;
3356 $re =~ s{^/|/$}{}g; # XXX validate?
3365 my ( $self, $resource ) = @_;
3367 my $re = $self->{'regex'};
3368 my $base = (File
::Spec-
>splitpath($resource->name))[2];
3370 return $base =~ /$re/;
3376 my $re = $self->{'regex'};
3378 print ref($self) . " - $re";
3384 my $re = $self->{'regex'};
3386 return "filename matches $re";
3390 App
::Ack
::Filter-
>register_filter(match
=> __PACKAGE__
);
3394 package App
::Ack
::Filter
::Default
;
3399 our @ISA = 'App::Ack::Filter';
3405 return bless {}, $class;
3409 my ( $self, $resource ) = @_;
3411 return -T
$resource->name;
3415 package App
::Ack
::Filter
::Inverse
;
3420 our @ISA = 'App::Ack::Filter';
3424 my ( $class, $filter ) = @_;
3432 my ( $self, $resource ) = @_;
3434 my $filter = $self->{'filter'};
3435 return !$filter->filter( $resource );
3441 return $self->{'filter'};
3451 my $filter = $self->{'filter'};
3457 package App
::Ack
::ConfigFinder
;
3464 use File
::Spec
3.00;
3467 if ($App::Ack
::is_windows
) {
3476 return bless {}, $class;
3479 sub _remove_redundancies
{
3480 my ( @configs ) = @_;
3482 my %dev_and_inode_seen;
3484 foreach my $path ( @configs ) {
3485 my ( $dev, $inode ) = (stat $path)[0, 1];
3487 if( defined($dev) ) {
3488 if( $dev_and_inode_seen{"$dev:$inode"} ) {
3492 $dev_and_inode_seen{"$dev:$inode"} = 1;
3496 return grep { defined() } @configs;
3499 sub _check_for_ackrc
{
3500 return unless defined $_[0];
3502 my @files = grep { -f
}
3503 map { File
::Spec-
>catfile(@_, $_) }
3506 die File
::Spec-
>catdir(@_) . " contains both .ackrc and _ackrc.\n" .
3507 "Please remove one of those files.\n"
3510 return wantarray ? @files : $files[0];
3511 } # end _check_for_ackrc
3514 sub find_config_files
{
3517 if($App::Ack
::is_windows
) {
3518 push @config_files, map { File
::Spec-
>catfile($_, 'ackrc') } (
3519 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3520 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3524 push @config_files, '/etc/ackrc';
3527 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3528 push @config_files, $ENV{'ACKRC'};
3531 push @config_files, _check_for_ackrc
($ENV{'HOME'});
3534 my @dirs = File
::Spec-
>splitdir(Cwd
::getcwd
());
3536 my $ackrc = _check_for_ackrc
(@dirs);
3537 if(defined $ackrc) {
3538 push @config_files, $ackrc;
3544 # XXX we only test for existence here, so if the file is
3545 # deleted out from under us, this will fail later. =(
3546 return _remove_redundancies
( @config_files );
3550 package App
::Ack
::ConfigLoader
;
3556 use Getopt
::Long
2.36 ();
3557 use Text
::ParseWords
3.1 ();
3560 my @INVALID_COMBINATIONS;
3563 my @context = qw( -A -B -C --after-context --before-context --context );
3564 my @pretty = qw( --heading --group --break );
3565 my @filename = qw( -h -H --with-filename --no-filename );
3567 @INVALID_COMBINATIONS = (
3569 [qw(-l)] => [@context, @pretty, @filename, qw(-L -o --passthru --output --max-count --column -f -g --show-types)],
3570 [qw(-L)] => [@context, @pretty, @filename, qw(-l -o --passthru --output --max-count --column -f -g --show-types -c --count)],
3571 [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)],
3572 [qw(-o)] => [@context, qw(--output -c --count --column --column -f --show-types)],
3573 [qw(--passthru)] => [@context, qw(--output --column -m --max-count -1 -c --count -f -g)],
3574 [qw(--output)] => [@context, qw(-c --count -f -g)],
3575 [qw(--match)] => [qw(-f -g)],
3576 [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
3577 [qw(-h --no-filename)] => [qw(-H --with-filename -f -g --group --heading)],
3578 [qw(-H --with-filename)] => [qw(-h --no-filename -f -g)],
3579 [qw(-c --count)] => [@context, @pretty, qw(--column -f -g)],
3580 [qw(--column)] => [qw(-f -g)],
3581 [@context] => [qw(-f -g)],
3582 [qw(-f)] => [qw(-g), @pretty],
3583 [qw(-g)] => [qw(-f), @pretty],
3587 sub process_filter_spec
{
3590 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3591 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3593 return ( $type_name,
3594 App
::Ack
::Filter-
>create_filter($ext_type, split(/,/, $arguments)) );
3596 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3597 my ( $type_name, $extensions ) = ( $1, $2 );
3599 my @extensions = split(/,/, $extensions);
3600 foreach my $extension ( @extensions ) {
3601 $extension =~ s/^[.]//;
3604 return ( $type_name, App
::Ack
::Filter-
>create_filter('ext', @extensions) );
3607 Carp
::croak
"invalid filter specification '$spec'";
3611 sub process_filetypes
{
3612 my ( $opt, $arg_sources ) = @_;
3614 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3615 Getopt
::Long
::Configure
(
3620 my %additional_specs;
3622 my $add_spec = sub {
3623 my ( undef, $spec ) = @_;
3625 my ( $name, $filter ) = process_filter_spec
($spec);
3627 push @{ $App::Ack
::mappings
{$name} }, $filter;
3629 $additional_specs{$name . '!'} = sub {
3630 my ( undef, $value ) = @_;
3632 my @filters = @{ $App::Ack
::mappings
{$name} };
3634 @filters = map { $_->invert() } @filters;
3637 push @{ $opt->{'filters'} }, @filters;
3641 my $set_spec = sub {
3642 my ( undef, $spec ) = @_;
3644 my ( $name, $filter ) = process_filter_spec
($spec);
3646 $App::Ack
::mappings
{$name} = [ $filter ];
3648 $additional_specs{$name . '!'} = sub {
3649 my ( undef, $value ) = @_;
3651 my @filters = @{ $App::Ack
::mappings
{$name} };
3653 @filters = map { $_->invert() } @filters;
3656 push @{ $opt->{'filters'} }, @filters;
3660 my $delete_spec = sub {
3661 my ( undef, $name ) = @_;
3663 delete $App::Ack
::mappings
{$name};
3664 delete $additional_specs{$name . '!'};
3667 my %type_arg_specs = (
3668 'type-add=s' => $add_spec,
3669 'type-set=s' => $set_spec,
3670 'type-del=s' => $delete_spec,
3673 for ( my $i = 0; $i < @{$arg_sources}; $i += 2) {
3674 my ( $source_name, $args ) = @{$arg_sources}[ $i, $i + 1];
3677 # $args are modified in place, so no need to munge $arg_sources
3678 Getopt
::Long
::GetOptionsFromArray
($args, %type_arg_specs);
3681 ( undef, $arg_sources->[$i + 1] ) =
3682 Getopt
::Long
::GetOptionsFromString
($args, %type_arg_specs);
3686 $additional_specs{'k|known-types'} = sub {
3687 my ( undef, $value ) = @_;
3689 my @filters = map { @{$_} } values(%App::Ack
::mappings
);
3691 push @{ $opt->{'filters'} }, @filters;
3694 return \
%additional_specs;
3697 sub removed_option
{
3698 my ( $option, $explanation ) = @_;
3700 $explanation ||= '';
3702 warn "Option '$option' is not valid in ack 2\n$explanation";
3708 my ( $opt, $extra_specs ) = @_;
3710 my $dash_a_explanation = <<EOT;
3711 This is because we now have -k/--known-types which makes it only select files
3712 of known types, rather than any text file (which is the behavior of ack 1.x).
3716 1 => sub { $opt->{1} = $opt->{m
} = 1 },
3717 'A|after-context=i' => \
$opt->{after_context
},
3718 'B|before-context=i'
3719 => \
$opt->{before_context
},
3720 'C|context:i' => sub { shift; my $val = shift; $opt->{before_context
} = $opt->{after_context
} = ($val || 2) },
3721 'a' => removed_option
('-a', $dash_a_explanation),
3722 'all' => removed_option
('--all', $dash_a_explanation),
3723 'break!' => \
$opt->{break},
3724 c
=> \
$opt->{count
},
3725 'color|colour!' => \
$opt->{color
},
3726 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
3727 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
3728 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
3729 'column!' => \
$opt->{column
},
3730 count
=> \
$opt->{count
},
3731 'create-ackrc' => sub { App
::Ack
::create_ackrc
(); exit; },
3733 my ( undef, $value ) = @_;
3736 $opt->{noenv_seen
} = 1;
3740 'files-from=s' => \
$opt->{files_from
},
3741 'filter!' => \
$App::Ack
::is_filter_mode
,
3742 flush
=> \
$opt->{flush
},
3743 'follow!' => \
$opt->{follow
},
3745 G
=> removed_option
('-G'),
3746 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
3747 'heading!' => \
$opt->{heading
},
3748 'h|no-filename' => \
$opt->{h
},
3749 'H|with-filename' => \
$opt->{H
},
3750 'i|ignore-case' => \
$opt->{i
},
3751 'ignore-directory|ignore-dir=s' # XXX Combine this version with the negated version below
3753 my ( undef, $dir ) = @_;
3755 $dir = App
::Ack
::remove_dir_sep
( $dir );
3756 if ( $dir !~ /^(?:is|match):/ ) {
3757 $dir = 'is:' . $dir;
3759 push @{ $opt->{idirs
} }, $dir;
3761 'ignore-file=s' => sub {
3762 my ( undef, $file ) = @_;
3763 push @{ $opt->{ifiles
} }, $file;
3765 'lines=s' => sub { shift; my $val = shift; push @{$opt->{lines
}}, $val },
3766 'l|files-with-matches'
3768 'L|files-without-matches'
3770 'm|max-count=i' => \
$opt->{m
},
3771 'match=s' => \
$opt->{regex
},
3772 'n|no-recurse' => \
$opt->{n
},
3773 o
=> sub { $opt->{output
} = '$&' },
3774 'output=s' => \
$opt->{output
},
3775 'pager=s' => \
$opt->{pager
},
3776 'noignore-directory|noignore-dir=s'
3778 my ( undef, $dir ) = @_;
3780 # XXX can you do --noignore-dir=match,...?
3781 $dir = App
::Ack
::remove_dir_sep
( $dir );
3782 if ( $dir !~ /^(?:is|match):/ ) {
3783 $dir = 'is:' . $dir;
3785 if ( $dir !~ /^(?:is|match):/ ) {
3786 Carp
::croak
("invalid noignore-directory argument: '$dir'");
3789 @{ $opt->{idirs
} } = grep {
3791 } @{ $opt->{idirs
} };
3793 push @{ $opt->{no_ignore_dirs
} }, $dir;
3795 'nopager' => sub { $opt->{pager
} = undef },
3796 'passthru' => \
$opt->{passthru
},
3797 'print0' => \
$opt->{print0
},
3798 'Q|literal' => \
$opt->{Q
},
3799 'r|R|recurse' => sub { $opt->{n
} = 0 },
3800 's' => \
$opt->{dont_report_bad_filenames
},
3801 'show-types' => \
$opt->{show_types
},
3802 'smart-case!' => \
$opt->{smart_case
},
3803 'sort-files' => \
$opt->{sort_files
},
3805 my ( $getopt, $value ) = @_;
3808 if ( $value =~ s/^no// ) {
3812 my $callback = $extra_specs->{ $value . '!' };
3815 $callback->( $getopt, $cb_value );
3818 Carp
::croak
( "Unknown type '$value'" );
3821 'u' => removed_option
('-u'),
3822 'unrestricted' => removed_option
('--unrestricted'),
3823 'v|invert-match' => \
$opt->{v
},
3824 'w|word-regexp' => \
$opt->{w
},
3825 'x' => sub { $opt->{files_from
} = '-' },
3827 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
3828 'help|?:s' => sub { shift; App
::Ack
::show_help
(@_); exit; },
3829 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
3830 'man' => sub { App
::Ack
::show_man
(); exit; },
3831 $extra_specs ? %{$extra_specs} : (),
3836 my ( $opt, $extra_specs, $arg_sources ) = @_;
3838 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3839 Getopt
::Long
::Configure
(
3845 my $is_help_types_active;
3847 for ( my $i = 0; $i < @{$arg_sources}; $i += 2 ) {
3848 my ( $source_name, $args ) = @{$arg_sources}[ $i, $i + 1 ];
3850 if ( $source_name eq 'ARGV' ) {
3851 $argv_source = $args;
3856 if ( $argv_source ) { # this *should* always be true, but you never know...
3857 my @copy = @{$argv_source};
3859 Getopt
::Long
::Configure
('pass_through');
3861 Getopt
::Long
::GetOptionsFromArray
( \
@copy,
3862 'help-types' => \
$is_help_types_active,
3865 Getopt
::Long
::Configure
('no_pass_through');
3868 my $arg_specs = get_arg_spec
($opt, $extra_specs);
3870 for ( my $i = 0; $i < @{$arg_sources}; $i += 2) {
3871 my ($source_name, $args) = @{$arg_sources}[$i, $i + 1];
3875 $ret = Getopt
::Long
::GetOptionsFromArray
( $args, %{$arg_specs} );
3878 ( $ret, $arg_sources->[$i + 1] ) =
3879 Getopt
::Long
::GetOptionsFromString
( $args, %{$arg_specs} );
3882 if ( !$is_help_types_active ) {
3883 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
3884 App
::Ack
::die( "Invalid option $where" );
3887 if ( $opt->{noenv_seen
} ) {
3888 App
::Ack
::die( "--noenv found in $source_name" );
3892 # XXX We need to check on a -- in the middle of a non-ARGV source
3897 sub should_dump_options
{
3898 my ( $sources ) = @_;
3900 for(my $i = 0; $i < @{$sources}; $i += 2) {
3901 my ( $name, $options ) = @{$sources}[$i, $i + 1];
3902 if($name eq 'ARGV') {
3904 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
3905 Getopt
::Long
::GetOptionsFromArray
($options,
3914 sub explode_sources
{
3915 my ( $sources ) = @_;
3919 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
3922 my $arg_spec = get_arg_spec
(\
%opt);
3924 my $add_type = sub {
3925 my ( undef, $arg ) = @_;
3928 if ( $arg =~ /(\w+)=/) {
3929 $arg_spec->{$1} = sub {};
3932 ( $arg ) = split /:/, $arg;
3933 $arg_spec->{$arg} = sub {};
3937 my $del_type = sub {
3938 my ( undef, $arg ) = @_;
3940 delete $arg_spec->{$arg};
3943 for(my $i = 0; $i < @{$sources}; $i += 2) {
3944 my ( $name, $options ) = @{$sources}[$i, $i + 1];
3945 if ( ref($options) ne 'ARRAY' ) {
3946 $sources->[$i + 1] = $options =
3947 [ Text
::ParseWords
::shellwords
($options) ];
3949 for ( my $j = 0; $j < @{$options}; $j++ ) {
3950 next unless $options->[$j] =~ /^-/;
3951 my @chunk = ( $options->[$j] );
3952 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
3956 Getopt
::Long
::GetOptionsFromArray
(\
@chunk,
3957 'type-add=s' => $add_type,
3958 'type-set=s' => $add_type,
3959 'type-del=s' => $del_type,
3961 Getopt
::Long
::GetOptionsFromArray
(\
@chunk, %{$arg_spec});
3963 splice @copy, -1 * @chunk if @chunk; # XXX explain this
3964 push @new_sources, $name, \
@copy;
3968 return \
@new_sources;
3974 my $first_a = $a->[0];
3975 my $first_b = $b->[0];
3977 $first_a =~ s/^--?//;
3978 $first_b =~ s/^--?//;
3980 return $first_a cmp $first_b;
3984 my ( $sources ) = @_;
3986 $sources = explode_sources
($sources);
3991 for(my $i = 0; $i < @{$sources}; $i += 2) {
3992 my ( $name, $contents ) = @{$sources}[$i, $i + 1];
3993 if ( not $opts_by_source{$name} ) {
3994 $opts_by_source{$name} = [];
3995 push @source_names, $name;
3997 push @{$opts_by_source{$name}}, $contents;
4000 foreach my $name (@source_names) {
4001 my $contents = $opts_by_source{$name};
4004 print '=' x
length($name), "\n";
4005 print ' ', join(' ', @{$_}), "\n" foreach sort { compare_opts
($a, $b) } @{$contents};
4011 sub remove_default_options_if_needed
{
4012 my ( $sources ) = @_;
4016 foreach my $index ( 0 .. $#$sources ) {
4017 if ( $sources->[$index] eq 'Defaults' ) {
4018 $default_index = $index;
4023 return $sources unless defined $default_index;
4025 my $should_remove = 0;
4027 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
4028 Getopt
::Long
::Configure
(
4034 foreach my $index ( $default_index + 2 .. $#$sources ) {
4035 next if $index % 2 != 0;
4037 my ( $name, $args ) = @{$sources}[ $index, $index + 1 ];
4040 Getopt
::Long
::GetOptionsFromArray
($args,
4041 'ignore-ack-defaults' => \
$should_remove,
4045 ( undef, $sources->[$index + 1] ) = Getopt
::Long
::GetOptionsFromString
($args,
4046 'ignore-ack-defaults' => \
$should_remove,
4051 Getopt
::Long
::Configure
('default');
4052 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4054 return $sources unless $should_remove;
4056 my @copy = @{$sources};
4057 splice @copy, $default_index, 2;
4061 sub check_for_mutually_exclusive_options
{
4062 my ( $arg_sources ) = @_;
4064 my %mutually_exclusive_with;
4065 my @copy = @{$arg_sources};
4067 for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
4068 my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
4070 foreach my $l_opt ( @{$lhs} ) {
4071 foreach my $r_opt ( @{$rhs} ) {
4072 push @{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
4073 push @{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
4081 my ( $source_name, $args ) = splice @copy, 0, 2;
4082 $args = ref($args) ? [ @{$args} ] : [ Text
::ParseWords
::shellwords
($args) ];
4084 foreach my $opt ( @{$args} ) {
4085 next unless $opt =~ /^[-+]/;
4086 last if $opt eq '--';
4088 if( $opt =~ /^(.*)=/ ) {
4091 elsif ( $opt =~ /^(-[^-]).+/ ) {
4095 $set_opts{ $opt } = 1;
4097 my $mutex_opts = $mutually_exclusive_with{ $opt };
4099 next unless $mutex_opts;
4101 foreach my $mutex_opt ( @{$mutex_opts} ) {
4102 if($set_opts{ $mutex_opt }) {
4103 die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
4111 my $arg_sources = \
@_;
4115 check_for_mutually_exclusive_options
($arg_sources);
4117 $arg_sources = remove_default_options_if_needed
($arg_sources);
4119 if ( should_dump_options
($arg_sources) ) {
4120 dump_options
($arg_sources);
4124 my $type_specs = process_filetypes
(\
%opt, $arg_sources);
4125 process_other
(\
%opt, $type_specs, $arg_sources);
4126 while ( @{$arg_sources} ) {
4127 my ( $source_name, $args ) = splice( @{$arg_sources}, 0, 2 );
4129 # All of our sources should be transformed into an array ref
4131 if ( $source_name eq 'ARGV' ) {
4135 Carp
::croak
"source '$source_name' has extra arguments!";
4139 Carp
::croak
'The impossible has occurred!';
4142 my $filters = ($opt{filters
} ||= []);
4144 # throw the default filter in if no others are selected
4145 if ( not grep { !$_->is_inverted() } @{$filters} ) {
4146 push @{$filters}, App
::Ack
::Filter
::Default-
>new();
4151 1; # End of App::Ack::ConfigLoader
4152 package App
::Ack
::ConfigDefault
;
4158 my @options = split( /\n/, _options_block
() );
4159 @options = grep { /./ && !/^#/ } @options;
4164 sub _options_block
{
4166 # This is the default ackrc for ack 2.0
4168 # There are four different ways to match
4170 # is: Match the filename exactly
4172 # ext: Match the extension of the filename exactly
4174 # match: Match the filename against a Perl regular expression
4176 # firstlinematch: Match the first 250 characters of the first line
4177 # of text against a Perl regular expression. This is only for
4178 # the --type-add option.
4181 # Directories to ignore
4183 --ignore-directory=is:.bzr
4186 --ignore-directory=is:.cdv
4189 --ignore-directory=is:~.dep
4190 --ignore-directory=is:~.dot
4191 --ignore-directory=is:~.nib
4192 --ignore-directory=is:~.plst
4195 --ignore-directory=is:.git
4198 --ignore-directory=is:.hg
4201 --ignore-directory=is:.pc
4204 --ignore-directory=is:.svn
4207 --ignore-directory=is:_MTN
4210 --ignore-directory=is:CVS
4213 --ignore-directory=is:RCS
4216 --ignore-directory=is:SCCS
4219 --ignore-directory=is:_darcs
4222 --ignore-directory=is:_sgbak
4225 --ignore-directory=is:autom4te.cache
4227 # Perl module building
4228 --ignore-directory=is:blib
4229 --ignore-directory=is:_build
4231 # Perl Devel::Cover module's output directory
4232 --ignore-directory=is:cover_db
4238 --ignore-file=ext:bak
4239 --ignore-file=match:/~$/
4242 --ignore-file=match:/^#.+#$/
4245 --ignore-file=match:/[._].*\.swp$/
4248 --ignore-file=match:/core\.\d+$/
4250 # minified Javascript
4251 --ignore-file=match:/[.]min[.]js$/
4256 # Perl http://perl.org/
4257 --type-add=perl:ext:pl,pm,pod,t
4258 --type-add=perl:firstlinematch:/^#!.*\bperl/
4260 # Makefiles http://www.gnu.org/s/make/
4261 --type-add=make:ext:mk
4262 --type-add=make:ext:mak
4263 --type-add=make:is:makefile
4264 --type-add=make:is:Makefile
4265 --type-add=make:is:GNUmakefile
4267 # Rakefiles http://rake.rubyforge.org/
4268 --type-add=rake:is:Rakefile
4270 # CMake http://www.cmake.org/
4271 --type-add=cmake:is:CMakeLists.txt
4272 --type-add=cmake:ext:cmake
4275 --type-add=actionscript:ext:as,mxml
4277 # Ada http://www.adaic.org/
4278 --type-add=ada:ext:ada,adb,ads
4280 # ASP http://msdn.microsoft.com/en-us/library/aa286483.aspx
4281 --type-add=asp:ext:asp
4283 # ASP.Net http://www.asp.net/
4284 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
4287 --type-add=asm:ext:asm,s
4290 --type-add=batch:ext:bat,cmd
4292 # ColdFusion http://en.wikipedia.org/wiki/ColdFusion
4293 --type-add=cfmx:ext:cfc,cfm,cfml
4295 # Clojure http://clojure.org/
4296 --type-add=clojure:ext:clj
4299 # .xs are Perl C files
4300 --type-add=cc:ext:c,h,xs
4306 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
4309 --type-add=csharp:ext:cs
4311 # CSS http://www.w3.org/Style/CSS/
4312 --type-add=css:ext:css
4314 # Delphi http://en.wikipedia.org/wiki/Embarcadero_Delphi
4315 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
4317 # Emacs Lisp http://www.gnu.org/software/emacs
4318 --type-add=elisp:ext:el
4320 # Erlang http://www.erlang.org/
4321 --type-add=erlang:ext:erl,hrl
4323 # Fortran http://en.wikipedia.org/wiki/Fortran
4324 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
4326 # Google Go http://golang.org/
4327 --type-add=go:ext:go
4329 # Groovy http://groovy.codehaus.org/
4330 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
4332 # Haskell http://www.haskell.org/
4333 --type-add=haskell:ext:hs,lhs
4336 --type-add=html:ext:htm,html
4338 # Java http://www.oracle.com/technetwork/java/index.html
4339 --type-add=java:ext:java,properties
4342 --type-add=js:ext:js
4344 # JSP http://www.oracle.com/technetwork/java/javaee/jsp/index.html
4345 --type-add=jsp:ext:jsp,jspx,jhtm,jhtml
4347 # Common Lisp http://common-lisp.net/
4348 --type-add=lisp:ext:lisp,lsp
4350 # Lua http://www.lua.org/
4351 --type-add=lua:ext:lua
4354 --type-add=objc:ext:m,h
4357 --type-add=objcpp:ext:mm,h
4359 # OCaml http://caml.inria.fr/
4360 --type-add=ocaml:ext:ml,mli
4362 # Parrot http://www.parrot.org/
4363 --type-add=parrot:ext:pir,pasm,pmc,ops,pod,pg,tg
4365 # PHP http://www.php.net/
4366 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
4367 --type-add=php:firstlinematch:/^#!.*\bphp/
4369 # Plone http://plone.org/
4370 --type-add=plone:ext:pt,cpt,metadata,cpy,py
4372 # Python http://www.python.org/
4373 --type-add=python:ext:py
4374 --type-add=python:firstlinematch:/^#!.*\bpython/
4376 # R http://www.r-project.org/
4379 # Ruby http://www.ruby-lang.org/
4380 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
4381 --type-add=ruby:is:Rakefile
4382 --type-add=ruby:firstlinematch:/^#!.*\bruby/
4384 # Rust http://www.rust-lang.org/
4385 --type-add=rust:ext:rs
4387 # Scala http://www.scala-lang.org/
4388 --type-add=scala:ext:scala
4390 # Scheme http://groups.csail.mit.edu/mac/projects/scheme/
4391 --type-add=scheme:ext:scm,ss
4394 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh
4395 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z)?sh\b/
4397 # Smalltalk http://www.smalltalk.org/
4398 --type-add=smalltalk:ext:st
4400 # SQL http://www.iso.org/iso/catalogue_detail.htm?csnumber=45498
4401 --type-add=sql:ext:sql,ctl
4403 # Tcl http://www.tcl.tk/
4404 --type-add=tcl:ext:tcl,itcl,itk
4406 # LaTeX http://www.latex-project.org/
4407 --type-add=tex:ext:tex,cls,sty
4409 # Template Toolkit http://template-toolkit.org/
4410 --type-add=tt:ext:tt,tt2,ttml
4413 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
4416 --type-add=verilog:ext:v,vh,sv
4418 # VHDL http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
4419 --type-add=vhdl:ext:vhd,vhdl
4421 # Vim http://www.vim.org/
4422 --type-add=vim:ext:vim
4424 # XML http://www.w3.org/TR/REC-xml/
4425 --type-add=xml:ext:xml,dtd,xsl,xslt,ent
4426 --type-add=xml:firstlinematch:/<[?]xml/
4428 # YAML http://yaml.org/
4429 --type-add=yaml:ext:yaml,yml