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.00b06';
26 # Check http://betterthangrep.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 return unless $idirs && @{$idirs};
82 foreach my $idir (@{$idirs}) {
83 if ( $idir =~ /^(\w+):(.*)/ ) {
88 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
92 Carp
::croak
( qq{Invalid filter specification "$_"} );
97 return !exists $ignore_dirs{$_} && !exists $ignore_dirs{$File::Next
::dir
};
101 sub _compile_file_filter
{
102 my ( $opt, $start ) = @_;
104 my $ifiles = $opt->{ifiles
};
107 my @ifiles_filters = map {
110 if ( /^(\w+):(.+)/ ) {
111 my ($how,$what) = ($1,$2);
112 $filter = App
::Ack
::Filter-
>create_filter($how, split(/,/, $what));
115 Carp
::croak
( qq{Invalid filter specification "$_"} );
120 my $filters = $opt->{'filters'} || [];
121 my $inverse_filters = [ grep { $_->is_inverted() } @{$filters} ];
122 @{$filters} = grep { !$_->is_inverted() } @{$filters};
124 my %is_member_of_starting_set = map { (App
::Ack
::get_file_id
($_) => 1) } @{$start};
127 # ack always selects files that are specified on the command
128 # line, regardless of filetype. If you want to ack a JPEG,
129 # and say "ack foo whatever.jpg" it will do it for you.
130 return 1 if $is_member_of_starting_set{ App
::Ack
::get_file_id
($File::Next
::name
) };
132 # Ignore named pipes found in directory searching. Named
133 # pipes created by subprocesses get specified on the command
134 # line, so the rule of "always select whatever is on the
135 # command line" wins.
136 return 0 if -p
$File::Next
::name
;
138 foreach my $filter (@ifiles_filters) {
139 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
140 return 0 if ! $resource || $filter->filter($resource);
146 foreach my $filter (@{$filters}) {
147 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
148 return 0 if ! $resource;
149 if ($filter->filter($resource)) {
155 # Don't bother invoking inverse filters unless we consider the current resource a match
156 if ( $match_found && @{$inverse_filters} ) {
157 foreach my $filter ( @{$inverse_filters} ) {
158 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
159 return 0 if ! $resource;
160 if ( not $filter->filter( $resource ) ) {
171 my $resource = shift;
174 my @types = App
::Ack
::filetypes
( $resource );
175 my $types = join( ',', @types );
176 my $arrow = @types ? ' => ' : ' =>';
177 App
::Ack
::print( $resource->name, $arrow, join( ',', @types ), $ors );
183 my @arg_sources = App
::Ack
::retrieve_arg_sources
();
185 my $opt = App
::Ack
::ConfigLoader
::process_args
( @arg_sources );
187 $App::Ack
::report_bad_filenames
= !$opt->{dont_report_bad_filenames
};
189 if ( $opt->{flush
} ) {
193 if ( not defined $opt->{color
} ) {
194 $opt->{color
} = !App
::Ack
::output_to_pipe
() && !$App::Ack
::is_windows
;
196 if ( not defined $opt->{heading
} and not defined $opt->{break} ) {
197 $opt->{heading
} = $opt->{break} = !App
::Ack
::output_to_pipe
();
200 if ( defined($opt->{H
}) || defined($opt->{h
}) ) {
201 $opt->{show_filename
}= $opt->{H
} && !$opt->{h
};
204 if ( my $output = $opt->{output
} ) {
205 $output =~ s{\\}{\\\\}g;
206 $output =~ s{"}{\\"}g;
207 $opt->{output
} = qq{"$output"};
211 if ( $App::Ack
::is_filter_mode
&& !$opt->{files_from
} ) { # probably -x
212 $resources = App
::Ack
::Resources-
>from_stdin( $opt );
213 my $regex = $opt->{regex
};
214 $regex = shift @ARGV if not defined $regex;
215 $opt->{regex
} = App
::Ack
::build_regex
( $regex, $opt );
218 if ( $opt->{f
} || $opt->{lines
} ) {
219 if ( $opt->{regex
} ) {
220 App
::Ack
::warn( "regex ($opt->{regex}) specified with -f or --lines" );
221 App
::Ack
::exit_from_ack
( 0 ); # XXX the 0 is misleading
225 my $regex = $opt->{regex
};
226 $regex = shift @ARGV if not defined $regex;
227 $opt->{regex
} = App
::Ack
::build_regex
( $regex, $opt );
230 if ( not defined $opt->{files_from
} ) {
233 if ( !exists($opt->{show_filename
}) ) {
234 unless(@start == 1 && !(-d
$start[0])) {
235 $opt->{show_filename
} = 1;
239 if ( defined $opt->{files_from
} ) {
240 $resources = App
::Ack
::Resources-
>from_file( $opt, $opt->{files_from
} );
241 exit 1 unless $resources;
244 @start = ('.') unless @start;
245 foreach my $target (@start) {
246 if ( !-e
$target && $App::Ack
::report_bad_filenames
) {
247 App
::Ack
::warn( "$target: No such file or directory" );
251 $opt->{file_filter
} = _compile_file_filter
($opt, \
@start);
252 $opt->{descend_filter
} = _compile_descend_filter
($opt);
254 $resources = App
::Ack
::Resources-
>from_argv( $opt, \
@start );
257 App
::Ack
::set_up_pager
( $opt->{pager
} ) if defined $opt->{pager
};
259 my $print_filenames = $opt->{show_filename
};
260 my $max_count = $opt->{m
};
261 my $ors = $opt->{print0
} ? "\0" : "\n";
262 my $only_first = $opt->{1};
267 while ( my $resource = $resources->next ) {
268 # XXX this variable name combined with what we're trying
269 # to do makes no sense.
271 # XXX Combine the -f and -g functions
273 # XXX printing should probably happen inside of App::Ack
274 if ( $opt->{show_types
} ) {
275 show_types
( $resource, $ors );
278 App
::Ack
::print( $resource->name, $ors );
281 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
283 elsif ( $opt->{g
} ) {
284 my $is_match = ( $resource->name =~ /$opt->{regex}/o );
285 if ( $opt->{v
} ? !$is_match : $is_match ) {
286 if ( $opt->{show_types
} ) {
287 show_types
( $resource, $ors );
290 App
::Ack
::print( $resource->name, $ors );
293 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
296 elsif ( $opt->{lines
} ) {
297 my $print_filename = $opt->{show_filename
};
298 my $passthru = $opt->{passthru
};
301 foreach my $line ( @{ $opt->{lines
} } ) {
302 my @lines = split /,/, $line;
308 @line_numbers{@lines} = (1) x
@lines;
311 my $filename = $resource->name;
313 local $opt->{color
} = 0;
315 App
::Ack
::iterate
($resource, $opt, sub {
318 if ( $line_numbers{$.} ) {
319 App
::Ack
::print_line_with_context
($opt, $filename, $_, $.);
321 elsif ( $passthru ) {
322 App
::Ack
::print_line_with_options
($opt, $filename, $_, $., ':');
327 elsif ( $opt->{count
} ) {
328 my $matches_for_this_file = App
::Ack
::count_matches_in_resource
( $resource, $opt );
330 unless ( $opt->{show_filename
} ) {
331 $total_count += $matches_for_this_file;
335 if ( !$opt->{l
} || $matches_for_this_file > 0) {
336 if ( $print_filenames ) {
337 App
::Ack
::print( $resource->name, ':', $matches_for_this_file, $ors );
340 App
::Ack
::print( $matches_for_this_file, $ors );
344 elsif ( $opt->{l
} || $opt->{L
} ) {
345 my $is_match = App
::Ack
::resource_has_match
( $resource, $opt );
347 if ( $opt->{L
} ? !$is_match : $is_match ) {
348 App
::Ack
::print( $resource->name, $ors );
351 last RESOURCES
if $only_first;
352 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
356 $nmatches += App
::Ack
::print_matches_in_resource
( $resource, $opt );
357 if ( $nmatches && $only_first ) {
363 if ( $opt->{count
} && !$opt->{show_filename
} ) {
364 App
::Ack
::print( $total_count, "\n" );
368 App
::Ack
::exit_from_ack
( $nmatches );
374 ack - grep-like text finder
378 ack [options] PATTERN [FILE...]
379 ack -f [options] [DIRECTORY...]
383 Ack is designed as a replacement for 99% of the uses of F<grep>.
385 Ack searches the named input FILEs (or standard input if no files
386 are named, or the file name - is given) for lines containing a match
387 to the given PATTERN. By default, ack prints the matching lines.
389 PATTERN is a Perl regular expression. Perl regular expressions
390 are commonly found in other programming languages, but for the particulars
391 of their behavior, please consult
392 L<http://perldoc.perl.org/perlreref.html|perlreref>. If you don't know
393 how to use regular expression but are interested in learning, you may
394 consult L<http://perldoc.perl.org/perlretut.html|perlretut>. If you do not
395 need or want ack to use regular expressions, please see the
396 C<-Q>/C<--literal> option.
398 Ack can also list files that would be searched, without actually
399 searching them, to let you take advantage of ack's file-type filtering
402 =head1 FILE SELECTION
404 If files are not specified for searching, either on the command
405 line or piped in with the C<-x> option, I<ack> delves into
406 subdirectories selecting files for searching.
408 I<ack> is intelligent about the files it searches. It knows about
409 certain file types, based on both the extension on the file and,
410 in some cases, the contents of the file. These selections can be
411 made with the B<--type> option.
413 With no file selection, I<ack> searches through regular files that
414 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
415 options, either present in F<ackrc> files or on the command line.
417 The default options for I<ack> ignore certain files and directories. These
422 =item * Backup files: Files matching F<#*#> or ending with F<~>.
424 =item * Coredumps: Files matching F<core.\d+>
426 =item * Version control directories like F<.svn> and F<.git>.
430 Run I<ack> with the C<--dump> option to see what settings are set.
432 However, I<ack> always searches the files given on the command line,
433 no matter what type. If you tell I<ack> to search in a coredump,
434 it will search in a coredump.
436 =head1 DIRECTORY SELECTION
438 I<ack> descends through the directory tree of the starting directories
439 specified. If no directories are specified, the current working directory is
440 used. However, it will ignore the shadow directories used by
441 many version control systems, and the build directories used by the
442 Perl MakeMaker system. You may add or remove a directory from this
443 list with the B<--[no]ignore-dir> option. The option may be repeated
444 to add/remove multiple directories from the ignore list.
446 For a complete list of directories that do not get searched, run
449 =head1 WHEN TO USE GREP
451 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
452 throw I<grep> away, because there are times you'll still need it.
454 E.g., searching through huge files looking for regexes that can be
455 expressed with I<grep> syntax should be quicker with I<grep>.
457 If your script or parent program uses I<grep> C<--quiet> or C<--silent>
458 or needs exit 2 on IO error, use I<grep>.
464 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
466 Print I<NUM> lines of trailing context after matching lines.
468 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
470 Print I<NUM> lines of leading context before matching lines.
474 Print a break between results from different files. On by default
475 when used interactively.
477 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
479 Print I<NUM> lines (default 2) of context around matching lines.
481 =item B<-c>, B<--count>
483 Suppress normal output; instead print a count of matching lines for
484 each input file. If B<-l> is in effect, it will only show the
485 number of lines for each file that has lines matching. Without
486 B<-l>, some line counts may be zeroes.
488 If combined with B<-h> (B<--no-filename>) ack outputs only one total
491 =item B<--color>, B<--nocolor>, B<--colour>, B<--nocolour>
493 B<--color> highlights the matching text. B<--nocolor> supresses
494 the color. This is on by default unless the output is redirected.
496 On Windows, this option is off by default unless the
497 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
498 environment variable is used.
500 =item B<--color-filename=I<color>>
502 Sets the color to be used for filenames.
504 =item B<--color-match=I<color>>
506 Sets the color to be used for matches.
508 =item B<--color-lineno=I<color>>
510 Sets the color to be used for line numbers.
512 =item B<--[no]column>
514 Show the column number of the first match. This is helpful for
515 editors that can place your cursor at a given position.
517 =item B<--create-ackrc>
519 Dumps the default ack options to standard output. This is useful for
520 when you want to customize the defaults.
524 Writes the list of options loaded and where they came from to standard
525 output. Handy for debugging.
527 =item B<--env>, B<--noenv>
529 B<--noenv> disables all environment processing. No F<.ackrc> is
530 read and all environment variables are ignored. By default, F<ack>
531 considers F<.ackrc> and settings in the environment.
535 B<--flush> flushes output immediately. This is off by default
536 unless ack is running interactively (when output goes to a pipe or
541 Only print the files that would be searched, without actually doing
542 any searching. PATTERN must not be specified, or it will be taken
545 =item B<--files-from=I<FILE>>
547 The list of files to be searched is specified in I<FILE>. The list of
548 files are seperated by newlines. If I<FILE> is C<->, the list is loaded
551 =item B<--[no]filter>
553 Forces ack to act as if it were recieving input via a pipe.
555 =item B<--follow>, B<--nofollow>
557 Follow or don't follow symlinks, other than whatever starting files
558 or directories were specified on the command line.
560 This is off by default.
564 Print files where the relative path + filename matches I<REGEX>.
566 =item B<--group>, B<--nogroup>
568 B<--group> groups matches by file name. This is the default
569 when used interactively.
571 B<--nogroup> prints one result per line, like grep. This is the
572 default when output is redirected.
574 =item B<-H>, B<--with-filename>
576 Print the filename for each match.
578 =item B<-h>, B<--no-filename>
580 Suppress the prefixing of filenames on output when multiple files are
583 =item B<--[no]heading>
585 Print a filename heading above each file's results. This is the default
586 when used interactively.
588 =item B<--help>, B<-?>
590 Print a short help statement.
592 =item B<--help-types>, B<--help=types>
594 Print all known types.
596 =item B<-i>, B<--ignore-case>
598 Ignore case in the search strings.
600 =item B<--ignore-ack-defaults>
602 Tells ack to completely ignore the default definitions provided with ack.
603 This is useful in combination with B<--create-ackrc> if you I<really> want
606 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
608 Ignore directory (as CVS, .svn, etc are ignored). May be used
609 multiple times to ignore multiple directories. For example, mason
610 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
611 option allows users to search directories which would normally be
612 ignored (perhaps to research the contents of F<.svn/props> directories).
614 The I<DIRNAME> must always be a simple directory name. Nested
615 directories like F<foo/bar> are NOT supported. You would need to
616 specify B<--ignore-dir=foo> and then no files from any foo directory
617 are taken into account by ack unless given explicitly on the command
620 =item B<--ignore-file=I<FILTERTYPE:FILTERARGS>>
622 Ignore files matching I<FILTERTYPE:FILTERARGS>. The filters are specified
623 identically to file type filters as seen in L</"Defining your own types">.
625 =item B<-k>, B<--known-types>
627 Limit selected files to those with types that ack knows about. This is
628 equivalent to the default behavior found in ack 1.
630 =item B<--lines=I<NUM>>
632 Only print line I<NUM> of each file. Multiple lines can be given with multiple
633 B<--lines> options or as a comma separated list (B<--lines=3,5,7>). B<--lines=4-7>
634 also works. The lines are always output in ascending order, no matter the
635 order given on the command line.
637 =item B<-l>, B<--files-with-matches>
639 Only print the filenames of matching files, instead of the matching text.
641 =item B<-L>, B<--files-without-matches>
643 Only print the filenames of files that do I<NOT> match.
645 =item B<--match I<REGEX>>
647 Specify the I<REGEX> explicitly. This is helpful if you don't want to put the
648 regex as your first argument, e.g. when executing multiple searches over the
651 # search for foo and bar in given files
652 ack file1 t/file* --match foo
653 ack file1 t/file* --match bar
655 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
657 Stop reading a file after I<NUM> matches.
661 Print this manual page.
663 =item B<-n>, B<--no-recurse>
665 No descending into subdirectories.
669 Show only the part of each line matching PATTERN (turns off text
672 =item B<--output=I<expr>>
674 Output the evaluation of I<expr> for each line (turns off text
676 If PATTERN matches more than once then a line is output for each non-overlapping match.
677 For more information please see the section L</"Examples of F<--output>">.
679 =item B<--pager=I<program>>, B<--nopager>
681 B<--pager> directs ack's output through I<program>. This can also be specified
682 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
684 Using --pager does not suppress grouping and coloring like piping
685 output on the command-line does.
687 B<--nopager> cancels any setting in ~/.ackrc, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
688 No output will be sent through a pager.
692 Prints all lines, whether or not they match the expression. Highlighting
693 will still work, though, so it can be used to highlight matches while
694 still seeing the entire file, as in:
696 # Watch a log file, and highlight a certain IP address
697 $ tail -f ~/access.log | ack --passthru 123.45.67.89
701 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
702 are output separated with a null byte instead of the usual newline. This is
703 helpful when dealing with filenames that contain whitespace, e.g.
705 # remove all files of type html
706 ack -f --html --print0 | xargs -0 rm -f
708 =item B<-Q>, B<--literal>
710 Quote all metacharacters in PATTERN, it is treated as a literal.
712 =item B<-r>, B<-R>, B<--recurse>
714 Recurse into sub-directories. This is the default and just here for
715 compatibility with grep. You can also use it for turning B<--no-recurse> off.
719 Suppress error messages about nonexistent or unreadable files. This is taken
722 =item B<--[no]smart-case>, B<--no-smart-case>
724 Ignore case in the search strings if PATTERN contains no uppercase
725 characters. This is similar to C<smartcase> in vim. This option is
728 B<-i> always overrides this option.
730 =item B<--sort-files>
732 Sorts the found files lexicographically. Use this if you want your file
733 listings to be deterministic between runs of I<ack>.
735 =item B<--show-types>
737 Outputs the filetypes that ack associates with each file.
739 Works with B<-f> and B<-g> options.
741 =item B<--type=TYPE>, B<--type=noTYPE>
743 Specify the types of files to include or exclude from a search.
744 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
745 also be specified as B<--perl>, and B<--type=noperl> can be done
748 If a file is of both type "foo" and "bar", specifying --foo and
749 --nobar will exclude the file, because an exclusion takes precedence
752 Type specifications can be repeated and are ORed together.
754 See I<ack --help=types> for a list of valid types.
756 =item B<--type-add I<TYPE>:I<FILTER>:I<FILTERARGS>>
758 Files with the given FILTERARGS applied to the given FILTER
759 are recognized as being of (the existing) type TYPE.
760 See also L</"Defining your own types">.
763 =item B<--type-set I<TYPE>:I<FILTER>:I<FILTERARGS>>
765 Files with the given FILTERARGS applied to the given FILTER are recognized as
766 being of type TYPE. This replaces an existing definition for type TYPE. See
767 also L</"Defining your own types">.
769 =item B<--type-del I<TYPE>>
771 The filters associated with TYPE are removed from Ack, and are no longer considered
774 =item B<-v>, B<--invert-match>
776 Invert match: select non-matching lines
780 Display version and copyright information.
782 =item B<-w>, B<--word-regexp>
784 Force PATTERN to match only whole words. The PATTERN is wrapped with
785 C<\b> metacharacters.
789 An abbreviation for B<--files-from=->; the list of files to search are read
790 from standard input, with one line per file.
794 Stops after reporting first match of any kind. This is different
795 from B<--max-count=1> or B<-m1>, where only one match per file is
796 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
801 Display the all-important Bill The Cat logo. Note that the exact
802 spelling of B<--thpppppt> is not important. It's checked against
803 a regular expression.
807 Check with the admiral for traps.
811 =head1 THE .ackrc FILE
813 The F<.ackrc> file contains command-line options that are prepended
814 to the command line before processing. Multiple options may live
815 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
816 might look like this:
818 # Always sort the files
821 # Always color, even if piping to a another program
824 # Use "less -r" as my pager
827 Note that arguments with spaces in them do not need to be quoted,
828 as they are not interpreted by the shell. Basically, each I<line>
829 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
831 F<ack> looks in several locations for F<.ackrc> files; the searching
832 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
833 files are not considered if B<--noenv> is specified on the command line.
835 =head1 Defining your own types
837 ack allows you to define your own types in addition to the predefined
838 types. This is done with command line options that are best put into
839 an F<.ackrc> file - then you do not have to define your types over and
840 over again. In the following examples the options will always be shown
841 on one command line so that they can be easily copy & pasted.
843 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
844 tells you, that perl files are files ending
845 in .pl, .pm, .pod or .t. So what if you would like to include .xs
846 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
847 does this for you. B<--type-add> appends
848 additional extensions to an existing type.
850 If you want to define a new type, or completely redefine an existing
851 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
852 the type I<eiffel> to include files with
853 the extensions .e or .eiffel. So to search for all eiffel files
854 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
855 As usual, you can also write B<--type=eiffel>
856 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
857 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
858 and I<.xs> files no longer belong to the type I<cc>.
860 When defining your own types in the F<.ackrc> file you have to use
863 --type-set=eiffel:ext:e,eiffel
865 or writing on separate lines
870 The following does B<NOT> work in the F<.ackrc> file:
872 --type-set eiffel:ext:e,eiffel
875 In order to see all currently defined types, use I<--help-types>, e.g.
876 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
878 In addition to filtering based on extension (like ack 1.x allowed), ack 2
879 offers additional filter types. The generic syntax is
880 I<--type-set TYPE:FILTER:FILTERARGS>; I<FILTERARGS> depends on the value
887 I<is> filters match the target filename exactly. It takes exactly one
888 argument, which is the name of the file to match.
892 --type-set make:is:Makefile
894 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
896 I<ext> filters match the extension of the target file against a list
897 of extensions. No leading dot is needed for the extensions.
901 --type-set perl:ext:pl,pm,t
905 I<match> filters match the target filename against a regular expression.
906 The regular expression is made case insensitive for the search.
910 --type-set make:match:/(gnu)?makefile/
912 =item firstlinematch:I<REGEX>
914 I<firstlinematch> matches the first line of the target file against a
915 regular expression. Like I<match>, the regular expression is made
920 --type-add perl:firstlinematch:/perl/
924 More filter types may be made available in the future.
926 =head1 ENVIRONMENT VARIABLES
928 For commonly-used ack options, environment variables can make life
929 much easier. These variables are ignored if B<--noenv> is specified
936 Specifies the location of the user's F<.ackrc> file. If this file doesn't
937 exist, F<ack> looks in the default location.
941 This variable specifies default options to be placed in front of
942 any explicit options on the command line.
944 =item ACK_COLOR_FILENAME
946 Specifies the color of the filename when it's printed in B<--group>
947 mode. By default, it's "bold green".
949 The recognized attributes are clear, reset, dark, bold, underline,
950 underscore, blink, reverse, concealed black, red, green, yellow,
951 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
952 on_magenta, on_cyan, and on_white. Case is not significant.
953 Underline and underscore are equivalent, as are clear and reset.
954 The color alone sets the foreground color, and on_color sets the
957 This option can also be set with B<--color-filename>.
959 =item ACK_COLOR_MATCH
961 Specifies the color of the matching text when printed in B<--color>
962 mode. By default, it's "black on_yellow".
964 This option can also be set with B<--color-match>.
966 See B<ACK_COLOR_FILENAME> for the color specifications.
968 =item ACK_COLOR_LINENO
970 Specifies the color of the line number when printed in B<--color>
971 mode. By default, it's "bold yellow".
973 This option can also be set with B<--color-lineno>.
975 See B<ACK_COLOR_FILENAME> for the color specifications.
979 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
980 ack will send its output.
982 Using C<ACK_PAGER> does not suppress grouping and coloring like
983 piping output on the command-line does, except that on Windows
984 ack will assume that C<ACK_PAGER> does not support color.
986 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
988 =item ACK_PAGER_COLOR
990 Specifies a pager program that understands ANSI color sequences.
991 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
992 like piping output on the command-line does.
994 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
998 =head1 ACK & OTHER TOOLS
1000 =head2 Vim integration
1002 F<ack> integrates easily with the Vim text editor. Set this in your
1003 F<.vimrc> to use F<ack> instead of F<grep>:
1007 That example uses C<-k> to search through only files of the types ack
1008 knows about, but you may use other default flags. Now you can search
1009 with F<ack> and easily step through the results in Vim:
1011 :grep Dumper perllib
1013 =head2 Emacs integration
1015 Phil Jackson put together an F<ack.el> extension that "provides a
1016 simple compilation mode ... has the ability to guess what files you
1017 want to search for based on the major-mode."
1019 L<http://www.shellarchive.co.uk/content/emacs.html>
1021 =head2 TextMate integration
1023 Pedro Melo is a TextMate user who writes "I spend my day mostly
1024 inside TextMate, and the built-in find-in-project sucks with large
1025 projects. So I hacked a TextMate command that was using find +
1026 grep to use ack. The result is the Search in Project with ack, and
1027 you can find it here:
1028 L<http://www.simplicidade.org/notes/archives/2008/03/search_in_proje.html>"
1030 =head2 Shell and Return Code
1032 For greater compatibility with I<grep>, I<ack> in normal use returns
1033 shell return or exit code of 0 only if something is found and 1 if
1036 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
1038 The I<grep> code 2 for errors is not used.
1040 If C<-f> or C<-g> are specified, then 0 is returned if at least one
1041 file is found. If no files are found, then 1 is returned.
1045 =head1 DEBUGGING ACK PROBLEMS
1047 If ack gives you output you're not expecting, start with a few simple steps.
1049 =head2 Use B<--noenv>
1051 Your environment variables and F<.ackrc> may be doing things you're
1052 not expecting, or forgotten you specified. Use B<--noenv> to ignore
1053 your environment and F<.ackrc>.
1055 =head2 Use B<-f> to see what files have been selected
1057 Ack's B<-f> was originally added as a debugging tool. If ack is
1058 not finding matches you think it should find, run F<ack -f> to see
1059 what files have been selected. You can also add the C<--show-types>
1060 options to show the type of each file selected.
1062 =head2 Use B<--dump>
1064 This lists the ackrc files that are loaded and the options loaded
1066 So for example you can find a list of directories that do not get searched or where filetypes are defined.
1070 =head2 Use the F<.ackrc> file.
1072 The F<.ackrc> is the place to put all your options you use most of
1073 the time but don't want to remember. Put all your --type-add and
1074 --type-set definitions in it. If you like --smart-case, set it
1075 there, too. I also set --sort-files there.
1077 =head2 Use F<-f> for working with big codesets
1079 Ack does more than search files. C<ack -f --perl> will create a
1080 list of all the Perl files in a tree, ideal for sending into F<xargs>.
1083 # Change all "this" to "that" in all Perl files in a tree.
1084 ack -f --perl | xargs perl -p -i -e's/this/that/g'
1088 perl -p -i -e's/this/that/g' $(ack -f --perl)
1090 =head2 Use F<-Q> when in doubt about metacharacters
1092 If you're searching for something with a regular expression
1093 metacharacter, most often a period in a filename or IP address, add
1094 the -Q to avoid false positives without all the backslashing. See
1095 the following example for more...
1097 =head2 Use ack to watch log files
1099 Here's one I used the other day to find trouble spots for a website
1100 visitor. The user had a problem loading F<troublesome.gif>, so I
1101 took the access log and scanned it with ack twice.
1103 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
1105 The first ack finds only the lines in the Apache log for the given
1106 IP. The second finds the match on my troublesome GIF, and shows
1107 the previous five lines from the log in each case.
1109 =head2 Examples of F<--output>
1111 Following variables are useful in the expansion string:
1117 The whole string matched by PATTERN.
1119 =item C<$1>, C<$2>, ...
1121 The contents of the 1st, 2nd ... bracketed group in PATTERN.
1125 The string before the match.
1129 The string after the match.
1133 For more details and other variables see
1134 L<http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions|perlvar>.
1136 This example shows how to add text around a particular pattern
1137 (in this case adding _ around word with "e")
1139 ack2.pl "\w*e\w*" quick.txt --output="$`_$&_$'"
1140 _The_ quick brown fox jumps over the lazy dog
1141 The quick brown fox jumps _over_ the lazy dog
1142 The quick brown fox jumps over _the_ lazy dog
1144 This shows how to pick out particular parts of a match using ( ) within regular expression.
1146 ack '=head(\d+)\s+(.*)' --output=' $1 : $2'
1147 input file contains "=head1 NAME"
1150 =head2 Share your knowledge
1152 Join the ack-users mailing list. Send me your tips and I may add
1157 =head2 Why isn't ack finding a match in (some file)?
1159 Probably because it's of a type that ack doesn't recognize. ack's
1160 searching behavior is driven by filetype. B<If ack doesn't know
1161 what kind of file it is, ack ignores the file.>
1163 Use the C<-f> switch to see a list of files that ack will search
1166 If you want ack to search files that it doesn't recognize, use the
1169 If you want ack to search every file, even ones that it always
1170 ignores like coredumps and backup files, use the C<-u> switch.
1172 =head2 Why does ack ignore unknown files by default?
1174 ack is designed by a programmer, for programmers, for searching
1175 large trees of code. Most codebases have a lot files in them which
1176 aren't source files (like compiled object files, source control
1177 metadata, etc), and grep wastes a lot of time searching through all
1178 of those as well and returning matches from those files.
1180 That's why ack's behavior of not searching things it doesn't recognize
1181 is one of its greatest strengths: the speed you get from only
1182 searching the things that you want to be looking at.
1184 =head2 Wouldn't it be great if F<ack> did search & replace?
1186 No, ack will always be read-only. Perl has a perfectly good way
1187 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
1190 You can certainly use ack to select your files to update. For
1191 example, to change all "foo" to "bar" in all PHP files, you can do
1192 this from the Unix shell:
1194 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
1196 =head2 Can you make ack recognize F<.xyz> files?
1198 Yes! Please see L</"Defining your own types">. If you think
1199 that F<ack> should recognize a type by default, please see
1202 =head2 There's already a program/package called ack.
1206 =head2 Why is it called ack if it's called ack-grep?
1208 The name of the program is "ack". Some packagers have called it
1209 "ack-grep" when creating packages because there's already a package
1210 out there called "ack" that has nothing to do with this ack.
1212 I suggest you make a symlink named F<ack> that points to F<ack-grep>
1213 because one of the crucial benefits of ack is having a name that's
1214 so short and simple to type.
1216 To do that, run this with F<sudo> or as root:
1218 ln -s /usr/bin/ack-grep /usr/bin/ack
1220 Alternatively, you could use a shell alias:
1228 =head2 What does F<ack> mean?
1230 Nothing. I wanted a name that was easy to type and that you could
1231 pronounce as a single syllable.
1233 =head2 Can I do multi-line regexes?
1235 No, ack does not support regexes that match multiple lines. Doing
1236 so would require reading in the entire file at a time.
1238 If you want to see lines near your match, use the C<--A>, C<--B>
1239 and C<--C> switches for displaying context.
1241 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
1243 ack treats command line options beginning with C<+> or C<-> as options; if you
1244 would like to search for these, you may prefix your search term with C<--> or
1245 use the C<--match> option. (However, don't forget that C<+> is a regular
1246 expression metacharacter!)
1248 =head1 ACKRC LOCATION SEMANTICS
1250 Ack can load its configuration from many sources. This list
1251 specifies the sources Ack looks for configuration; each one
1252 that is found is loaded in the order specified here, and
1253 each one overrides options set in any of the sources preceding
1254 it. (For example, if I set --sort-files in my user ackrc, and
1255 --nosort-files on the command line, the command line takes
1262 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
1263 using C<--ignore-ack-defaults>.
1265 =item * Global ackrc
1267 Options are then loaded from the global ackrc. This is located at
1268 C</etc/ackrc> on Unix-like systems, and
1269 C<C:\Documents and Settings\All Users\Application Data> on Windows.
1270 This can be omitted using C<--noenv>.
1274 Options are then loaded from the user's ackrc. This is located at
1275 C<$HOME/.ackrc> on Unix-like systems, and
1276 C<C:\Documents and Settings\$USER\Application Data>. If a different
1277 ackrc is desired, it may be overriden with the C<$ACKRC> environment
1279 This can be omitted using C<--noenv>.
1281 =item * Project ackrc
1283 Options are then loaded from the project ackrc. The project ackrc is
1284 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
1285 in the current directory, then the parent directory, then the grandparent
1286 directory, etc. This can be omitted using C<--noenv>.
1290 Options are then loaded from the enviroment variable C<ACK_OPTIONS>. This can
1291 be omitted using C<--noenv>.
1293 =item * Command line
1295 Options are then loaded from the command line.
1299 =head1 DIFFERENCES BETWEEN ACK 1.X AND ACK 2.X
1301 A lot of changes were made for ack 2; here is a list of them.
1303 =head2 GENERAL CHANGES
1309 When no selectors are specified, ack 1.x only searches through files that
1310 it can map to a file type. ack 2.x, by constrast, will search through
1311 every regular, non-binary file that is not explicitly ignored via
1312 B<--ignore-file> or B<--ignore-dir>. This is similar to the behavior of the
1313 B<-a/--all> option in ack 1.x.
1317 A more flexible filter system has been added, so that more powerful file types
1318 may be created by the user. For details, please consult
1319 L</"Defining your own types">.
1323 ack now loads multiple ackrc files; see L</"ACKRC LOCATION SEMANTICS"> for
1328 ack's default filter definitions aren't special; you may tell ack to
1329 completely disregard them if you don't like them.
1333 =head2 REMOVED OPTIONS
1339 Because of the change in default search behavior, the B<-a/--all> and
1340 B<-u/--unrestricted> options have been removed. In addition, the
1341 B<-k/--known-types> option was added to cause ack to behave with
1342 the default search behavior of ack 1.x.
1346 The B<-G> option has been removed. Two regular expressions on the
1347 command line was considered too confusing; to simulate B<-G>'s functionality,
1348 you may use the new B<-x> option to pipe filenames from one invocation of
1353 The B<--binary> option has been removed.
1357 The B<--skipped> option has been removed.
1361 The B<--text> option has been removed.
1365 The B<--invert-file-match> option has been removed. Instead, you may
1366 use B<-v> with B<-g>.
1370 =head2 CHANGED OPTIONS
1376 The options that modify the regular expression's behavior (B<-i>, B<-w>,
1377 B<-Q>, and B<-v>) may now be used with B<-g>.
1381 =head2 ADDED OPTIONS
1387 B<--files-from> was added so that a user may submit a list of filenames as
1388 a list of files to search.
1392 B<-x> was added to tell ack to accept a list of filenames via standard input;
1393 this list is the list of filenames that will be used for the search.
1397 B<-s> was added to tell ack to suppress error messages about non-existent or
1402 B<--ignore-directory> and B<--noignore-directory> were added as aliases for
1403 B<--ignore-dir> and B<--noignore-dir> respectively.
1407 B<--ignore-file> was added so that users may specify patterns of files to
1408 ignore (ex. /.*~$/).
1412 B<--dump> was added to allow users to easily find out which options are
1417 B<--create-ackrc> was added so that users may create custom ackrc files based
1418 on the default settings loaded by ack, and so that users may easily view those
1423 B<--type-del> was added to selectively remove file type definitions.
1427 B<--ignore-ack-defaults> was added so that users may ignore ack's default
1428 options in favor of their own.
1432 B<--bar> was added so ack users may consult Admiral Ackbar.
1438 Andy Lester, C<< <andy at petdance.com> >>
1442 Please report any bugs or feature requests to the issues list at
1443 Github: L<https://github.com/petdance/ack2/issues>
1447 All enhancement requests MUST first be posted to the ack-users
1448 mailing list at L<http://groups.google.com/group/ack-users>. I
1449 will not consider a request without it first getting seen by other
1450 ack users. This includes requests for new filetypes.
1452 There is a list of enhancements I want to make to F<ack> in the ack
1453 issues list at Github: L<https://github.com/petdance/ack2/issues>
1455 Patches are always welcome, but patches with tests get the most
1460 Support for and information about F<ack> can be found at:
1464 =item * The ack homepage
1466 L<http://betterthangrep.com/>
1468 =item * The ack-users mailing list
1470 L<http://groups.google.com/group/ack-users>
1472 =item * The ack issues list at Github
1474 L<https://github.com/petdance/ack2/issues>
1476 =item * AnnoCPAN: Annotated CPAN documentation
1478 L<http://annocpan.org/dist/ack>
1480 =item * CPAN Ratings
1482 L<http://cpanratings.perl.org/d/ack>
1486 L<http://search.cpan.org/dist/ack>
1488 =item * Git source repository
1490 L<https://github.com/petdance/ack2>
1494 =head1 ACKNOWLEDGEMENTS
1496 How appropriate to have I<ack>nowledgements!
1498 Thanks to everyone who has contributed to ack in any way, including
1519 Eric Van Dewoestine,
1528 Christopher J. Madsen,
1540 GE<aacute>bor SzabE<oacute>,
1543 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
1547 Mark Leighton Fisher,
1553 Nilson Santos F. Jr,
1558 Ask BjE<oslash>rn Hansen,
1562 Slaven ReziE<0x107>,
1572 =head1 COPYRIGHT & LICENSE
1574 Copyright 2005-2013 Andy Lester.
1576 This program is free software; you can redistribute it and/or modify
1577 it under the terms of the Artistic License v2.0.
1579 See http://www.perlfoundation.org/artistic_license_2_0 or the LICENSE.md
1580 file that comes with the ack distribution.
1589 our $VERSION = '1.12';
1595 our $name; # name of the current file
1596 our $dir; # dir of the current file
1598 our %files_defaults;
1603 file_filter
=> undef,
1604 descend_filter
=> undef,
1605 error_handler
=> sub { CORE
::die @_ },
1606 warning_handler
=> sub { CORE
::warn @_ },
1607 sort_files
=> undef,
1608 follow_symlinks
=> 1,
1611 %skip_dirs = map {($_,1)} (File
::Spec-
>curdir, File
::Spec-
>updir);
1616 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
1618 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
1619 my $filter = $parms->{file_filter
};
1623 my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 );
1624 if ( -f
$fullpath || -p
$fullpath || $fullpath =~ m{^/dev/fd} ) {
1627 local $File::Next
::dir
= $dirname;
1628 local $File::Next
::name
= $fullpath;
1629 next if not $filter->();
1631 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
1634 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
1648 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
1650 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
1651 my $err = $parms->{error_handler
};
1652 my $warn = $parms->{error_handler
};
1654 my $filename = $queue[1];
1656 if ( !defined($filename) ) {
1657 $err->( 'Must pass a filename to from_file()' );
1662 if ( $filename eq '-' ) {
1666 if ( !open( $fh, '<', $filename ) ) {
1667 $err->( "Unable to open $filename: $!" );
1671 my $filter = $parms->{file_filter
};
1674 local $/ = $parms->{nul_separated
} ? "\x00" : $/;
1675 while ( my $fullpath = <$fh> ) {
1677 next unless $fullpath =~ /./;
1678 if ( not ( -f
$fullpath || -p _
) ) {
1679 $warn->( "$fullpath: No such file" );
1683 my ($volume,$dirname,$file) = File
::Spec-
>splitpath( $fullpath );
1686 local $File::Next
::dir
= $dirname;
1687 local $File::Next
::name
= $fullpath;
1688 next if not $filter->();
1690 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
1698 sub _bad_invocation
{
1699 my $good = (caller(1))[3];
1701 $bad =~ s/(.+)::/$1->/;
1702 return "$good must not be invoked as $bad";
1705 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
1706 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
1711 my @parts = split( /\//, $path );
1713 return $path if @parts < 2;
1715 return File
::Spec-
>catfile( @parts );
1721 my $defaults = shift;
1722 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
1724 my %passed_parms = %{$passed_parms};
1727 for my $key ( keys %{$defaults} ) {
1729 exists $passed_parms{$key}
1730 ? delete $passed_parms{$key}
1731 : $defaults->{$key};
1734 # Any leftover keys are bogus
1735 for my $badkey ( keys %passed_parms ) {
1736 my $sub = (caller(1))[3];
1737 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
1740 # If it's not a code ref, assume standard sort
1741 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
1742 $parms->{sort_files
} = \
&sort_standard
;
1747 my $start = reslash
( $_ );
1749 push @queue, ($start,undef,$start);
1752 push @queue, (undef,$start,$start);
1756 return ($parms,@queue);
1760 sub _candidate_files
{
1762 my $dirname = shift;
1765 if ( !opendir $dh, $dirname ) {
1766 $parms->{error_handler
}->( "$dirname: $!" );
1771 my $descend_filter = $parms->{descend_filter
};
1772 my $follow_symlinks = $parms->{follow_symlinks
};
1773 my $sort_sub = $parms->{sort_files
};
1775 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
1778 # Only do directory checking if we have a descend_filter
1779 my $fullpath = File
::Spec-
>catdir( $dirname, $file );
1780 if ( !$follow_symlinks ) {
1781 next if -l
$fullpath;
1785 if ( $descend_filter ) {
1786 if ( $has_stat ? (-d _
) : (-d
$fullpath) ) {
1787 local $File::Next
::dir
= $fullpath;
1789 next if not $descend_filter->();
1793 push( @newfiles, [ $dirname, $file, $fullpath ] );
1796 push( @newfiles, $dirname, $file, $fullpath );
1802 return map { @{$_} } sort $sort_sub @newfiles;
1809 1; # End of File::Next
1815 use Getopt
::Long
2.36 ();
1822 $VERSION = '2.00b06';
1823 $COPYRIGHT = 'Copyright 2005-2013 Andy Lester.';
1824 $GIT_REVISION = q{04e8986};
1839 our $is_filter_mode;
1840 our $output_to_pipe;
1846 use File
::Spec
1.00015 ();
1847 use File
::Glob
1.00015 ':glob';
1850 # These have to be checked before any filehandle diddling.
1851 $output_to_pipe = not -t
*STDOUT
;
1852 $is_filter_mode = -p STDIN
;
1854 $is_cygwin = ($^O eq 'cygwin');
1855 $is_windows = ($^O =~ /MSWin32/);
1856 $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File
::Spec-
>catfile( '', '' ) );
1860 sub retrieve_arg_sources
{
1866 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
1867 Getopt
::Long
::Configure
('pass_through');
1868 Getopt
::Long
::Configure
('no_auto_abbrev');
1870 Getopt
::Long
::GetOptions
(
1872 'ackrc=s' => \
$ackrc,
1875 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
1880 my $finder = App
::Ack
::ConfigFinder-
>new;
1881 @files = $finder->find_config_files;
1884 # we explicitly use open so we get a nice error message
1885 # XXX this is a potential race condition!
1886 if(open my $fh, '<', $ackrc) {
1890 die "Unable to load ackrc '$ackrc': $!"
1892 push( @files, $ackrc );
1895 push @arg_sources, Defaults
=> [ App
::Ack
::ConfigDefault
::options
() ];
1897 foreach my $file ( @files) {
1898 my @lines = read_rcfile
($file);
1899 push ( @arg_sources, $file, \
@lines ) if @lines;
1902 if ( $ENV{ACK_OPTIONS
} && !$noenv ) {
1903 push( @arg_sources, 'ACK_OPTIONS' => $ENV{ACK_OPTIONS
} );
1906 push( @arg_sources, 'ARGV' => [ @ARGV ] );
1908 return @arg_sources;
1914 return unless defined $file && -e
$file;
1918 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
1919 while ( my $line = <$fh> ) {
1924 next if $line eq '';
1925 next if $line =~ /^#/;
1927 push( @lines, $line );
1935 sub create_ignore_rules
{
1940 my @opts = @{$opts};
1944 for my $opt ( @opts ) {
1945 if ( $opt =~ /^(is|ext|regex),(.+)$/ ) {
1948 if ( $method eq 'regex' ) {
1949 push( @{$rules{regex
}}, qr/$arg/ );
1952 ++$rules{$method}{$arg};
1956 App
::Ack
::die( "Invalid argument for --$what: $opt" );
1964 sub remove_dir_sep
{
1966 $path =~ s/[$dir_sep_chars]$//;
1976 defined $str or App
::Ack
::die( 'No regular expression found.' );
1978 $str = quotemeta( $str ) if $opt->{Q
};
1980 $str = "\\b$str" if $str =~ /^\w/;
1981 $str = "$str\\b" if $str =~ /\w$/;
1984 my $regex_is_lc = $str eq lc $str;
1985 if ( $opt->{i
} || ($opt->{smart_case
} && $regex_is_lc) ) {
1996 die "Invalid regex '$str':\n $error";
2006 return unless defined $regex;
2008 eval { qr/$regex/ };
2010 (my $error = $@) =~ s/ at \S+ line \d+.*//;
2012 App
::Ack
::die( "Invalid regex '$regex':\n $error" );
2022 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2027 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2031 require File
::Basename
;
2032 return File
::Basename
::basename
( $0 );
2037 sub filetypes_supported
{
2038 return keys %mappings;
2042 my $y = q{_ /|,\\'!.x',=(www)=, U };
2043 $y =~ tr/,x!w/\nOo_/;
2048 my $y = _get_thpppt
();
2049 App
::Ack
::print( "$y ack $_[0]!\n" );
2057 3~!I#7#I"7#I!?!+!="+"="+!:!
2058 2?#I!7!I!?#I!7!I"+"=%+"=#
2059 1?"+!?*+!=#~"=!+#?"="+!
2060 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2061 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2063 ,,!?%I"?(+$=$~!=#:"~$:!~!
2064 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2065 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2066 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2067 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2068 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2069 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2070 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2071 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2072 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2073 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2074 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2075 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2076 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2077 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2078 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2079 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2080 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2081 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2082 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2083 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2084 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2085 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2086 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2087 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2088 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2089 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2090 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2091 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2092 7+:!,!~#,"=!7'I!?#I"7/+!7+
2093 77I!+!7!?!7!I"71+!7,
2096 $x =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2097 App
::Ack
::print( $x );
2103 my $help_arg = shift || 0;
2105 return show_help_types
() if $help_arg =~ /^types?/;
2107 App
::Ack
::print( <<"END_OF_HELP" );
2108 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2110 Search for PATTERN in each source file in the tree from the current
2111 directory on down. If any files or directories are specified, then
2112 only those files and directories are checked. ack may also search
2113 STDIN, but only if no file or directory arguments are specified,
2114 or if one of them is "-".
2116 Default switches may be specified in ACK_OPTIONS environment variable or
2117 an .ackrc file. If you want no dependency on the environment, turn it
2120 Example: ack -i select
2123 -i, --ignore-case Ignore case distinctions in PATTERN
2124 --[no]smart-case Ignore case distinctions in PATTERN,
2125 only if PATTERN contains no upper case.
2126 Ignored if -i is specified
2127 -v, --invert-match Invert match: select non-matching lines
2128 -w, --word-regexp Force PATTERN to match only whole words
2129 -Q, --literal Quote all metacharacters; PATTERN is literal
2132 --lines=NUM Only print line(s) NUM of each file
2133 -l, --files-with-matches Only print filenames containing matches
2134 -L, --files-without-matches Only print filenames with no matches
2135 --output=expr Output the evaluation of expr for each line
2136 (turns off text highlighting)
2137 -o Show only the part of a line matching PATTERN
2138 Same as --output='\$&'
2139 --passthru Print all lines, whether matching or not
2140 --match PATTERN Specify PATTERN explicitly.
2141 -m, --max-count=NUM Stop searching in each file after NUM matches
2142 -1 Stop searching after one match of any kind
2143 -H, --with-filename Print the filename for each match
2144 -h, --no-filename Suppress the prefixing filename on output
2145 -c, --count Show number of lines matching per file
2146 --[no]column Show the column number of the first match
2148 -A NUM, --after-context=NUM Print NUM lines of trailing context after matching
2150 -B NUM, --before-context=NUM Print NUM lines of leading context before matching
2152 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2154 --print0 Print null byte as separator between filenames,
2155 only works with -f, -g, -l, -L or -c.
2157 -s Suppress error messages about nonexistent or
2162 --pager=COMMAND Pipes all ack output through COMMAND. For example,
2163 --pager="less -R". Ignored if output is redirected.
2164 --nopager Do not send output through a pager. Cancels any
2165 setting in ~/.ackrc, ACK_PAGER or ACK_PAGER_COLOR.
2166 --[no]heading Print a filename heading above each file's results.
2167 (default: on when used interactively)
2168 --[no]break Print a break between results from different files.
2169 (default: on when used interactively)
2170 --group Same as --heading --break
2171 --nogroup Same as --noheading --nobreak
2172 --[no]color Highlight the matching text (default: on unless
2173 output is redirected, or on Windows)
2174 --[no]colour Same as --[no]color
2175 --color-filename=COLOR
2177 --color-lineno=COLOR Set the color for filenames, matches, and line numbers.
2178 --flush Flush output immediately, even when ack is used
2179 non-interactively (when output goes to a pipe or
2184 -f Only print the files selected, without searching.
2185 The PATTERN must not be specified.
2186 -g Same as -f, but only select files matching PATTERN.
2187 --sort-files Sort the found files lexically.
2188 --show-types Show which types each file has.
2189 --files-from=FILE Read the list of files to search from FILE.
2190 -x Read the list of files to search from STDIN.
2192 File inclusion/exclusion:
2193 --[no]ignore-dir=name Add/Remove directory from the list of ignored dirs
2194 --[no]ignore-directory=name Synonym for ignore-dir
2195 --ignore-file=filter Add filter for ignoring files
2196 -r, -R, --recurse Recurse into subdirectories (ack's default behavior)
2197 -n, --no-recurse No descending into subdirectories
2198 --[no]follow Follow symlinks. Default is off.
2199 -k, --known-types Include only files with types that ack recognizes.
2201 --type=X Include only X files, where X is a recognized filetype.
2202 --type=noX Exclude X files.
2203 See "ack --help-types" for supported filetypes.
2205 File type specification:
2206 --type-set TYPE:FILTER:FILTERARGS
2207 Files with the given FILTERARGS applied to the given
2208 FILTER are recognized as being of type TYPE. This
2209 replaces an existing definition for type TYPE.
2210 --type-add TYPE:FILTER:FILTERARGS
2211 Files with the given FILTERARGS applied to the given
2212 FILTER are recognized as being of type TYPE.
2213 --type-del TYPE Removes all filters associated with TYPE.
2217 --[no]env Ignore environment variables and global ackrc files. --env is legal but redundant.
2218 --ackrc=filename Specify an ackrc file to use
2219 --ignore-ack-defaults Ignore the default definitions that ack includes.
2220 --create-ackrc Outputs a default ackrc for your customization to standard output.
2221 --help, -? This help
2222 --help-types Display all known types
2223 --dump Dump information on which options are loaded from which RC files
2224 --[no]filter Force ack to treat standard input as a pipe (--filter) or tty (--nofilter)
2226 --version Display version & copyright
2227 --thpppt Bill the Cat
2228 --bar The warning admiral
2230 Exit status is 0 if match, 1 if no match.
2232 This is version $VERSION of ack.
2240 sub show_help_types
{
2241 App
::Ack
::print( <<'END_OF_HELP' );
2242 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2244 The following is the list of filetypes supported by ack. You can
2245 specify a file type with the --type=TYPE format, or the --TYPE
2246 format. For example, both --type=perl and --perl work.
2248 Note that some extensions may appear in multiple types. For example,
2249 .pod files are both Perl and Parrot.
2253 my @types = filetypes_supported
();
2256 $maxlen = length if $maxlen < length;
2258 for my $type ( sort @types ) {
2259 next if $type =~ /^-/; # Stuff to not show
2260 my $ext_list = $mappings{$type};
2262 if ( ref $ext_list ) {
2263 $ext_list = join( ' ', map { $_->to_string } @{$ext_list} );
2265 App
::Ack
::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2274 Pod
::Usage
::pod2usage
({
2275 -input
=> $App::Ack
::orig_program_name
,
2284 sub get_version_statement
{
2287 my $copyright = get_copyright
();
2288 my $this_perl = $Config::Config
{perlpath
};
2290 my $ext = $Config::Config
{_exe
};
2291 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2293 my $ver = sprintf( '%vd', $^V );
2295 my $git_revision = $GIT_REVISION ? " (git commit $GIT_REVISION)" : '';
2297 return <<"END_OF_VERSION";
2298 ack ${VERSION}${git_revision}
2299 Running under Perl $ver at $this_perl
2303 This program is free software. You may modify or distribute it
2304 under the terms of the Artistic License v2.0.
2309 sub print_version_statement
{
2310 App
::Ack
::print( get_version_statement
() );
2322 eval 'use Term::ANSIColor 1.12 ()';
2324 $ENV{ACK_COLOR_MATCH
} ||= 'black on_yellow';
2325 $ENV{ACK_COLOR_FILENAME
} ||= 'bold green';
2326 $ENV{ACK_COLOR_LINENO
} ||= 'bold yellow';
2332 # print subs added in order to make it easy for a third party
2333 # module (such as App::Wack) to redefine the display methods
2334 # and show the results in a different way.
2335 sub print { print {$fh} @_; return; }
2336 sub print_first_filename
{ App
::Ack
::print( $_[0], "\n" ); return; }
2337 sub print_blank_line
{ App
::Ack
::print( "\n" ); return; }
2338 sub print_separator
{ App
::Ack
::print( "--\n" ); return; }
2339 sub print_filename
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2340 sub print_line_no
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2341 sub print_column_no
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2343 my $filename = shift;
2344 my $nmatches = shift;
2347 my $show_filename = shift;
2349 if ($show_filename) {
2350 App
::Ack
::print( $filename );
2351 App
::Ack
::print( ':', $nmatches ) if $count;
2354 App
::Ack
::print( $nmatches ) if $count;
2356 App
::Ack
::print( $ors );
2362 my $filename = shift;
2364 my $show_filename = shift;
2366 if ($show_filename) {
2367 App
::Ack
::print( $filename, ':0', $ors );
2370 App
::Ack
::print( '0', $ors );
2377 my $command = shift;
2379 return if App
::Ack
::output_to_pipe
();
2382 if ( not open( $pager, '|-', $command ) ) {
2383 App
::Ack
::die( qq{Unable to pipe to pager "$command": $!} );
2391 sub output_to_pipe
{
2392 return $output_to_pipe;
2397 my $nmatches = shift;
2399 my $rc = $nmatches ? 0 : 1;
2405 my @capture_indices;
2406 my $match_column_number;
2409 my ( $opt, $line ) = @_;
2411 my $re = $opt->{regex
};
2412 my $invert = $opt->{v
};
2416 $match_column_number = undef;
2417 @capture_indices = ();
2419 if ( $invert ? $line !~ /$re/ : $line =~ /$re/ ) {
2420 if ( not $invert ) {
2421 # @- = @LAST_MATCH_START
2422 # @+ = @LAST_MATCH_END
2423 $match_column_number = $-[0] + 1;
2426 @capture_indices = map {
2438 sub get_capture_indices
{
2439 return @capture_indices;
2442 sub get_match_column
{
2443 return $match_column_number;
2448 sub print_matches_in_resource
{
2449 my ( $resource, $opt ) = @_;
2451 my $passthru = $opt->{passthru
};
2452 my $max_count = $opt->{m
} || -1;
2454 my $filename = $resource->name;
2455 my $break = $opt->{break};
2456 my $heading = $opt->{heading
};
2457 my $ors = $opt->{print0
} ? "\0" : "\n";
2458 my $color = $opt->{color
};
2459 my $print_filename = $opt->{show_filename
};
2461 my $has_printed_for_this_resource = 0;
2463 App
::Ack
::iterate
($resource, $opt, sub {
2464 if ( App
::Ack
::does_match
($opt, $_) ) {
2465 if( !$has_printed_for_this_resource ) {
2466 if( $break && has_printed_something
() ) {
2467 App
::Ack
::print_blank_line
();
2469 if( $print_filename) {
2471 my $filename = $resource->name;
2473 $filename = Term
::ANSIColor
::colored
($filename,
2474 $ENV{ACK_COLOR_FILENAME
});
2476 App
::Ack
::print_filename
( $filename, $ors );
2480 App
::Ack
::print_line_with_context
($opt, $filename, $_, $.);
2481 $has_printed_for_this_resource = 1;
2485 elsif ( $passthru ) {
2487 if( $break && !$has_printed_for_this_resource && has_printed_something
() ) {
2488 App
::Ack
::print_blank_line
();
2490 App
::Ack
::print_line_with_options
($opt, $filename, $_, $., ':');
2491 $has_printed_for_this_resource = 1;
2493 return $max_count != 0;
2499 sub count_matches_in_resource
{
2500 my ( $resource, $opt ) = @_;
2504 App
::Ack
::iterate
( $resource, $opt, sub {
2505 ++$nmatches if App
::Ack
::does_match
($opt, $_);
2512 sub resource_has_match
{
2513 my ( $resource, $opt ) = @_;
2515 return count_matches_in_resource
($resource, $opt) > 0;
2520 my @before_ctx_lines;
2521 my @after_ctx_lines;
2525 if ( not $is_iterating ) {
2526 Carp
::croak
( 'get_context() called outside of iterate()' );
2530 scalar(@before_ctx_lines) ? \
@before_ctx_lines : undef,
2531 scalar(@after_ctx_lines) ? \
@after_ctx_lines : undef,
2536 my ( $resource, $opt, $cb ) = @_;
2540 local $opt->{before_context
} = $opt->{output
} ? 0 : $opt->{before_context
};
2541 local $opt->{after_context
} = $opt->{output
} ? 0 : $opt->{after_context
};
2543 my $n_before_ctx_lines = $opt->{before_context
} || 0;
2544 my $n_after_ctx_lines = $opt->{after_context
} || 0;
2547 @after_ctx_lines = @before_ctx_lines = ();
2549 if ( $resource->next_text() ) {
2550 $current_line = $_; # prime the first line of input
2553 while ( defined $current_line ) {
2554 while ( (@after_ctx_lines < $n_after_ctx_lines) && $resource->next_text() ) {
2555 push @after_ctx_lines, $_;
2558 local $_ = $current_line;
2559 my $former_dot_period = $.;
2560 $. = $. - @after_ctx_lines;
2562 last unless $cb->();
2564 # I tried doing this with local(), but for some reason,
2565 # $. continued to have its new value after the exit of the
2566 # enclosing block. I'm guessing that $. has some extra
2567 # magic associated with it or something. If someone can
2568 # tell me why this happened, I would love to know!
2569 $. = $former_dot_period; # XXX this won't happen on an exception
2571 push @before_ctx_lines, $current_line;
2572 if($n_after_ctx_lines) {
2573 $current_line = shift @after_ctx_lines;
2575 elsif($resource->next_text()) {
2579 undef $current_line;
2581 shift @before_ctx_lines while @before_ctx_lines > $n_before_ctx_lines;
2584 $is_iterating = 0; # XXX this won't happen on an exception
2585 # then again, do we care? ack doesn't really
2586 # handle exceptions anyway.
2593 my $has_printed_something;
2596 $has_printed_something = 0;
2599 sub has_printed_something
{
2600 return $has_printed_something;
2603 sub print_line_with_options
{
2604 my ( $opt, $filename, $line, $line_no, $separator ) = @_;
2606 $has_printed_something = 1;
2608 my $print_filename = $opt->{show_filename
};
2609 my $print_column = $opt->{column
};
2610 my $ors = $opt->{print0
} ? "\0" : "\n";
2611 my $heading = $opt->{heading
};
2612 my $output_expr = $opt->{output
};
2613 my $re = $opt->{regex
};
2614 my $color = $opt->{color
};
2619 $filename = Term
::ANSIColor
::colored
($filename,
2620 $ENV{ACK_COLOR_FILENAME
});
2621 $line_no = Term
::ANSIColor
::colored
($line_no,
2622 $ENV{ACK_COLOR_LINENO
});
2625 if($print_filename) {
2627 push @line_parts, $line_no;
2630 push @line_parts, $filename, $line_no;
2633 if( $print_column ) {
2634 push @line_parts, get_match_column
();
2637 if( $output_expr ) {
2638 # XXX avoid re-evaluation if we can
2639 while( $line =~ /$re/g ) {
2640 my $output = eval $output_expr;
2641 App
::Ack
::print( join( $separator, @line_parts, $output ), $ors );
2645 my @capture_indices = get_capture_indices
();
2646 if( @capture_indices ) {
2647 my $offset = 0; # additional offset for when we add stuff
2649 foreach my $index_pair ( @capture_indices ) {
2650 my ( $match_start, $match_end ) = @{$index_pair};
2652 my $substring = substr( $line,
2653 $offset + $match_start, $match_end - $match_start );
2654 my $substitution = Term
::ANSIColor
::colored
( $substring,
2655 $ENV{ACK_COLOR_MATCH
} );
2657 substr( $line, $offset + $match_start,
2658 $match_end - $match_start, $substitution );
2660 $offset += length( $substitution ) - length( $substring );
2664 # XXX I know $& is a no-no; fix it later
2665 if($line =~ s/$re/Term::ANSIColor::colored($&, $ENV{ACK_COLOR_MATCH})/ge) {
2666 $line .= "\033[0m\033[K";
2670 push @line_parts, $line;
2671 App
::Ack
::print( join( $separator, @line_parts ), $ors );
2680 my $previous_file_processed;
2681 my $previous_line_printed;
2684 $is_first_match = 1;
2685 $previous_line_printed = -1;
2688 sub print_line_with_context
{
2689 my ( $opt, $filename, $matching_line, $line_no ) = @_;
2691 my $heading = $opt->{heading
};
2693 if( !defined($previous_file_processed) ||
2694 $previous_file_processed ne $filename ) {
2695 $previous_file_processed = $filename;
2696 $previous_line_printed = -1;
2699 $is_first_match = 1;
2703 my $ors = $opt->{print0
} ? "\0" : "\n";
2704 my $match_word = $opt->{w
};
2705 my $re = $opt->{regex
};
2706 my $is_tracking_context = $opt->{after_context
} || $opt->{before_context
};
2707 my $output_expr = $opt->{output
};
2709 chomp $matching_line;
2711 my ( $before_context, $after_context ) = get_context
();
2713 if ( $before_context ) {
2714 my $first_line = $. - @{$before_context};
2716 if ( $first_line <= $previous_line_printed ) {
2717 splice @{$before_context}, 0, $previous_line_printed - $first_line + 1;
2718 $first_line = $. - @{$before_context};
2720 if ( @{$before_context} ) {
2721 my $offset = @{$before_context};
2723 if( !$is_first_match && $previous_line_printed != $first_line - 1 ) {
2724 App
::Ack
::print('--', $ors);
2726 foreach my $line (@{$before_context}) {
2727 my $context_line_no = $. - $offset;
2728 if ( $context_line_no <= $previous_line_printed ) {
2733 App
::Ack
::print_line_with_options
($opt, $filename, $line, $context_line_no, '-');
2734 $previous_line_printed = $context_line_no;
2740 if ( $. > $previous_line_printed ) {
2741 if( $is_tracking_context && !$is_first_match && $previous_line_printed != $. - 1 ) {
2742 App
::Ack
::print('--', $ors);
2745 App
::Ack
::print_line_with_options
($opt, $filename, $matching_line, $line_no, ':');
2746 $previous_line_printed = $.;
2749 if($after_context) {
2751 foreach my $line (@{$after_context}) {
2753 if ( $previous_line_printed >= $. + $offset ) {
2758 my $separator = App
::Ack
::does_match
( $opt, $line ) ? ':' : '-';
2759 App
::Ack
::print_line_with_options
($opt, $filename, $line, $. + $offset, $separator);
2760 $previous_line_printed = $. + $offset;
2765 $is_first_match = 0;
2772 # inefficient, but functional
2774 my ( $resource ) = @_;
2778 foreach my $k (keys %mappings) {
2779 my $filters = $mappings{$k};
2781 foreach my $filter (@{$filters}) {
2782 # clone the resource
2783 my $clone = $resource->clone;
2784 if ( $filter->filter($clone) ) {
2791 return sort @matches;
2794 # returns a (fairly) unique identifier for a file
2795 # use this function to compare two files to see if they're
2796 # equal (ie. the same file, but with a different path/links/etc)
2798 my ( $filename ) = @_;
2800 if ( $is_windows ) {
2801 return File
::Next
::reslash
( $filename );
2804 # XXX is this the best method? it always hits the FS
2805 if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
2806 return join(':', $dev, $inode);
2809 # XXX this could be better
2816 my @lines = App
::Ack
::ConfigDefault
::options
();
2818 print join("\n", '--ignore-ack-defaults', @lines);
2823 1; # End of App::Ack
2824 package App
::Ack
::Resource
;
2834 Carp
::confess
( 'Must be overloaded' );
2854 sub needs_line_scan
{
2879 package App
::Ack
::Resources
;
2892 my $self = bless {}, $class;
2894 my $file_filter = undef;
2895 my $descend_filter = $opt->{descend_filter
};
2898 $descend_filter = sub {
2904 File
::Next
::files
( {
2905 file_filter
=> $opt->{file_filter
},
2906 descend_filter
=> $descend_filter,
2907 error_handler
=> sub { my $msg = shift; App
::Ack
::warn( $msg ) },
2908 sort_files
=> $opt->{sort_files
},
2909 follow_symlinks
=> $opt->{follow
},
2922 File
::Next
::from_file
( {
2923 error_handler
=> sub { my $msg = shift; App
::Ack
::warn( $msg ) },
2924 warning_handler
=> sub { my $msg = shift; App
::Ack
::warn( $msg ) },
2925 sort_files
=> $opt->{sort_files
},
2926 }, $file ) or return undef;
2933 # This is for reading input lines from STDIN, not the list of files from STDIN
2938 my $self = bless {}, $class;
2940 my $has_been_called = 0;
2942 $self->{iter
} = sub {
2943 if ( !$has_been_called ) {
2944 $has_been_called = 1;
2956 my $file = $self->{iter
}->() or return;
2958 return App
::Ack
::Resource
::Basic-
>new( $file );
2962 package App
::Ack
::Resource
::Basic
;
2969 our @ISA = 'App::Ack::Resource';
2975 my $filename = shift;
2978 filename
=> $filename,
2983 if ( $self->{filename
} eq '-' ) {
2984 $self->{fh
} = *STDIN
;
2987 if ( !open( $self->{fh
}, '<', $self->{filename
} ) && $App::Ack
::report_bad_filenames
) {
2988 App
::Ack
::warn( "$self->{filename}: $!" );
3000 return $self->{filename
};
3005 sub needs_line_scan
{
3009 return 1 if $opt->{v
};
3011 my $size = -s
$self->{fh
};
3015 elsif ( $size > 100_000 ) {
3020 my $rc = sysread( $self->{fh
}, $buffer, $size );
3021 if ( !defined($rc) && $App::Ack
::report_bad_filenames
) {
3022 App
::Ack
::warn( "$self->{filename}: $!" );
3025 return 0 unless $rc && ( $rc == $size );
3027 my $regex = $opt->{regex
};
3028 return $buffer =~ /$regex/m;
3035 if( !seek( $self->{fh
}, 0, 0 ) && $App::Ack
::report_bad_filenames
) {
3036 App
::Ack
::warn( "$self->{filename}: $!" );
3044 if ( defined ($_ = readline $_[0]->{fh
}) ) {
3045 $. = ++$_[0]->{line
};
3046 s/[\r\n]+$//; # chomp may not handle this
3047 $_ .= "\n"; # add back newline (XXX make it native)
3058 if ( !close($self->{fh
}) && $App::Ack
::report_bad_filenames
) {
3059 App
::Ack
::warn( $self->name() . ": $!" );
3069 return __PACKAGE__-
>new($self->name);
3074 package App
::Ack
::Filter
;
3079 '""' => 'to_string';
3087 my ( undef, $type, @args ) = @_;
3089 if ( my $package = $filter_types{$type} ) {
3090 return $package->new(@args);
3092 Carp
::croak
"Unknown filter type '$type'";
3096 sub register_filter
{
3097 my ( undef, $type, $package ) = @_;
3099 $filter_types{$type} = $package;
3108 return App
::Ack
::Filter
::Inverse-
>new( $self );
3120 return '(unimplemented to_string)';
3131 package App
::Ack
::Filter
::Extension
;
3136 our @ISA = 'App::Ack::Filter';
3140 my ( $class, @extensions ) = @_;
3142 my $exts = join('|', map { "\Q$_\E"} @extensions);
3143 my $re = qr/[.](?:$exts)$/i;
3146 extensions
=> \
@extensions,
3152 my ( $self, $resource ) = @_;
3154 my $re = $self->{'regex'};
3156 return $resource->name =~ /$re/;
3162 my $re = $self->{'regex'};
3164 return ref($self) . " - $re";
3170 my $exts = $self->{'extensions'};
3172 return join(' ', map { ".$_" } @{$exts});
3176 App
::Ack
::Filter-
>register_filter(ext
=> __PACKAGE__
);
3180 package App
::Ack
::Filter
::FirstLineMatch
;
3185 our @ISA = 'App::Ack::Filter';
3189 my ( $class, $re ) = @_;
3191 $re =~ s{^/|/$}{}g; # XXX validate?
3199 # XXX This test checks the first "line" of the file, but we need
3200 # it to be less piggy. If it's something like a .min.js file, then
3201 # the "line" could be the entire file. Instead, it should read the
3202 # first, say, 100 characters of the first line.
3205 my ( $self, $resource ) = @_;
3207 my $re = $self->{'regex'};
3210 return unless $resource->next_text;
3218 my $re = $self->{'regex'};
3220 return ref($self) . " - $re";
3226 my $re = $self->{'regex'};
3228 return "first line matches $re";
3232 App
::Ack
::Filter-
>register_filter(firstlinematch
=> __PACKAGE__
);
3236 package App
::Ack
::Filter
::Is
;
3241 our @ISA = 'App::Ack::Filter';
3244 use File
::Spec
3.00 ();
3247 my ( $class, $filename ) = @_;
3250 filename
=> $filename,
3255 my ( $self, $resource ) = @_;
3257 my $filename = $self->{'filename'};
3258 my $base = (File
::Spec-
>splitpath($resource->name))[2];
3260 return $base eq $filename;
3266 my $filename = $self->{'filename'};
3268 return ref($self) . " - $filename";
3274 my $filename = $self->{'filename'};
3278 App
::Ack
::Filter-
>register_filter(is => __PACKAGE__
);
3282 package App
::Ack
::Filter
::Match
;
3287 our @ISA = 'App::Ack::Filter';
3290 use File
::Spec
3.00;
3293 my ( $class, $re ) = @_;
3295 $re =~ s{^/|/$}{}g; # XXX validate?
3304 my ( $self, $resource ) = @_;
3306 my $re = $self->{'regex'};
3307 my $base = (File
::Spec-
>splitpath($resource->name))[2];
3309 return $base =~ /$re/;
3315 my $re = $self->{'regex'};
3317 print ref($self) . " - $re";
3323 my $re = $self->{'regex'};
3325 return "filename matches $re";
3329 App
::Ack
::Filter-
>register_filter(match
=> __PACKAGE__
);
3333 package App
::Ack
::Filter
::Default
;
3338 our @ISA = 'App::Ack::Filter';
3344 return bless {}, $class;
3348 my ( $self, $resource ) = @_;
3350 return -T
$resource->name;
3354 package App
::Ack
::Filter
::Inverse
;
3359 our @ISA = 'App::Ack::Filter';
3363 my ( $class, $filter ) = @_;
3371 my ( $self, $resource ) = @_;
3373 my $filter = $self->{'filter'};
3374 return !$filter->filter( $resource );
3380 return $self->{'filter'};
3390 my $filter = $self->{'filter'};
3396 package App
::Ack
::ConfigFinder
;
3403 use File
::Spec
3.00;
3406 if ($App::Ack
::is_windows
) {
3415 return bless {}, $class;
3418 sub _remove_redundancies
{
3419 my ( @configs ) = @_;
3421 my %dev_and_inode_seen;
3423 foreach my $path ( @configs ) {
3424 my ( $dev, $inode ) = (stat $path)[0, 1];
3426 if( defined($dev) ) {
3427 if( $dev_and_inode_seen{"$dev:$inode"} ) {
3431 $dev_and_inode_seen{"$dev:$inode"} = 1;
3435 return grep { defined() } @configs;
3438 sub _check_for_ackrc
{
3439 return unless defined $_[0];
3441 my @files = grep { -f
}
3442 map { File
::Spec-
>catfile(@_, $_) }
3445 die File
::Spec-
>catdir(@_) . " contains both .ackrc and _ackrc.\n" .
3446 "Please remove one of those files.\n"
3449 return wantarray ? @files : $files[0];
3450 } # end _check_for_ackrc
3453 sub find_config_files
{
3456 if($App::Ack
::is_windows
) {
3457 push @config_files, map { File
::Spec-
>catfile($_, 'ackrc') } (
3458 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3459 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3463 push @config_files, '/etc/ackrc';
3466 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3467 push @config_files, $ENV{'ACKRC'};
3470 push @config_files, _check_for_ackrc
($ENV{'HOME'});
3473 my @dirs = File
::Spec-
>splitdir(Cwd
::getcwd
());
3475 my $ackrc = _check_for_ackrc
(@dirs);
3476 if(defined $ackrc) {
3477 push @config_files, $ackrc;
3483 # XXX we only test for existence here, so if the file is
3484 # deleted out from under us, this will fail later. =(
3485 return _remove_redundancies
( @config_files );
3489 package App
::Ack
::ConfigLoader
;
3495 use Getopt
::Long
2.36 ();
3496 use Text
::ParseWords
3.1 ();
3499 my @INVALID_COMBINATIONS;
3502 my @context = qw( -A -B -C --after-context --before-context --context );
3503 my @pretty = qw( --heading --group --break );
3504 my @filename = qw( -h -H --with-filename --no-filename );
3506 @INVALID_COMBINATIONS = (
3508 [qw(-l)] => [@context, @pretty, @filename, qw(-L -o --passthru --output --max-count --column -f -g --show-types)],
3509 [qw(-L)] => [@context, @pretty, @filename, qw(-l -o --passthru --output --max-count --column -f -g --show-types -c --count)],
3510 [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)],
3511 [qw(-o)] => [@context, qw(--output -c --count --column --column -f --show-types)],
3512 [qw(--passthru)] => [@context, qw(--output --column -m --max-count -1 -c --count -f -g)],
3513 [qw(--output)] => [@context, qw(-c --count -f -g)],
3514 [qw(--match)] => [qw(-f -g)],
3515 [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
3516 [qw(-h --no-filename)] => [qw(-H --with-filename -f -g --group --heading)],
3517 [qw(-H --with-filename)] => [qw(-h --no-filename -f -g)],
3518 [qw(-c --count)] => [@context, @pretty, qw(--column -f -g)],
3519 [qw(--column)] => [qw(-f -g)],
3520 [@context] => [qw(-f -g)],
3521 [qw(-f)] => [qw(-g), @pretty],
3522 [qw(-g)] => [qw(-f), @pretty],
3526 sub process_filter_spec
{
3529 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3530 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3532 return ( $type_name,
3533 App
::Ack
::Filter-
>create_filter($ext_type, split(/,/, $arguments)) );
3535 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3536 my ( $type_name, $extensions ) = ( $1, $2 );
3538 my @extensions = split(/,/, $extensions);
3539 foreach my $extension ( @extensions ) {
3540 $extension =~ s/^[.]//;
3543 return ( $type_name, App
::Ack
::Filter-
>create_filter('ext', @extensions) );
3546 Carp
::croak
"invalid filter specification '$spec'";
3550 sub process_filetypes
{
3551 my ( $opt, $arg_sources ) = @_;
3553 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3554 Getopt
::Long
::Configure
(
3559 my %additional_specs;
3561 my $add_spec = sub {
3562 my ( undef, $spec ) = @_;
3564 my ( $name, $filter ) = process_filter_spec
($spec);
3566 push @{ $App::Ack
::mappings
{$name} }, $filter;
3568 $additional_specs{$name . '!'} = sub {
3569 my ( undef, $value ) = @_;
3571 my @filters = @{ $App::Ack
::mappings
{$name} };
3573 @filters = map { $_->invert() } @filters;
3576 push @{ $opt->{'filters'} }, @filters;
3580 my $set_spec = sub {
3581 my ( undef, $spec ) = @_;
3583 my ( $name, $filter ) = process_filter_spec
($spec);
3585 $App::Ack
::mappings
{$name} = [ $filter ];
3587 $additional_specs{$name . '!'} = sub {
3588 my ( undef, $value ) = @_;
3590 my @filters = @{ $App::Ack
::mappings
{$name} };
3592 @filters = map { $_->invert() } @filters;
3595 push @{ $opt->{'filters'} }, @filters;
3599 my $delete_spec = sub {
3600 my ( undef, $name ) = @_;
3602 delete $App::Ack
::mappings
{$name};
3603 delete $additional_specs{$name . '!'};
3606 my %type_arg_specs = (
3607 'type-add=s' => $add_spec,
3608 'type-set=s' => $set_spec,
3609 'type-del=s' => $delete_spec,
3612 for ( my $i = 0; $i < @{$arg_sources}; $i += 2) {
3613 my ( $source_name, $args ) = @{$arg_sources}[ $i, $i + 1];
3616 # $args are modified in place, so no need to munge $arg_sources
3617 Getopt
::Long
::GetOptionsFromArray
($args, %type_arg_specs);
3620 ( undef, $arg_sources->[$i + 1] ) =
3621 Getopt
::Long
::GetOptionsFromString
($args, %type_arg_specs);
3625 $additional_specs{'k|known-types'} = sub {
3626 my ( undef, $value ) = @_;
3628 my @filters = map { @{$_} } values(%App::Ack
::mappings
);
3630 push @{ $opt->{'filters'} }, @filters;
3633 return \
%additional_specs;
3636 sub removed_option
{
3637 my ( $option, $explanation ) = @_;
3639 $explanation ||= '';
3641 warn "Option '$option' is not valid in ack 2\n$explanation";
3647 my ( $opt, $extra_specs ) = @_;
3649 my $dash_a_explanation = <<EOT;
3650 This is because we now have -k/--known-types which makes it only select files
3651 of known types, rather than any text file (which is the behavior of ack 1.x).
3655 1 => sub { $opt->{1} = $opt->{m
} = 1 },
3656 'A|after-context=i' => \
$opt->{after_context
},
3657 'B|before-context=i'
3658 => \
$opt->{before_context
},
3659 'C|context:i' => sub { shift; my $val = shift; $opt->{before_context
} = $opt->{after_context
} = ($val || 2) },
3660 'a' => removed_option
('-a', $dash_a_explanation),
3661 'all' => removed_option
('--all', $dash_a_explanation),
3662 'break!' => \
$opt->{break},
3663 c
=> \
$opt->{count
},
3664 'color|colour!' => \
$opt->{color
},
3665 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
3666 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
3667 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
3668 'column!' => \
$opt->{column
},
3669 count
=> \
$opt->{count
},
3670 'create-ackrc' => sub { App
::Ack
::create_ackrc
(); exit; },
3672 my ( undef, $value ) = @_;
3675 $opt->{noenv_seen
} = 1;
3679 'files-from=s' => \
$opt->{files_from
},
3680 'filter!' => \
$App::Ack
::is_filter_mode
,
3681 flush
=> \
$opt->{flush
},
3682 'follow!' => \
$opt->{follow
},
3684 G
=> removed_option
('-G'),
3685 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
3686 'heading!' => \
$opt->{heading
},
3687 'h|no-filename' => \
$opt->{h
},
3688 'H|with-filename' => \
$opt->{H
},
3689 'i|ignore-case' => \
$opt->{i
},
3690 'ignore-directory|ignore-dir=s' # XXX Combine this version with the negated version below
3692 my ( undef, $dir ) = @_;
3694 $dir = App
::Ack
::remove_dir_sep
( $dir );
3695 if ( $dir !~ /^(?:is|match):/ ) {
3696 $dir = 'is:' . $dir;
3698 push @{ $opt->{idirs
} }, $dir;
3700 'ignore-file=s' => sub {
3701 my ( undef, $file ) = @_;
3702 push @{ $opt->{ifiles
} }, $file;
3704 'lines=s' => sub { shift; my $val = shift; push @{$opt->{lines
}}, $val },
3705 'l|files-with-matches'
3707 'L|files-without-matches'
3709 'm|max-count=i' => \
$opt->{m
},
3710 'match=s' => \
$opt->{regex
},
3711 'n|no-recurse' => \
$opt->{n
},
3712 o
=> sub { $opt->{output
} = '$&' },
3713 'output=s' => \
$opt->{output
},
3714 'pager=s' => \
$opt->{pager
},
3715 'noignore-directory|noignore-dir=s'
3717 my ( undef, $dir ) = @_;
3719 # XXX can you do --noignore-dir=match,...?
3720 $dir = App
::Ack
::remove_dir_sep
( $dir );
3721 if ( $dir !~ /^(?:is|match):/ ) {
3722 $dir = 'is:' . $dir;
3724 if ( $dir !~ /^(?:is|match):/ ) {
3725 Carp
::croak
("invalid noignore-directory argument: '$dir'");
3728 @{ $opt->{idirs
} } = grep {
3730 } @{ $opt->{idirs
} };
3732 'nopager' => sub { $opt->{pager
} = undef },
3733 'passthru' => \
$opt->{passthru
},
3734 'print0' => \
$opt->{print0
},
3735 'Q|literal' => \
$opt->{Q
},
3736 'r|R|recurse' => sub { $opt->{n
} = 0 },
3737 's' => \
$opt->{dont_report_bad_filenames
},
3738 'show-types' => \
$opt->{show_types
},
3739 'smart-case!' => \
$opt->{smart_case
},
3740 'sort-files' => \
$opt->{sort_files
},
3742 my ( $getopt, $value ) = @_;
3745 if ( $value =~ s/^no// ) {
3749 my $callback = $extra_specs->{ $value . '!' };
3752 $callback->( $getopt, $cb_value );
3755 Carp
::croak
( "Unknown type '$value'" );
3758 'u' => removed_option
('-u'),
3759 'unrestricted' => removed_option
('--unrestricted'),
3760 'v|invert-match' => \
$opt->{v
},
3761 'w|word-regexp' => \
$opt->{w
},
3762 'x' => sub { $opt->{files_from
} = '-' },
3764 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
3765 'help|?:s' => sub { shift; App
::Ack
::show_help
(@_); exit; },
3766 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
3767 'man' => sub { App
::Ack
::show_man
(); exit; },
3768 $extra_specs ? %{$extra_specs} : (),
3773 my ( $opt, $extra_specs, $arg_sources ) = @_;
3775 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3776 Getopt
::Long
::Configure
(
3782 my $is_help_types_active;
3784 for ( my $i = 0; $i < @{$arg_sources}; $i += 2 ) {
3785 my ( $source_name, $args ) = @{$arg_sources}[ $i, $i + 1 ];
3787 if ( $source_name eq 'ARGV' ) {
3788 $argv_source = $args;
3793 if ( $argv_source ) { # this *should* always be true, but you never know...
3794 my @copy = @{$argv_source};
3796 Getopt
::Long
::Configure
('pass_through');
3798 Getopt
::Long
::GetOptionsFromArray
( \
@copy,
3799 'help-types' => \
$is_help_types_active,
3802 Getopt
::Long
::Configure
('no_pass_through');
3805 my $arg_specs = get_arg_spec
($opt, $extra_specs);
3807 for ( my $i = 0; $i < @{$arg_sources}; $i += 2) {
3808 my ($source_name, $args) = @{$arg_sources}[$i, $i + 1];
3812 $ret = Getopt
::Long
::GetOptionsFromArray
( $args, %{$arg_specs} );
3815 ( $ret, $arg_sources->[$i + 1] ) =
3816 Getopt
::Long
::GetOptionsFromString
( $args, %{$arg_specs} );
3819 if ( !$is_help_types_active ) {
3820 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
3821 App
::Ack
::die( "Invalid option $where" );
3824 if ( $opt->{noenv_seen
} ) {
3825 App
::Ack
::die( "--noenv found in $source_name" );
3829 # XXX We need to check on a -- in the middle of a non-ARGV source
3834 sub should_dump_options
{
3835 my ( $sources ) = @_;
3837 for(my $i = 0; $i < @{$sources}; $i += 2) {
3838 my ( $name, $options ) = @{$sources}[$i, $i + 1];
3839 if($name eq 'ARGV') {
3841 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
3842 Getopt
::Long
::GetOptionsFromArray
($options,
3851 sub explode_sources
{
3852 my ( $sources ) = @_;
3856 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
3859 my $arg_spec = get_arg_spec
(\
%opt);
3861 my $add_type = sub {
3862 my ( undef, $arg ) = @_;
3865 if ( $arg =~ /(\w+)=/) {
3866 $arg_spec->{$1} = sub {};
3869 ( $arg ) = split /:/, $arg;
3870 $arg_spec->{$arg} = sub {};
3874 my $del_type = sub {
3875 my ( undef, $arg ) = @_;
3877 delete $arg_spec->{$arg};
3880 for(my $i = 0; $i < @{$sources}; $i += 2) {
3881 my ( $name, $options ) = @{$sources}[$i, $i + 1];
3882 if ( ref($options) ne 'ARRAY' ) {
3883 $sources->[$i + 1] = $options =
3884 [ Text
::ParseWords
::shellwords
($options) ];
3886 for ( my $j = 0; $j < @{$options}; $j++ ) {
3887 next unless $options->[$j] =~ /^-/;
3888 my @chunk = ( $options->[$j] );
3889 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
3893 Getopt
::Long
::GetOptionsFromArray
(\
@chunk,
3894 'type-add=s' => $add_type,
3895 'type-set=s' => $add_type,
3896 'type-del=s' => $del_type,
3898 Getopt
::Long
::GetOptionsFromArray
(\
@chunk, %{$arg_spec});
3900 splice @copy, -1 * @chunk if @chunk; # XXX explain this
3901 push @new_sources, $name, \
@copy;
3905 return \
@new_sources;
3911 my $first_a = $a->[0];
3912 my $first_b = $b->[0];
3914 $first_a =~ s/^--?//;
3915 $first_b =~ s/^--?//;
3917 return $first_a cmp $first_b;
3921 my ( $sources ) = @_;
3923 $sources = explode_sources
($sources);
3928 for(my $i = 0; $i < @{$sources}; $i += 2) {
3929 my ( $name, $contents ) = @{$sources}[$i, $i + 1];
3930 if ( not $opts_by_source{$name} ) {
3931 $opts_by_source{$name} = [];
3932 push @source_names, $name;
3934 push @{$opts_by_source{$name}}, $contents;
3937 foreach my $name (@source_names) {
3938 my $contents = $opts_by_source{$name};
3941 print '=' x
length($name), "\n";
3942 print ' ', join(' ', @{$_}), "\n" foreach sort { compare_opts
($a, $b) } @{$contents};
3948 sub remove_default_options_if_needed
{
3949 my ( $sources ) = @_;
3953 foreach my $index ( 0 .. $#$sources ) {
3954 if ( $sources->[$index] eq 'Defaults' ) {
3955 $default_index = $index;
3960 return $sources unless defined $default_index;
3962 my $should_remove = 0;
3964 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3965 Getopt
::Long
::Configure
(
3971 foreach my $index ( $default_index + 2 .. $#$sources ) {
3972 next if $index % 2 != 0;
3974 my ( $name, $args ) = @{$sources}[ $index, $index + 1 ];
3977 Getopt
::Long
::GetOptionsFromArray
($args,
3978 'ignore-ack-defaults' => \
$should_remove,
3982 ( undef, $sources->[$index + 1] ) = Getopt
::Long
::GetOptionsFromString
($args,
3983 'ignore-ack-defaults' => \
$should_remove,
3988 Getopt
::Long
::Configure
('default');
3989 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
3991 return $sources unless $should_remove;
3993 my @copy = @{$sources};
3994 splice @copy, $default_index, 2;
3998 sub check_for_mutually_exclusive_options
{
3999 my ( $arg_sources ) = @_;
4001 my %mutually_exclusive_with;
4002 my @copy = @{$arg_sources};
4004 for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
4005 my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
4007 foreach my $l_opt ( @{$lhs} ) {
4008 foreach my $r_opt ( @{$rhs} ) {
4009 push @{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
4010 push @{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
4018 my ( $source_name, $args ) = splice @copy, 0, 2;
4019 $args = ref($args) ? [ @{$args} ] : [ Text
::ParseWords
::shellwords
($args) ];
4021 foreach my $opt ( @{$args} ) {
4022 next unless $opt =~ /^[-+]/;
4023 last if $opt eq '--';
4025 if( $opt =~ /^(.*)=/ ) {
4028 elsif ( $opt =~ /^(-[^-]).+/ ) {
4032 $set_opts{ $opt } = 1;
4034 my $mutex_opts = $mutually_exclusive_with{ $opt };
4036 next unless $mutex_opts;
4038 foreach my $mutex_opt ( @{$mutex_opts} ) {
4039 if($set_opts{ $mutex_opt }) {
4040 die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
4048 my $arg_sources = \
@_;
4052 check_for_mutually_exclusive_options
($arg_sources);
4054 $arg_sources = remove_default_options_if_needed
($arg_sources);
4056 if ( should_dump_options
($arg_sources) ) {
4057 dump_options
($arg_sources);
4061 my $type_specs = process_filetypes
(\
%opt, $arg_sources);
4062 process_other
(\
%opt, $type_specs, $arg_sources);
4063 while ( @{$arg_sources} ) {
4064 my ( $source_name, $args ) = splice( @{$arg_sources}, 0, 2 );
4066 # All of our sources should be transformed into an array ref
4068 if ( $source_name eq 'ARGV' ) {
4072 Carp
::croak
"source '$source_name' has extra arguments!";
4076 Carp
::croak
'The impossible has occurred!';
4079 my $filters = ($opt{filters
} ||= []);
4081 # throw the default filter in if no others are selected
4082 if ( not grep { !$_->is_inverted() } @{$filters} ) {
4083 push @{$filters}, App
::Ack
::Filter
::Default-
>new();
4088 1; # End of App::Ack::ConfigLoader
4089 package App
::Ack
::ConfigDefault
;
4095 my @options = split( /\n/, _options_block
() );
4096 @options = grep { /./ && !/^#/ } @options;
4101 sub _options_block
{
4103 # This is the default ackrc for ack 2.0
4105 # There are four different ways to match
4106 # is: Match the filename exactly
4107 # ext: Match the extension of the filename exactly
4108 # match: Match the filename against a Perl regular expression
4109 # firstlinematch: Match the first 80 characters of the first line
4110 # of text against a Perl regular expression. This is only for
4111 # the --type-add option.
4114 # Directories to ignore
4116 --ignore-directory=is:.bzr
4119 --ignore-directory=is:.cdv
4122 --ignore-directory=is:~.dep
4123 --ignore-directory=is:~.dot
4124 --ignore-directory=is:~.nib
4125 --ignore-directory=is:~.plst
4128 --ignore-directory=is:.git
4131 --ignore-directory=is:.hg
4134 --ignore-directory=is:.pc
4137 --ignore-directory=is:.svn
4140 --ignore-directory=is:_MTN
4143 --ignore-directory=is:CVS
4146 --ignore-directory=is:RCS
4149 --ignore-directory=is:SCCS
4152 --ignore-directory=is:_darcs
4155 --ignore-directory=is:_sgbak
4158 --ignore-directory=is:autom4te.cache
4160 # Perl module building
4161 --ignore-directory=is:blib
4162 --ignore-directory=is:_build
4164 # Perl Devel::Cover module's output directory
4165 --ignore-directory=is:cover_db
4171 --ignore-file=ext:bak
4172 --ignore-file=match:/~$/
4175 --ignore-file=match:/^#.+#$/
4178 --ignore-file=match:/[._].*\.swp$/
4181 --ignore-file=match:/core\.\d+$/
4183 # minified Javascript
4184 --ignore-file=match:/[.]min[.]js$/
4189 # Perl http://perl.org/
4190 --type-add=perl:ext:pl,pm,pod,t
4191 --type-add=perl:firstlinematch:/#!.*\bperl/
4193 # Makefiles http://www.gnu.org/s/make/
4194 --type-add=make:ext:mk
4195 --type-add=make:ext:mak
4196 --type-add=make:is:makefile
4197 --type-add=make:is:Makefile
4198 --type-add=make:is:GNUmakefile
4200 # Rakefiles http://rake.rubyforge.org/
4201 --type-add=rake:is:Rakefile
4203 # CMake http://www.cmake.org/
4204 --type-add=cmake:is:CMakeLists.txt
4205 --type-add=cmake:ext:cmake
4208 --type-add=actionscript:ext:as,mxml
4210 # Ada http://www.adaic.org/
4211 --type-add=ada:ext:ada,adb,ads
4213 # ASP http://msdn.microsoft.com/en-us/library/aa286483.aspx
4214 --type-add=asp:ext:asp
4216 # ASP.Net http://www.asp.net/
4217 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
4220 --type-add=asm:ext:asm,s
4223 --type-add=batch:ext:bat,cmd
4225 # ColdFusion http://en.wikipedia.org/wiki/ColdFusion
4226 --type-add=cfmx:ext:cfc,cfm,cfml
4228 # Clojure http://clojure.org/
4229 --type-add=clojure:ext:clj
4232 # .xs are Perl C files
4233 --type-add=cc:ext:c,h,xs
4239 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
4242 --type-add=csharp:ext:cs
4244 # CSS http://www.w3.org/Style/CSS/
4245 --type-add=css:ext:css
4247 # Delphi http://en.wikipedia.org/wiki/Embarcadero_Delphi
4248 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
4250 # Emacs Lisp http://www.gnu.org/software/emacs
4251 --type-add=elisp:ext:el
4253 # Erlang http://www.erlang.org/
4254 --type-add=erlang:ext:erl,hrl
4256 # Fortran http://en.wikipedia.org/wiki/Fortran
4257 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
4259 # Google Go http://golang.org/
4260 --type-add=go:ext:go
4262 # Groovy http://groovy.codehaus.org/
4263 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
4265 # Haskell http://www.haskell.org/
4266 --type-add=haskell:ext:hs,lhs
4269 --type-add=html:ext:htm,html
4271 # Java http://www.oracle.com/technetwork/java/index.html
4272 --type-add=java:ext:java,properties
4275 --type-add=js:ext:js
4277 # JSP http://www.oracle.com/technetwork/java/javaee/jsp/index.html
4278 --type-add=jsp:ext:jsp,jspx,jhtm,jhtml
4280 # Common Lisp http://common-lisp.net/
4281 --type-add=lisp:ext:lisp,lsp
4283 # Lua http://www.lua.org/
4284 --type-add=lua:ext:lua
4287 --type-add=objc:ext:m,h
4290 --type-add=objcpp:ext:mm,h
4292 # OCaml http://caml.inria.fr/
4293 --type-add=ocaml:ext:ml,mli
4295 # Parrot http://www.parrot.org/
4296 --type-add=parrot:ext:pir,pasm,pmc,ops,pod,pg,tg
4298 # PHP http://www.php.net/
4299 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
4300 --type-add=php:firstlinematch:/#!.*\bphp/
4302 # Plone http://plone.org/
4303 --type-add=plone:ext:pt,cpt,metadata,cpy,py
4305 # Python http://www.python.org/
4306 --type-add=python:ext:py
4307 --type-add=python:firstlinematch:/#!.*\bpython/
4309 # R http://www.r-project.org/
4312 # Ruby http://www.ruby-lang.org/
4313 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
4314 --type-add=ruby:is:Rakefile
4315 --type-add=ruby:firstlinematch:/#!.*\bruby/
4317 # Scala http://www.scala-lang.org/
4318 --type-add=scala:ext:scala
4320 # Scheme http://groups.csail.mit.edu/mac/projects/scheme/
4321 --type-add=scheme:ext:scm,ss
4324 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh
4325 --type-add=shell:firstlinematch:/(?:ba|t?c|k|z)?sh\b/
4327 # Smalltalk http://www.smalltalk.org/
4328 --type-add=smalltalk:ext:st
4330 # SQL http://www.iso.org/iso/catalogue_detail.htm?csnumber=45498
4331 --type-add=sql:ext:sql,ctl
4333 # Tcl http://www.tcl.tk/
4334 --type-add=tcl:ext:tcl,itcl,itk
4336 # LaTeX http://www.latex-project.org/
4337 --type-add=tex:ext:tex,cls,sty
4339 # Template Toolkit http://template-toolkit.org/
4340 --type-add=tt:ext:tt,tt2,ttml
4343 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
4346 --type-add=verilog:ext:v,vh,sv
4348 # VHDL http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
4349 --type-add=vhdl:ext:vhd,vhdl
4351 # Vim http://www.vim.org/
4352 --type-add=vim:ext:vim
4354 # XML http://www.w3.org/TR/REC-xml/
4355 --type-add=xml:ext:xml,dtd,xsl,xslt,ent
4356 --type-add=xml:firstlinematch:/<[?]xml/
4358 # YAML http://yaml.org/
4359 --type-add=yaml:ext:yaml,yml