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 # https://github.com/petdance/ack2
8 # and submit patches against the individual files
17 our $VERSION = '2.15_01'; # Check http://beyondgrep.com/ for updates
20 use Getopt
::Long
2.38 ();
26 # XXX Don't make this so brute force
27 # See also: https://github.com/petdance/ack2/issues/89
29 our $opt_after_context;
30 our $opt_before_context;
35 our $opt_show_filename;
48 # flag if we need any context tracking
49 our $is_tracking_context;
51 # These are all our globals.
54 $App::Ack
::orig_program_name
= $0;
55 $0 = join(' ', 'ack', $0);
56 if ( $App::Ack
::VERSION
ne $main::VERSION
) {
57 App
::Ack
::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
60 # Do preliminary arg checking;
61 my $env_is_usable = 1;
62 for my $arg ( @ARGV ) {
63 last if ( $arg eq '--' );
65 # Get the --thpppt, --bar, --cathy checking out of the way.
66 $arg =~ /^--th[pt]+t+$/ and App
::Ack
::_thpppt
($arg);
67 $arg eq '--bar' and App
::Ack
::_bar
();
68 $arg eq '--cathy' and App
::Ack
::_cathy
();
70 # See if we want to ignore the environment. (Don't tell Al Gore.)
71 $arg eq '--env' and $env_is_usable = 1;
72 $arg eq '--noenv' and $env_is_usable = 0;
75 if ( !$env_is_usable ) {
76 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
81 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
82 Getopt
::Long
::Configure
('pass_through', 'no_auto_abbrev');
83 Getopt
::Long
::GetOptions
(
84 'help' => sub { App
::Ack
::show_help
(); exit; },
85 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
86 'man' => sub { App
::Ack
::show_man
(); exit; },
88 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
91 App
::Ack
::show_help
();
98 sub _compile_descend_filter
{
102 my $dont_ignore_dirs = 0;
104 for my $filter (@{$opt->{idirs
} || []}) {
105 if ($filter->is_inverted()) {
113 # if we have one or more --noignore-dir directives, we can't ignore
114 # entire subdirectory hierarchies, so we return an "accept all"
115 # filter and scrutinize the files more in _compile_file_filter
116 return if $dont_ignore_dirs;
117 return unless $idirs;
119 $idirs = $opt->{idirs
};
122 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::dir
);
123 return !grep { $_->filter($resource) } @{$idirs};
127 sub _compile_file_filter
{
128 my ( $opt, $start ) = @_;
130 my $ifiles_filters = $opt->{ifiles
};
132 my $filters = $opt->{'filters'} || [];
133 my $direct_filters = App
::Ack
::Filter
::Collection-
>new();
134 my $inverse_filters = App
::Ack
::Filter
::Collection-
>new();
136 foreach my $filter (@{$filters}) {
137 if ($filter->is_inverted()) {
138 # We want to check if files match the uninverted filters
139 $inverse_filters->add($filter->invert());
142 $direct_filters->add($filter);
146 my %is_member_of_starting_set = map { (get_file_id
($_) => 1) } @{$start};
148 my @ignore_dir_filter = @{$opt->{idirs
} || []};
149 my @is_inverted = map { $_->is_inverted() } @ignore_dir_filter;
150 # this depends on InverseFilter->invert returning the original
151 # filter (for optimization)
152 @ignore_dir_filter = map { $_->is_inverted() ? $_->invert() : $_ } @ignore_dir_filter;
153 my $dont_ignore_dir_filter = grep { $_ } @is_inverted;
154 my $previous_dir = '';
155 my $previous_dir_ignore_result;
159 if ( $File::Next
::name
=~ /$opt_regex/ && $opt_v ) {
162 if ( $File::Next
::name
!~ /$opt_regex/ && !$opt_v ) {
166 # ack always selects files that are specified on the command
167 # line, regardless of filetype. If you want to ack a JPEG,
168 # and say "ack foo whatever.jpg" it will do it for you.
169 return 1 if $is_member_of_starting_set{ get_file_id
($File::Next
::name
) };
171 if ( $dont_ignore_dir_filter ) {
172 if ( $previous_dir eq $File::Next
::dir
) {
173 if ( $previous_dir_ignore_result ) {
178 my @dirs = File
::Spec-
>splitdir($File::Next
::dir
);
182 for ( my $i = 0; $i < @dirs; $i++) {
183 my $dir_rsrc = App
::Ack
::Resource
::Basic-
>new(File
::Spec-
>catfile(@dirs[0 .. $i]));
186 for my $filter (@ignore_dir_filter) {
187 if ( $filter->filter($dir_rsrc) ) {
188 $is_ignoring = !$is_inverted[$j];
194 $previous_dir = $File::Next
::dir
;
195 $previous_dir_ignore_result = $is_ignoring;
197 if ( $is_ignoring ) {
203 # Ignore named pipes found in directory searching. Named
204 # pipes created by subprocesses get specified on the command
205 # line, so the rule of "always select whatever is on the
206 # command line" wins.
207 return 0 if -p
$File::Next
::name
;
209 # We can't handle unreadable filenames; report them.
211 use filetest
'access';
213 if ( not -R
$File::Next
::name
) {
214 if ( $App::Ack
::report_bad_filenames
) {
215 App
::Ack
::warn( "${File::Next::name}: cannot open file for reading" );
221 my $resource = App
::Ack
::Resource
::Basic-
>new($File::Next
::name
);
223 if ( $ifiles_filters && $ifiles_filters->filter($resource) ) {
227 my $match_found = $direct_filters->filter($resource);
229 # Don't bother invoking inverse filters unless we consider the current resource a match
230 if ( $match_found && $inverse_filters->filter( $resource ) ) {
238 my $resource = shift;
241 my @types = filetypes
( $resource );
242 my $types = join( ',', @types );
243 my $arrow = @types ? ' => ' : ' =>';
244 App
::Ack
::print( $resource->name, $arrow, join( ',', @types ), $ors );
249 # Set default colors, load Term::ANSIColor
251 eval 'use Term::ANSIColor 1.10 ()';
252 eval 'use Win32::Console::ANSI' if $App::Ack
::is_windows
;
254 $ENV{ACK_COLOR_MATCH
} ||= 'black on_yellow';
255 $ENV{ACK_COLOR_FILENAME
} ||= 'bold green';
256 $ENV{ACK_COLOR_LINENO
} ||= 'bold yellow';
262 my ( $resource ) = @_;
266 foreach my $k (keys %App::Ack
::mappings
) {
267 my $filters = $App::Ack
::mappings
{$k};
269 foreach my $filter (@{$filters}) {
271 my $clone = $resource->clone;
272 if ( $filter->filter($clone) ) {
279 # http://search.cpan.org/dist/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm
280 @matches = sort @matches;
284 # Returns a (fairly) unique identifier for a file.
285 # Use this function to compare two files to see if they're
286 # equal (ie. the same file, but with a different path/links/etc).
288 my ( $filename ) = @_;
290 if ( $App::Ack
::is_windows
) {
291 return File
::Next
::reslash
( $filename );
294 # XXX is this the best method? it always hits the FS
295 if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
296 return join(':', $dev, $inode);
299 # XXX this could be better
305 # Returns a regex object based on a string and command-line options.
306 # Dies when the regex $str is undefined (i.e. not given on command line).
312 defined $str or App
::Ack
::die( 'No regular expression found.' );
314 $str = quotemeta( $str ) if $opt->{Q
};
316 my $pristine_str = $str;
319 $str = "\\b$str" if $pristine_str =~ /^\w/;
320 $str = "$str\\b" if $pristine_str =~ /\w$/;
323 my $regex_is_lc = $str eq lc $str;
324 if ( $opt->{i
} || ($opt->{smart_case
} && $regex_is_lc) ) {
328 my $re = eval { qr/$str/m };
330 die "Invalid regex '$str':\n $@";
337 my $match_column_number;
341 # number of context lines
342 my $n_before_ctx_lines;
343 my $n_after_ctx_lines;
345 # array to keep track of lines that might be required for a "before" context
346 my @before_context_buf;
347 # position to insert next line in @before_context_buf
348 my $before_context_pos;
350 # number of "after" context lines still pending
351 my $after_context_pending;
353 # number of latest line that got printed
359 my $has_printed_something;
362 $has_printed_something = 0;
365 # setup context tracking variables
366 sub setup_line_context
{
368 $n_before_ctx_lines = $opt_output ? 0 : ($opt_before_context || 0);
369 $n_after_ctx_lines = $opt_output ? 0 : ($opt_after_context || 0);
371 @before_context_buf = (undef) x
$n_before_ctx_lines;
372 $before_context_pos = 0;
374 $is_tracking_context = $n_before_ctx_lines || $n_after_ctx_lines;
381 # adjust context tracking variables when entering a new file
382 sub setup_line_context_for_file
{
384 $printed_line_no = 0;
385 $after_context_pending = 0;
386 if ( $opt_heading && !$opt_lines ) {
395 This subroutine jumps through a number of optimization hoops to
396 try to be fast in the more common use cases of ack. For one thing,
397 in non-context tracking searches (not using -A, -B, or -C),
398 conditions that normally would be checked inside the loop happen
399 outside, resulting in three nearly identical loops for -v, --passthru,
400 and normal searching. Any changes that happen to one should propagate
401 to the others if they make sense. The non-context branches also inline
402 does_match for performance reasons; any relevant changes that happen here
403 must also happen there.
407 sub print_matches_in_resource
{
408 my ( $resource, $opt ) = @_;
410 my $max_count = $opt_m || -1;
412 my $filename = $resource->name;
413 my $ors = $opt_print0 ? "\0" : "\n";
415 my $has_printed_for_this_resource = 0;
419 my $fh = $resource->open();
421 if ( $App::Ack
::report_bad_filenames
) {
422 App
::Ack
::warn( "$filename: $!" );
427 my $display_filename = $filename;
428 if ( $opt_show_filename && $opt_heading && $opt_color ) {
429 $display_filename = Term
::ANSIColor
::colored
($display_filename, $ENV{ACK_COLOR_FILENAME
});
432 # check for context before the main loop, so we don't
433 # pay for it if we don't need it
434 if ( $is_tracking_context ) {
435 $after_context_pending = 0;
437 if ( does_match
($opt, $_) && $max_count ) {
438 if ( !$has_printed_for_this_resource ) {
439 if ( $opt_break && $has_printed_something ) {
440 App
::Ack
::print_blank_line
();
442 if ( $opt_show_filename && $opt_heading ) {
443 App
::Ack
::print_filename
( $display_filename, $ors );
446 print_line_with_context
($opt, $filename, $_, $.);
447 $has_printed_for_this_resource = 1;
451 elsif ( $opt_passthru ) {
452 chomp; # XXX proper newline handling?
453 # XXX inline this call?
454 if ( $opt_break && !$has_printed_for_this_resource && $has_printed_something ) {
455 App
::Ack
::print_blank_line
();
457 print_line_with_options
($opt, $filename, $_, $., ':');
458 $has_printed_for_this_resource = 1;
461 chomp; # XXX proper newline handling?
462 print_line_if_context
($opt, $filename, $_, $., '-');
465 last if ($max_count == 0) && ($after_context_pending == 0);
471 if ( $opt_passthru ) {
473 $match_column_number = undef;
474 if ( $opt_v ? !/$opt_regex/o : /$opt_regex/o ) {
476 $match_column_number = $-[0] + 1;
478 if ( !$has_printed_for_this_resource ) {
479 if ( $opt_break && $has_printed_something ) {
480 App
::Ack
::print_blank_line
();
482 if ( $opt_show_filename && $opt_heading ) {
483 App
::Ack
::print_filename
( $display_filename, $ors );
486 print_line_with_context
($opt, $filename, $_, $.);
487 $has_printed_for_this_resource = 1;
492 chomp; # XXX proper newline handling?
493 if ( $opt_break && !$has_printed_for_this_resource && $has_printed_something ) {
494 App
::Ack
::print_blank_line
();
496 print_line_with_options
($opt, $filename, $_, $., ':');
497 $has_printed_for_this_resource = 1;
499 last unless $max_count != 0;
503 $match_column_number = undef;
505 if ( !/$opt_regex/o ) {
506 if ( !$has_printed_for_this_resource ) {
507 if ( $opt_break && $has_printed_something ) {
508 App
::Ack
::print_blank_line
();
510 if ( $opt_show_filename && $opt_heading ) {
511 App
::Ack
::print_filename
( $display_filename, $ors );
514 print_line_with_context
($opt, $filename, $_, $.);
515 $has_printed_for_this_resource = 1;
519 last unless $max_count != 0;
523 # XXX unroll first match check ($has_printed_for_this_resource)
524 # XXX what if this is a *huge* file? (see also -l)
530 my $prev_match_end = 0;
533 $match_column_number = undef;
534 while ( $contents =~ /$opt_regex/og ) {
535 my $match_start = $-[0];
536 my $match_end = $+[0];
538 pos($contents) = $prev_match_end;
539 $prev_match_end = $match_end;
541 while ( $contents =~ /\n/og && $-[0] < $match_start ) {
545 my $start_line = rindex($contents, "\n", $match_start);
546 my $end_line = index($contents, "\n", $match_end);
548 if ( $start_line == -1 ) {
555 if ( $end_line == -1 ) {
556 $end_line = length($contents);
561 $match_column_number = $match_start - $start_line + 1;
562 if ( !$has_printed_for_this_resource ) {
563 if ( $opt_break && $has_printed_something ) {
564 App
::Ack
::print_blank_line
();
566 if ( $opt_show_filename && $opt_heading ) {
567 App
::Ack
::print_filename
( $display_filename, $ors );
570 my $line = substr($contents, $start_line, $end_line - $start_line + 1);
571 $line =~ s/[\r\n]+$//g;
572 print_line_with_options
($opt, $filename, $line, $line_no, ':');
574 pos($contents) = $end_line + 1;
576 $has_printed_for_this_resource = 1;
580 last unless $max_count != 0;
586 $is_iterating = 0; # XXX this won't happen on an exception
587 # then again, do we care? ack doesn't really
588 # handle exceptions anyway.
593 sub print_line_with_options
{
594 my ( $opt, $filename, $line, $line_no, $separator ) = @_;
596 $has_printed_something = 1;
597 $printed_line_no = $line_no;
599 my $ors = $opt_print0 ? "\0" : "\n";
604 $filename = Term
::ANSIColor
::colored
($filename,
605 $ENV{ACK_COLOR_FILENAME
});
606 $line_no = Term
::ANSIColor
::colored
($line_no,
607 $ENV{ACK_COLOR_LINENO
});
610 if($opt_show_filename) {
612 push @line_parts, $line_no;
615 push @line_parts, $filename, $line_no;
619 push @line_parts, get_match_column
();
623 while ( $line =~ /$opt_regex/og ) {
624 # XXX We need to stop using eval() for --output. See https://github.com/petdance/ack2/issues/421
625 my $output = eval $opt_output;
626 App
::Ack
::print( join( $separator, @line_parts, $output ), $ors );
631 $line =~ /$opt_regex/o; # this match is redundant, but we need
632 # to perfom it in order to get if
633 # capture groups are set
635 if ( @+ > 1 ) { # if we have captures
636 while ( $line =~ /$opt_regex/og ) {
637 my $offset = 0; # additional offset for when we add stuff
638 my $previous_match_end = 0;
640 for ( my $i = 1; $i < @+; $i++ ) {
641 my ( $match_start, $match_end ) = ( $-[$i], $+[$i] );
643 next unless defined($match_start);
644 next if $match_start < $previous_match_end;
646 my $substring = substr( $line,
647 $offset + $match_start, $match_end - $match_start );
648 my $substitution = Term
::ANSIColor
::colored
( $substring,
649 $ENV{ACK_COLOR_MATCH
} );
651 substr( $line, $offset + $match_start,
652 $match_end - $match_start, $substitution );
654 $previous_match_end = $match_end; # offsets do not need to be applied
655 $offset += length( $substitution ) - length( $substring );
658 pos($line) = $+[0] + $offset;
662 my $matched = 0; # flag; if matched, need to escape afterwards
664 while ( $line =~ /$opt_regex/og ) {
667 my ( $match_start, $match_end ) = ($-[0], $+[0]);
668 next unless defined($match_start);
670 my $substring = substr( $line, $match_start,
671 $match_end - $match_start );
672 my $substitution = Term
::ANSIColor
::colored
( $substring,
673 $ENV{ACK_COLOR_MATCH
} );
675 substr( $line, $match_start, $match_end - $match_start,
678 pos($line) = $match_end +
679 (length( $substitution ) - length( $substring ));
681 # XXX why do we do this?
682 $line .= "\033[0m\033[K" if $matched;
686 push @line_parts, $line;
687 App
::Ack
::print( join( $separator, @line_parts ), $ors );
694 my ( $resource, $opt, $cb ) = @_;
698 my $fh = $resource->open();
700 if ( $App::Ack
::report_bad_filenames
) {
701 App
::Ack
::warn( $resource->name . ': ' . $! );
706 # Check for context before the main loop, so we don't pay for it if we don't need it.
707 if ( $is_tracking_context ) {
708 $after_context_pending = 0;
722 $is_iterating = 0; # XXX this won't happen on an exception
723 # then again, do we care? ack doesn't really
724 # handle exceptions anyway.
729 sub print_line_with_context
{
730 my ( $opt, $filename, $matching_line, $line_no ) = @_;
732 my $ors = $opt_print0 ? "\0" : "\n";
733 my $is_tracking_context = $opt_after_context || $opt_before_context;
735 $matching_line =~ s/[\r\n]+$//g;
737 # check if we need to print context lines first
738 if( $is_tracking_context ) {
739 my $before_unprinted = $line_no - $printed_line_no - 1;
740 if ( !$is_first_match && ( !$printed_line_no || $before_unprinted > $n_before_ctx_lines ) ) {
741 App
::Ack
::print('--', $ors);
744 # We want at most $n_before_ctx_lines of context
745 if ( $before_unprinted > $n_before_ctx_lines ) {
746 $before_unprinted = $n_before_ctx_lines;
749 while ( $before_unprinted > 0 ) {
750 my $line = $before_context_buf[($before_context_pos - $before_unprinted + $n_before_ctx_lines) % $n_before_ctx_lines];
754 # Disable $opt->{column} since there are no matches in the context lines
755 local $opt_column = 0;
757 print_line_with_options
($opt, $filename, $line, $line_no-$before_unprinted, '-');
762 print_line_with_options
($opt, $filename, $matching_line, $line_no, ':');
764 # We want to get the next $n_after_ctx_lines printed
765 $after_context_pending = $n_after_ctx_lines;
772 # print the line only if it's part of a context we need to display
773 sub print_line_if_context
{
774 my ( $opt, $filename, $line, $line_no, $separator ) = @_;
776 if ( $after_context_pending ) {
777 # Disable $opt->{column} since there are no matches in the context lines
778 local $opt_column = 0;
779 print_line_with_options
( $opt, $filename, $line, $line_no, $separator );
780 --$after_context_pending;
782 elsif ( $n_before_ctx_lines ) {
783 # save line for "before" context
784 $before_context_buf[$before_context_pos] = $_;
785 $before_context_pos = ($before_context_pos+1) % $n_before_ctx_lines;
793 # does_match() MUST have an $opt_regex set.
797 This subroutine is inlined a few places in print_matches_in_resource
798 for performance reasons, so any changes here must be copied there as
804 my ( $opt, $line ) = @_;
806 $match_column_number = undef;
809 return ( $line !~ /$opt_regex/o );
812 if ( $line =~ /$opt_regex/o ) {
813 # @- = @LAST_MATCH_START
814 # @+ = @LAST_MATCH_END
815 $match_column_number = $-[0] + 1;
824 sub get_match_column
{
825 return $match_column_number;
828 sub resource_has_match
{
829 my ( $resource, $opt ) = @_;
832 my $fh = $resource->open();
834 if ( $App::Ack
::report_bad_filenames
) {
835 App
::Ack
::warn( $resource->name . ': ' . $! );
841 if (!/$opt_regex/o) {
849 # XXX only do this for certain file sizes?
854 $has_match = $content =~ /$opt_regex/o;
862 sub count_matches_in_resource
{
863 my ( $resource, $opt ) = @_;
866 my $fh = $resource->open();
868 if ( $App::Ack
::report_bad_filenames
) {
869 App
::Ack
::warn( $resource->name . ': ' . $! );
875 ++$nmatches if (!/$opt_regex/o);
883 $nmatches =()= ($content =~ /$opt_regex/og);
892 my @arg_sources = App
::Ack
::ConfigLoader
::retrieve_arg_sources
();
894 my $opt = App
::Ack
::ConfigLoader
::process_args
( @arg_sources );
896 $opt_after_context = $opt->{after_context
};
897 $opt_before_context = $opt->{before_context
};
898 $opt_output = $opt->{output
};
899 $opt_print0 = $opt->{print0
};
900 $opt_color = $opt->{color
};
901 $opt_heading = $opt->{heading
};
902 $opt_show_filename = $opt->{show_filename
};
903 $opt_regex = $opt->{regex
};
904 $opt_break = $opt->{break};
905 $opt_count = $opt->{count
};
910 $opt_lines = $opt->{lines
};
913 $opt_passthru = $opt->{passthru
};
914 $opt_column = $opt->{column
};
916 $App::Ack
::report_bad_filenames
= !$opt->{dont_report_bad_filenames
};
918 if ( $opt->{flush
} ) {
922 if ( !defined($opt_color) && !$opt_g ) {
923 my $windows_color = 1;
924 if ( $App::Ack
::is_windows
) {
925 $windows_color = eval { require Win32
::Console
::ANSI
; };
927 $opt_color = !App
::Ack
::output_to_pipe
() && $windows_color;
929 if ( not defined $opt_heading and not defined $opt_break ) {
930 $opt_heading = $opt_break = $opt->{break} = !App
::Ack
::output_to_pipe
();
933 if ( defined($opt->{H
}) || defined($opt->{h
}) ) {
934 $opt_show_filename = $opt->{show_filename
} = $opt->{H
} && !$opt->{h
};
937 if ( my $output = $opt_output ) {
938 $output =~ s{\\}{\\\\}g;
939 $output =~ s{"}{\\"}g;
940 $opt_output = qq{"$output"};
944 if ( $App::Ack
::is_filter_mode
&& !$opt->{files_from
} ) { # probably -x
945 $resources = App
::Ack
::Resources-
>from_stdin( $opt );
946 $opt_regex = shift @ARGV if not defined $opt_regex;
947 $opt_regex = $opt->{regex
} = build_regex
( $opt_regex, $opt );
950 if ( $opt_f || $opt_lines ) {
952 App
::Ack
::warn( "regex ($opt_regex) specified with -f or --lines" );
953 App
::Ack
::exit_from_ack
( 0 ); # XXX the 0 is misleading
957 $opt_regex = shift @ARGV if not defined $opt_regex;
958 $opt_regex = $opt->{regex
} = build_regex
( $opt_regex, $opt );
960 if ( $opt_regex && $opt_regex =~ /\n/ ) {
961 App
::Ack
::exit_from_ack
( 0 );
964 if ( not defined $opt->{files_from
} ) {
967 if ( !exists($opt->{show_filename
}) ) {
968 unless(@start == 1 && !(-d
$start[0])) {
969 $opt_show_filename = $opt->{show_filename
} = 1;
973 if ( defined $opt->{files_from
} ) {
974 $resources = App
::Ack
::Resources-
>from_file( $opt, $opt->{files_from
} );
975 exit 1 unless $resources;
978 @start = ('.') unless @start;
979 foreach my $target (@start) {
980 if ( !-e
$target && $App::Ack
::report_bad_filenames
) {
981 App
::Ack
::warn( "$target: No such file or directory" );
985 $opt->{file_filter
} = _compile_file_filter
($opt, \
@start);
986 $opt->{descend_filter
} = _compile_descend_filter
($opt);
988 $resources = App
::Ack
::Resources-
>from_argv( $opt, \
@start );
991 App
::Ack
::set_up_pager
( $opt->{pager
} ) if defined $opt->{pager
};
993 my $ors = $opt_print0 ? "\0" : "\n";
994 my $only_first = $opt->{1};
999 setup_line_context
( $opt );
1002 while ( my $resource = $resources->next ) {
1003 if ($is_tracking_context) {
1004 setup_line_context_for_file
($opt);
1007 # XXX Combine the -f and -g functions
1009 # XXX printing should probably happen inside of App::Ack
1010 if ( $opt->{show_types
} ) {
1011 show_types
( $resource, $ors );
1014 App
::Ack
::print( $resource->name, $ors );
1017 last RESOURCES
if defined($opt_m) && $nmatches >= $opt_m;
1020 if ( $opt->{show_types
} ) {
1021 show_types
( $resource, $ors );
1024 local $opt_show_filename = 0; # XXX Why is this local?
1026 print_line_with_options
($opt, '', $resource->name, 0, $ors);
1029 last RESOURCES
if defined($opt_m) && $nmatches >= $opt_m;
1031 elsif ( $opt_lines ) {
1033 foreach my $line ( @{ $opt_lines } ) {
1034 my @lines = split /,/, $line;
1040 @line_numbers{@lines} = (1) x
@lines;
1043 my $filename = $resource->name;
1045 local $opt_color = 0;
1047 iterate
($resource, $opt, sub {
1050 if ( $line_numbers{$.} ) {
1051 print_line_with_context
($opt, $filename, $_, $.);
1053 elsif ( $opt_passthru ) {
1054 print_line_with_options
($opt, $filename, $_, $., ':');
1056 elsif ( $is_tracking_context ) {
1057 print_line_if_context
($opt, $filename, $_, $., '-');
1062 elsif ( $opt_count ) {
1063 my $matches_for_this_file = count_matches_in_resource
( $resource, $opt );
1065 if ( not $opt_show_filename ) {
1066 $total_count += $matches_for_this_file;
1070 if ( !$opt_l || $matches_for_this_file > 0) {
1071 if ( $opt_show_filename ) {
1072 App
::Ack
::print( $resource->name, ':', $matches_for_this_file, $ors );
1075 App
::Ack
::print( $matches_for_this_file, $ors );
1079 elsif ( $opt_l || $opt_L ) {
1080 my $is_match = resource_has_match
( $resource, $opt );
1082 if ( $opt_L ? !$is_match : $is_match ) {
1083 App
::Ack
::print( $resource->name, $ors );
1086 last RESOURCES
if $only_first;
1087 last RESOURCES
if defined($opt_m) && $nmatches >= $opt_m;
1091 $nmatches += print_matches_in_resource
( $resource, $opt );
1092 if ( $nmatches && $only_first ) {
1098 if ( $opt_count && !$opt_show_filename ) {
1099 App
::Ack
::print( $total_count, "\n" );
1102 close $App::Ack
::fh
;
1103 App
::Ack
::exit_from_ack
( $nmatches );
1110 ack - grep-like text finder
1114 ack [options] PATTERN [FILE...]
1115 ack -f [options] [DIRECTORY...]
1119 Ack is designed as an alternative to F<grep> for programmers.
1121 Ack searches the named input FILEs (or standard input if no files
1122 are named, or the file name - is given) for lines containing a match
1123 to the given PATTERN. By default, ack prints the matching lines.
1125 PATTERN is a Perl regular expression. Perl regular expressions
1126 are commonly found in other programming languages, but for the particulars
1127 of their behavior, please consult
1128 L<http://perldoc.perl.org/perlreref.html|perlreref>. If you don't know
1129 how to use regular expression but are interested in learning, you may
1130 consult L<http://perldoc.perl.org/perlretut.html|perlretut>. If you do not
1131 need or want ack to use regular expressions, please see the
1132 C<-Q>/C<--literal> option.
1134 Ack can also list files that would be searched, without actually
1135 searching them, to let you take advantage of ack's file-type filtering
1138 =head1 FILE SELECTION
1140 If files are not specified for searching, either on the command
1141 line or piped in with the C<-x> option, I<ack> delves into
1142 subdirectories selecting files for searching.
1144 I<ack> is intelligent about the files it searches. It knows about
1145 certain file types, based on both the extension on the file and,
1146 in some cases, the contents of the file. These selections can be
1147 made with the B<--type> option.
1149 With no file selection, I<ack> searches through regular files that
1150 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
1151 options, either present in F<ackrc> files or on the command line.
1153 The default options for I<ack> ignore certain files and directories. These
1158 =item * Backup files: Files matching F<#*#> or ending with F<~>.
1160 =item * Coredumps: Files matching F<core.\d+>
1162 =item * Version control directories like F<.svn> and F<.git>.
1166 Run I<ack> with the C<--dump> option to see what settings are set.
1168 However, I<ack> always searches the files given on the command line,
1169 no matter what type. If you tell I<ack> to search in a coredump,
1170 it will search in a coredump.
1172 =head1 DIRECTORY SELECTION
1174 I<ack> descends through the directory tree of the starting directories
1175 specified. If no directories are specified, the current working directory is
1176 used. However, it will ignore the shadow directories used by
1177 many version control systems, and the build directories used by the
1178 Perl MakeMaker system. You may add or remove a directory from this
1179 list with the B<--[no]ignore-dir> option. The option may be repeated
1180 to add/remove multiple directories from the ignore list.
1182 For a complete list of directories that do not get searched, run
1185 =head1 WHEN TO USE GREP
1187 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
1188 throw I<grep> away, because there are times you'll still need it.
1190 E.g., searching through huge files looking for regexes that can be
1191 expressed with I<grep> syntax should be quicker with I<grep>.
1193 If your script or parent program uses I<grep> C<--quiet> or C<--silent>
1194 or needs exit 2 on IO error, use I<grep>.
1202 Specifies an ackrc file to load after all others; see L</"ACKRC LOCATION SEMANTICS">.
1204 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
1206 Print I<NUM> lines of trailing context after matching lines.
1208 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
1210 Print I<NUM> lines of leading context before matching lines.
1212 =item B<--[no]break>
1214 Print a break between results from different files. On by default
1215 when used interactively.
1217 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
1219 Print I<NUM> lines (default 2) of context around matching lines.
1221 =item B<-c>, B<--count>
1223 Suppress normal output; instead print a count of matching lines for
1224 each input file. If B<-l> is in effect, it will only show the
1225 number of lines for each file that has lines matching. Without
1226 B<-l>, some line counts may be zeroes.
1228 If combined with B<-h> (B<--no-filename>) ack outputs only one total
1231 =item B<--[no]color>, B<--[no]colour>
1233 B<--color> highlights the matching text. B<--nocolor> suppresses
1234 the color. This is on by default unless the output is redirected.
1236 On Windows, this option is off by default unless the
1237 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
1238 environment variable is used.
1240 =item B<--color-filename=I<color>>
1242 Sets the color to be used for filenames.
1244 =item B<--color-match=I<color>>
1246 Sets the color to be used for matches.
1248 =item B<--color-lineno=I<color>>
1250 Sets the color to be used for line numbers.
1252 =item B<--[no]column>
1254 Show the column number of the first match. This is helpful for
1255 editors that can place your cursor at a given position.
1257 =item B<--create-ackrc>
1259 Dumps the default ack options to standard output. This is useful for
1260 when you want to customize the defaults.
1264 Writes the list of options loaded and where they came from to standard
1265 output. Handy for debugging.
1269 B<--noenv> disables all environment processing. No F<.ackrc> is
1270 read and all environment variables are ignored. By default, F<ack>
1271 considers F<.ackrc> and settings in the environment.
1275 B<--flush> flushes output immediately. This is off by default
1276 unless ack is running interactively (when output goes to a pipe or
1281 Only print the files that would be searched, without actually doing
1282 any searching. PATTERN must not be specified, or it will be taken
1283 as a path to search.
1285 =item B<--files-from=I<FILE>>
1287 The list of files to be searched is specified in I<FILE>. The list of
1288 files are separated by newlines. If I<FILE> is C<->, the list is loaded
1289 from standard input.
1291 =item B<--[no]filter>
1293 Forces ack to act as if it were receiving input via a pipe.
1295 =item B<--[no]follow>
1297 Follow or don't follow symlinks, other than whatever starting files
1298 or directories were specified on the command line.
1300 This is off by default.
1302 =item B<-g I<PATTERN>>
1304 Print files where the relative path + filename matches I<PATTERN>.
1305 This option can be combined with B<--color> to make it easier to spot
1308 =item B<--[no]group>
1310 B<--group> groups matches by file name. This is the default
1311 when used interactively.
1313 B<--nogroup> prints one result per line, like grep. This is the
1314 default when output is redirected.
1316 =item B<-H>, B<--with-filename>
1318 Print the filename for each match. This is the default unless searching
1319 a single explicitly specified file.
1321 =item B<-h>, B<--no-filename>
1323 Suppress the prefixing of filenames on output when multiple files are
1326 =item B<--[no]heading>
1328 Print a filename heading above each file's results. This is the default
1329 when used interactively.
1331 =item B<--help>, B<-?>
1333 Print a short help statement.
1335 =item B<--help-types>, B<--help=types>
1337 Print all known types.
1339 =item B<-i>, B<--ignore-case>
1341 Ignore case distinctions in PATTERN
1343 =item B<--ignore-ack-defaults>
1345 Tells ack to completely ignore the default definitions provided with ack.
1346 This is useful in combination with B<--create-ackrc> if you I<really> want
1349 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
1351 Ignore directory (as CVS, .svn, etc are ignored). May be used
1352 multiple times to ignore multiple directories. For example, mason
1353 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
1354 option allows users to search directories which would normally be
1355 ignored (perhaps to research the contents of F<.svn/props> directories).
1357 The I<DIRNAME> must always be a simple directory name. Nested
1358 directories like F<foo/bar> are NOT supported. You would need to
1359 specify B<--ignore-dir=foo> and then no files from any foo directory
1360 are taken into account by ack unless given explicitly on the command
1363 =item B<--ignore-file=I<FILTERTYPE:FILTERARGS>>
1365 Ignore files matching I<FILTERTYPE:FILTERARGS>. The filters are specified
1366 identically to file type filters as seen in L</"Defining your own types">.
1368 =item B<-k>, B<--known-types>
1370 Limit selected files to those with types that ack knows about. This is
1371 equivalent to the default behavior found in ack 1.
1373 =item B<--lines=I<NUM>>
1375 Only print line I<NUM> of each file. Multiple lines can be given with multiple
1376 B<--lines> options or as a comma separated list (B<--lines=3,5,7>). B<--lines=4-7>
1377 also works. The lines are always output in ascending order, no matter the
1378 order given on the command line.
1380 =item B<-l>, B<--files-with-matches>
1382 Only print the filenames of matching files, instead of the matching text.
1384 =item B<-L>, B<--files-without-matches>
1386 Only print the filenames of files that do I<NOT> match.
1388 =item B<--match I<PATTERN>>
1390 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
1391 regex as your first argument, e.g. when executing multiple searches over the
1394 # search for foo and bar in given files
1395 ack file1 t/file* --match foo
1396 ack file1 t/file* --match bar
1398 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
1400 Stop reading a file after I<NUM> matches.
1404 Print this manual page.
1406 =item B<-n>, B<--no-recurse>
1408 No descending into subdirectories.
1412 Show only the part of each line matching PATTERN (turns off text
1415 =item B<--output=I<expr>>
1417 Output the evaluation of I<expr> for each line (turns off text
1419 If PATTERN matches more than once then a line is output for each non-overlapping match.
1420 For more information please see the section L</"Examples of F<--output>">.
1422 =item B<--pager=I<program>>, B<--nopager>
1424 B<--pager> directs ack's output through I<program>. This can also be specified
1425 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
1427 Using --pager does not suppress grouping and coloring like piping
1428 output on the command-line does.
1430 B<--nopager> cancels any setting in ~/.ackrc, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
1431 No output will be sent through a pager.
1435 Prints all lines, whether or not they match the expression. Highlighting
1436 will still work, though, so it can be used to highlight matches while
1437 still seeing the entire file, as in:
1439 # Watch a log file, and highlight a certain IP address
1440 $ tail -f ~/access.log | ack --passthru 123.45.67.89
1444 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
1445 are output separated with a null byte instead of the usual newline. This is
1446 helpful when dealing with filenames that contain whitespace, e.g.
1448 # remove all files of type html
1449 ack -f --html --print0 | xargs -0 rm -f
1451 =item B<-Q>, B<--literal>
1453 Quote all metacharacters in PATTERN, it is treated as a literal.
1455 =item B<-r>, B<-R>, B<--recurse>
1457 Recurse into sub-directories. This is the default and just here for
1458 compatibility with grep. You can also use it for turning B<--no-recurse> off.
1462 Suppress error messages about nonexistent or unreadable files. This is taken
1465 =item B<--[no]smart-case>, B<--no-smart-case>
1467 Ignore case in the search strings if PATTERN contains no uppercase
1468 characters. This is similar to C<smartcase> in vim. This option is
1469 off by default, and ignored if C<-i> is specified.
1471 B<-i> always overrides this option.
1473 =item B<--sort-files>
1475 Sorts the found files lexicographically. Use this if you want your file
1476 listings to be deterministic between runs of I<ack>.
1478 =item B<--show-types>
1480 Outputs the filetypes that ack associates with each file.
1482 Works with B<-f> and B<-g> options.
1484 =item B<--type=[no]TYPE>
1486 Specify the types of files to include or exclude from a search.
1487 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
1488 also be specified as B<--perl>, and B<--type=noperl> can be done
1491 If a file is of both type "foo" and "bar", specifying --foo and
1492 --nobar will exclude the file, because an exclusion takes precedence
1495 Type specifications can be repeated and are ORed together.
1497 See I<ack --help=types> for a list of valid types.
1499 =item B<--type-add I<TYPE>:I<FILTER>:I<FILTERARGS>>
1501 Files with the given FILTERARGS applied to the given FILTER
1502 are recognized as being of (the existing) type TYPE.
1503 See also L</"Defining your own types">.
1506 =item B<--type-set I<TYPE>:I<FILTER>:I<FILTERARGS>>
1508 Files with the given FILTERARGS applied to the given FILTER are recognized as
1509 being of type TYPE. This replaces an existing definition for type TYPE. See
1510 also L</"Defining your own types">.
1512 =item B<--type-del I<TYPE>>
1514 The filters associated with TYPE are removed from Ack, and are no longer considered
1517 =item B<-v>, B<--invert-match>
1519 Invert match: select non-matching lines
1523 Display version and copyright information.
1525 =item B<-w>, B<--word-regexp>
1527 Force PATTERN to match only whole words. The PATTERN is wrapped with
1528 C<\b> metacharacters.
1532 An abbreviation for B<--files-from=->; the list of files to search are read
1533 from standard input, with one line per file.
1537 Stops after reporting first match of any kind. This is different
1538 from B<--max-count=1> or B<-m1>, where only one match per file is
1539 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
1544 Display the all-important Bill The Cat logo. Note that the exact
1545 spelling of B<--thpppppt> is not important. It's checked against
1546 a regular expression.
1550 Check with the admiral for traps.
1554 Chocolate, Chocolate, Chocolate!
1558 =head1 THE .ackrc FILE
1560 The F<.ackrc> file contains command-line options that are prepended
1561 to the command line before processing. Multiple options may live
1562 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
1563 might look like this:
1565 # Always sort the files
1568 # Always color, even if piping to a another program
1571 # Use "less -r" as my pager
1574 Note that arguments with spaces in them do not need to be quoted,
1575 as they are not interpreted by the shell. Basically, each I<line>
1576 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
1578 F<ack> looks in several locations for F<.ackrc> files; the searching
1579 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
1580 files are not considered if B<--noenv> is specified on the command line.
1582 =head1 Defining your own types
1584 ack allows you to define your own types in addition to the predefined
1585 types. This is done with command line options that are best put into
1586 an F<.ackrc> file - then you do not have to define your types over and
1587 over again. In the following examples the options will always be shown
1588 on one command line so that they can be easily copy & pasted.
1590 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
1591 tells you, that perl files are files ending
1592 in .pl, .pm, .pod or .t. So what if you would like to include .xs
1593 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
1594 does this for you. B<--type-add> appends
1595 additional extensions to an existing type.
1597 If you want to define a new type, or completely redefine an existing
1598 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
1599 the type I<eiffel> to include files with
1600 the extensions .e or .eiffel. So to search for all eiffel files
1601 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
1602 As usual, you can also write B<--type=eiffel>
1603 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
1604 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
1605 and I<.xs> files no longer belong to the type I<cc>.
1607 When defining your own types in the F<.ackrc> file you have to use
1610 --type-set=eiffel:ext:e,eiffel
1612 or writing on separate lines
1617 The following does B<NOT> work in the F<.ackrc> file:
1619 --type-set eiffel:ext:e,eiffel
1622 In order to see all currently defined types, use I<--help-types>, e.g.
1623 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
1625 In addition to filtering based on extension (like ack 1.x allowed), ack 2
1626 offers additional filter types. The generic syntax is
1627 I<--type-set TYPE:FILTER:FILTERARGS>; I<FILTERARGS> depends on the value
1632 =item is:I<FILENAME>
1634 I<is> filters match the target filename exactly. It takes exactly one
1635 argument, which is the name of the file to match.
1639 --type-set make:is:Makefile
1641 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
1643 I<ext> filters match the extension of the target file against a list
1644 of extensions. No leading dot is needed for the extensions.
1648 --type-set perl:ext:pl,pm,t
1650 =item match:I<PATTERN>
1652 I<match> filters match the target filename against a regular expression.
1653 The regular expression is made case insensitive for the search.
1657 --type-set make:match:/(gnu)?makefile/
1659 =item firstlinematch:I<PATTERN>
1661 I<firstlinematch> matches the first line of the target file against a
1662 regular expression. Like I<match>, the regular expression is made
1667 --type-add perl:firstlinematch:/perl/
1671 More filter types may be made available in the future.
1673 =head1 ENVIRONMENT VARIABLES
1675 For commonly-used ack options, environment variables can make life
1676 much easier. These variables are ignored if B<--noenv> is specified
1677 on the command line.
1683 Specifies the location of the user's F<.ackrc> file. If this file doesn't
1684 exist, F<ack> looks in the default location.
1688 This variable specifies default options to be placed in front of
1689 any explicit options on the command line.
1691 =item ACK_COLOR_FILENAME
1693 Specifies the color of the filename when it's printed in B<--group>
1694 mode. By default, it's "bold green".
1696 The recognized attributes are clear, reset, dark, bold, underline,
1697 underscore, blink, reverse, concealed black, red, green, yellow,
1698 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
1699 on_magenta, on_cyan, and on_white. Case is not significant.
1700 Underline and underscore are equivalent, as are clear and reset.
1701 The color alone sets the foreground color, and on_color sets the
1704 This option can also be set with B<--color-filename>.
1706 =item ACK_COLOR_MATCH
1708 Specifies the color of the matching text when printed in B<--color>
1709 mode. By default, it's "black on_yellow".
1711 This option can also be set with B<--color-match>.
1713 See B<ACK_COLOR_FILENAME> for the color specifications.
1715 =item ACK_COLOR_LINENO
1717 Specifies the color of the line number when printed in B<--color>
1718 mode. By default, it's "bold yellow".
1720 This option can also be set with B<--color-lineno>.
1722 See B<ACK_COLOR_FILENAME> for the color specifications.
1726 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
1727 ack will send its output.
1729 Using C<ACK_PAGER> does not suppress grouping and coloring like
1730 piping output on the command-line does, except that on Windows
1731 ack will assume that C<ACK_PAGER> does not support color.
1733 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
1735 =item ACK_PAGER_COLOR
1737 Specifies a pager program that understands ANSI color sequences.
1738 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
1739 like piping output on the command-line does.
1741 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
1745 =head1 AVAILABLE COLORS
1747 F<ack> uses the colors available in Perl's L<Term::ANSIColor> module, which
1748 provides the following listed values. Note that case does not matter when using
1751 =head2 Foreground colors
1753 black red green yellow blue magenta cyan white
1755 bright_black bright_red bright_green bright_yellow
1756 bright_blue bright_magenta bright_cyan bright_white
1758 =head2 Background colors
1760 on_black on_red on_green on_yellow
1761 on_blue on_magenta on_cyan on_white
1763 on_bright_black on_bright_red on_bright_green on_bright_yellow
1764 on_bright_blue on_bright_magenta on_bright_cyan on_bright_white
1766 =head1 ACK & OTHER TOOLS
1768 =head2 Vim integration
1770 F<ack> integrates easily with the Vim text editor. Set this in your
1771 F<.vimrc> to use F<ack> instead of F<grep>:
1775 That example uses C<-k> to search through only files of the types ack
1776 knows about, but you may use other default flags. Now you can search
1777 with F<ack> and easily step through the results in Vim:
1779 :grep Dumper perllib
1781 Miles Sterrett has written a Vim plugin for F<ack> which allows you to use
1782 C<:Ack> instead of C<:grep>, as well as several other advanced features.
1784 L<https://github.com/mileszs/ack.vim>
1786 =head2 Emacs integration
1788 Phil Jackson put together an F<ack.el> extension that "provides a
1789 simple compilation mode ... has the ability to guess what files you
1790 want to search for based on the major-mode."
1792 L<http://www.shellarchive.co.uk/content/emacs.html>
1794 =head2 TextMate integration
1796 Pedro Melo is a TextMate user who writes "I spend my day mostly
1797 inside TextMate, and the built-in find-in-project sucks with large
1798 projects. So I hacked a TextMate command that was using find +
1799 grep to use ack. The result is the Search in Project with ack, and
1800 you can find it here:
1801 L<http://www.simplicidade.org/notes/archives/2008/03/search_in_proje.html>"
1803 =head2 Shell and Return Code
1805 For greater compatibility with I<grep>, I<ack> in normal use returns
1806 shell return or exit code of 0 only if something is found and 1 if
1809 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
1811 The I<grep> code 2 for errors is not used.
1813 If C<-f> or C<-g> are specified, then 0 is returned if at least one
1814 file is found. If no files are found, then 1 is returned.
1818 =head1 DEBUGGING ACK PROBLEMS
1820 If ack gives you output you're not expecting, start with a few simple steps.
1822 =head2 Use B<--noenv>
1824 Your environment variables and F<.ackrc> may be doing things you're
1825 not expecting, or forgotten you specified. Use B<--noenv> to ignore
1826 your environment and F<.ackrc>.
1828 =head2 Use B<-f> to see what files have been selected
1830 Ack's B<-f> was originally added as a debugging tool. If ack is
1831 not finding matches you think it should find, run F<ack -f> to see
1832 what files have been selected. You can also add the C<--show-types>
1833 options to show the type of each file selected.
1835 =head2 Use B<--dump>
1837 This lists the ackrc files that are loaded and the options loaded
1839 So for example you can find a list of directories that do not get searched or where filetypes are defined.
1843 =head2 Use the F<.ackrc> file.
1845 The F<.ackrc> is the place to put all your options you use most of
1846 the time but don't want to remember. Put all your --type-add and
1847 --type-set definitions in it. If you like --smart-case, set it
1848 there, too. I also set --sort-files there.
1850 =head2 Use F<-f> for working with big codesets
1852 Ack does more than search files. C<ack -f --perl> will create a
1853 list of all the Perl files in a tree, ideal for sending into F<xargs>.
1856 # Change all "this" to "that" in all Perl files in a tree.
1857 ack -f --perl | xargs perl -p -i -e's/this/that/g'
1861 perl -p -i -e's/this/that/g' $(ack -f --perl)
1863 =head2 Use F<-Q> when in doubt about metacharacters
1865 If you're searching for something with a regular expression
1866 metacharacter, most often a period in a filename or IP address, add
1867 the -Q to avoid false positives without all the backslashing. See
1868 the following example for more...
1870 =head2 Use ack to watch log files
1872 Here's one I used the other day to find trouble spots for a website
1873 visitor. The user had a problem loading F<troublesome.gif>, so I
1874 took the access log and scanned it with ack twice.
1876 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
1878 The first ack finds only the lines in the Apache log for the given
1879 IP. The second finds the match on my troublesome GIF, and shows
1880 the previous five lines from the log in each case.
1882 =head2 Examples of F<--output>
1884 Following variables are useful in the expansion string:
1890 The whole string matched by PATTERN.
1892 =item C<$1>, C<$2>, ...
1894 The contents of the 1st, 2nd ... bracketed group in PATTERN.
1898 The string before the match.
1902 The string after the match.
1906 For more details and other variables see
1907 L<http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions|perlvar>.
1909 This example shows how to add text around a particular pattern
1910 (in this case adding _ around word with "e")
1912 ack2.pl "\w*e\w*" quick.txt --output="$`_$&_$'"
1913 _The_ quick brown fox jumps over the lazy dog
1914 The quick brown fox jumps _over_ the lazy dog
1915 The quick brown fox jumps over _the_ lazy dog
1917 This shows how to pick out particular parts of a match using ( ) within regular expression.
1919 ack '=head(\d+)\s+(.*)' --output=' $1 : $2'
1920 input file contains "=head1 NAME"
1923 =head2 Share your knowledge
1925 Join the ack-users mailing list. Send me your tips and I may add
1930 =head2 Why isn't ack finding a match in (some file)?
1932 Probably because it's of a type that ack doesn't recognize. ack's
1933 searching behavior is driven by filetype. B<If ack doesn't know
1934 what kind of file it is, ack ignores the file.>
1936 Use the C<-f> switch to see a list of files that ack will search
1937 for you. You can use the C<--show-types> switch to show which type
1938 ack thinks each file is.
1940 =head2 Wouldn't it be great if F<ack> did search & replace?
1942 No, ack will always be read-only. Perl has a perfectly good way
1943 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
1946 You can certainly use ack to select your files to update. For
1947 example, to change all "foo" to "bar" in all PHP files, you can do
1948 this from the Unix shell:
1950 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
1952 =head2 Can I make ack recognize F<.xyz> files?
1954 Yes! Please see L</"Defining your own types">. If you think
1955 that F<ack> should recognize a type by default, please see
1958 =head2 There's already a program/package called ack.
1962 =head2 Why is it called ack if it's called ack-grep?
1964 The name of the program is "ack". Some packagers have called it
1965 "ack-grep" when creating packages because there's already a package
1966 out there called "ack" that has nothing to do with this ack.
1968 I suggest you make a symlink named F<ack> that points to F<ack-grep>
1969 because one of the crucial benefits of ack is having a name that's
1970 so short and simple to type.
1972 To do that, run this with F<sudo> or as root:
1974 ln -s /usr/bin/ack-grep /usr/bin/ack
1976 Alternatively, you could use a shell alias:
1984 =head2 What does F<ack> mean?
1986 Nothing. I wanted a name that was easy to type and that you could
1987 pronounce as a single syllable.
1989 =head2 Can I do multi-line regexes?
1991 No, ack does not support regexes that match multiple lines. Doing
1992 so would require reading in the entire file at a time.
1994 If you want to see lines near your match, use the C<--A>, C<--B>
1995 and C<--C> switches for displaying context.
1997 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
1999 ack treats command line options beginning with C<+> or C<-> as options; if you
2000 would like to search for these, you may prefix your search term with C<--> or
2001 use the C<--match> option. (However, don't forget that C<+> is a regular
2002 expression metacharacter!)
2004 =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex?
2006 The Perl language limits the repetition quanitifier to 32K. You
2007 can search for C<.{32767}> but not C<.{32768}>.
2009 =head1 ACKRC LOCATION SEMANTICS
2011 Ack can load its configuration from many sources. The following list
2012 specifies the sources Ack looks for configuration files; each one
2013 that is found is loaded in the order specified here, and
2014 each one overrides options set in any of the sources preceding
2015 it. (For example, if I set --sort-files in my user ackrc, and
2016 --nosort-files on the command line, the command line takes
2023 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
2024 using C<--ignore-ack-defaults>.
2026 =item * Global ackrc
2028 Options are then loaded from the global ackrc. This is located at
2029 C</etc/ackrc> on Unix-like systems.
2031 Under Windows XP and earlier, the global ackrc is at
2032 C<C:\Documents and Settings\All Users\Application Data\ackrc>
2034 Under Windows Vista/7, the global ackrc is at
2035 C<C:\ProgramData\ackrc>
2037 The C<--noenv> option prevents all ackrc files from being loaded.
2041 Options are then loaded from the user's ackrc. This is located at
2042 C<$HOME/.ackrc> on Unix-like systems.
2044 Under Windows XP and earlier, the user's ackrc is at
2045 C<C:\Documents and Settings\$USER\Application Data\ackrc>.
2047 Under Windows Vista/7, the user's ackrc is at
2048 C<C:\Users\$USER\AppData\Roaming\ackrc>.
2050 If you want to load a different user-level ackrc, it may be specified
2051 with the C<$ACKRC> environment variable.
2053 The C<--noenv> option prevents all ackrc files from being loaded.
2055 =item * Project ackrc
2057 Options are then loaded from the project ackrc. The project ackrc is
2058 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
2059 in the current directory, then the parent directory, then the grandparent
2060 directory, etc. This can be omitted using C<--noenv>.
2064 The C<--ackrc> option may be included on the command line to specify an
2065 ackrc file that can override all others. It is consulted even if C<--noenv>
2070 Options are then loaded from the environment variable C<ACK_OPTIONS>. This can
2071 be omitted using C<--noenv>.
2073 =item * Command line
2075 Options are then loaded from the command line.
2079 =head1 DIFFERENCES BETWEEN ACK 1.X AND ACK 2.X
2081 A lot of changes were made for ack 2; here is a list of them.
2083 =head2 GENERAL CHANGES
2089 When no selectors are specified, ack 1.x only searches through files that
2090 it can map to a file type. ack 2.x, by contrast, will search through
2091 every regular, non-binary file that is not explicitly ignored via
2092 B<--ignore-file> or B<--ignore-dir>. This is similar to the behavior of the
2093 B<-a/--all> option in ack 1.x.
2097 A more flexible filter system has been added, so that more powerful file types
2098 may be created by the user. For details, please consult
2099 L</"Defining your own types">.
2103 ack now loads multiple ackrc files; see L</"ACKRC LOCATION SEMANTICS"> for
2108 ack's default filter definitions aren't special; you may tell ack to
2109 completely disregard them if you don't like them.
2113 =head2 REMOVED OPTIONS
2119 Because of the change in default search behavior, the B<-a/--all> and
2120 B<-u/--unrestricted> options have been removed. In addition, the
2121 B<-k/--known-types> option was added to cause ack to behave with
2122 the default search behavior of ack 1.x.
2126 The B<-G> option has been removed. Two regular expressions on the
2127 command line was considered too confusing; to simulate B<-G>'s functionality,
2128 you may use the new B<-x> option to pipe filenames from one invocation of
2133 The B<--binary> option has been removed.
2137 The B<--skipped> option has been removed.
2141 The B<--text> option has been removed.
2145 The B<--invert-file-match> option has been removed. Instead, you may
2146 use B<-v> with B<-g>.
2150 =head2 CHANGED OPTIONS
2156 The options that modify the regular expression's behavior (B<-i>, B<-w>,
2157 B<-Q>, and B<-v>) may now be used with B<-g>.
2161 =head2 ADDED OPTIONS
2167 B<--files-from> was added so that a user may submit a list of filenames as
2168 a list of files to search.
2172 B<-x> was added to tell ack to accept a list of filenames via standard input;
2173 this list is the list of filenames that will be used for the search.
2177 B<-s> was added to tell ack to suppress error messages about non-existent or
2182 B<--ignore-directory> and B<--noignore-directory> were added as aliases for
2183 B<--ignore-dir> and B<--noignore-dir> respectively.
2187 B<--ignore-file> was added so that users may specify patterns of files to
2188 ignore (ex. /.*~$/).
2192 B<--dump> was added to allow users to easily find out which options are
2197 B<--create-ackrc> was added so that users may create custom ackrc files based
2198 on the default settings loaded by ack, and so that users may easily view those
2203 B<--type-del> was added to selectively remove file type definitions.
2207 B<--ignore-ack-defaults> was added so that users may ignore ack's default
2208 options in favor of their own.
2212 B<--bar> was added so ack users may consult Admiral Ackbar.
2218 Andy Lester, C<< <andy at petdance.com> >>
2222 Please report any bugs or feature requests to the issues list at
2223 Github: L<https://github.com/petdance/ack2/issues>
2227 All enhancement requests MUST first be posted to the ack-users
2228 mailing list at L<http://groups.google.com/group/ack-users>. I
2229 will not consider a request without it first getting seen by other
2230 ack users. This includes requests for new filetypes.
2232 There is a list of enhancements I want to make to F<ack> in the ack
2233 issues list at Github: L<https://github.com/petdance/ack2/issues>
2235 Patches are always welcome, but patches with tests get the most
2240 Support for and information about F<ack> can be found at:
2244 =item * The ack homepage
2246 L<http://beyondgrep.com/>
2248 =item * The ack-users mailing list
2250 L<http://groups.google.com/group/ack-users>
2252 =item * The ack issues list at Github
2254 L<https://github.com/petdance/ack2/issues>
2256 =item * AnnoCPAN: Annotated CPAN documentation
2258 L<http://annocpan.org/dist/ack>
2260 =item * CPAN Ratings
2262 L<http://cpanratings.perl.org/d/ack>
2266 L<http://search.cpan.org/dist/ack>
2268 =item * Git source repository
2270 L<https://github.com/petdance/ack2>
2274 =head1 ACKNOWLEDGEMENTS
2276 How appropriate to have I<ack>nowledgements!
2278 Thanks to everyone who has contributed to ack in any way, including
2283 RaE<uacute>l GundE<iacute>n,
2289 RaE<aacute>l GundE<aacute>n,
2325 Eric Van Dewoestine,
2334 Christopher J. Madsen,
2346 GE<aacute>bor SzabE<oacute>,
2349 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
2353 Mark Leighton Fisher,
2359 Nilson Santos F. Jr,
2364 Ask BjE<oslash>rn Hansen,
2368 Slaven ReziE<0x107>,
2378 =head1 COPYRIGHT & LICENSE
2380 Copyright 2005-2015 Andy Lester.
2382 This program is free software; you can redistribute it and/or modify
2383 it under the terms of the Artistic License v2.0.
2385 See http://www.perlfoundation.org/artistic_license_2_0 or the LICENSE.md
2386 file that comes with the ack distribution.
2398 $VERSION = '2.15_01';
2399 $COPYRIGHT = 'Copyright 2005-2015 Andy Lester.';
2414 our $is_filter_mode;
2415 our $output_to_pipe;
2421 use File
::Spec
1.00015 ();
2424 # These have to be checked before any filehandle diddling.
2425 $output_to_pipe = not -t
*STDOUT
;
2426 $is_filter_mode = -p STDIN
;
2428 $is_cygwin = ($^O eq 'cygwin');
2429 $is_windows = ($^O eq 'MSWin32');
2430 $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File
::Spec-
>catfile( '', '' ) );
2435 sub remove_dir_sep
{
2437 $path =~ s/[$dir_sep_chars]$//;
2445 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2450 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2454 require File
::Basename
;
2455 return File
::Basename
::basename
( $0 );
2460 sub filetypes_supported
{
2461 return keys %mappings;
2465 my $y = q{_ /|,\\'!.x',=(www)=, U };
2466 $y =~ tr/,x!w/\nOo_/;
2471 my $y = _get_thpppt
();
2472 App
::Ack
::print( "$y ack $_[0]!\n" );
2480 3~!I#7#I"7#I!?!+!="+"="+!:!
2481 2?#I!7!I!?#I!7!I"+"=%+"=#
2482 1?"+!?*+!=#~"=!+#?"="+!
2483 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2484 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2486 ,,!?%I"?(+$=$~!=#:"~$:!~!
2487 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2488 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2489 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2490 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2491 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2492 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2493 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2494 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2495 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2496 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2497 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2498 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2499 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2500 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2501 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2502 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2503 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2504 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2505 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2506 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2507 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2508 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2509 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2510 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2511 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2512 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2513 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2514 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2515 7+:!,!~#,"=!7'I!?#I"7/+!7+
2516 77I!+!7!?!7!I"71+!7,
2519 return App
::Ack
::__pic
($x);
2525 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2526 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2527 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2533 4.! $\! /M!~!.!8! +.!M# 4
2534 0,!.! (\! .~!M!N! ,+!I!.!M!.! 3
2535 /?!O!.!M!:! '\! .O!.! +~!Z!=!N!.! 4
2536 ..! !D!Z!.!Z!.! '\! 9=!M".! 6
2537 /.! !.!~!M".! '\! 8~! 9
2539 4.! &:!M! !N"M# !M"N!M! #D!M&=! =
2540 :M!7!M#:! !~!M!7!,!$!M!:! #.! !O!N!.!M!:!M# ;
2541 8Z!M"~!N!$!D!.!N!?! !I!N!.! (?!M! !M!,!D!M".! 9
2542 (?!Z!M!N!:! )=!M!O!8!.!M!+!M! !M!,! !O!M! +,!M!.!M!~!Z!N!M!:! &:!~! 0
2543 &8!7!.!~!M"D!M!,! &M!?!=!8! !M!,!O! !M!+! !+!O!.!M! $M#~! !.!8!M!Z!.!M! !O!M"Z! %:!~!M!Z!M!Z!.! +
2544 &:!M!7!,! *M!.!Z!M! !8"M!.!M!~! !.!M!.!=! #~!8!.!M! !7!M! "N!Z#I! !D!M!,!M!.! $."M!,! !M!.! *
2545 2$!O! "N! !.!M!I! !7" "M! "+!O! !~!M! !d!O!.!7!I!M!.! !.!O!=!M!.! !M",!M!.! %.!$!O!D! +
2546 1~!O! "M!+! !8!$! "M! "?!O! %Z!8!D!M!?!8!I!O!7!M! #M!.!M! "M",!M! 4
2547 07!~! ".!8! !.!M! "I!+! !.!M! &Z!D!.!7!=!M! !:!.!M! #:!8"+! !.!+!8! !8! 3
2548 /~!M! #N! !~!M!$! !.!M! !.!M" &~!M! "~!M!O! "D! $M! !8! "M!,!M!+!D!.! 1
2549 #.! #?!M!N!.! #~!O! $M!.!7!$! "?" !?!~!M! '7!8!?!M!.!+!M"O! $?"$!D! !.!O! !$!7!I!.! 0
2550 $,!M!:!O!?! ".! !?!=! $=!:!O! !M! "M! !M! !+!$! (.! +.!M! !M!.! !8! !+"Z!~! $:!M!$! !.! '
2551 #.!8!.!I!$! $7!I! %M" !=!M! !~!M!D! "7!I! .I!O! %?!=!,!D! !,!M! !D!~!8!~! %D!M! (
2552 #.!M"?! $=!O! %=!N! "8!.! !Z!M! #M!~! (M!:! #.!M" &O! !M!.! !?!,! !8!.!N!~! $8!N!M!,!.! %
2553 *$!O! &M!,! "O! !.!M!.! #M! (~!M( &O!.! !7! "M! !.!M!.!M!,! #.!M! !M! &
2554 )=!8!.! $.!M!O!.! "$!.!I!N! !I!M# (7!M(I! %D"Z!M! "=!I! "M! !M!:! #~!D! '
2555 )D! &8!N!:! ".!O! !M!="M! "M! (7!M) %." !M!D!."M!.! !$!=! !M!,! +
2556 (M! &+!.!M! #Z!7!O!M!.!~!8! +,!M#D!?!M#D! #.!Z!M#,!Z!?! !~!N! "N!.! !M! +
2557 'D!:! %$!D! !?! #M!Z! !8!.! !M"?!7!?!7! '+!I!D! !?!O!:!M!:! ":!M!:! !M!7".!M! "8!+! !:!D! !.!M! *
2558 %.!O!:! $.!O!+! !D!.! #M! "M!.!+!N!I!Z! "7!M!N!M!N!?!I!7!Z!=!M'D"~! #M!.!8!$! !:! !.!M! "N!?! !,!O! )
2559 !.!?!M!:!M!I! %8!,! "M!.! #M! "N! !M!.! !M!.! !+!~! !.!M!.! ':!M! $M! $M!Z!$! !M!.! "D! "M! "?!M! (
2560 !7!8! !+!I! ".! "$!=! ":!$! "+! !M!.! !O! !M!I!M".! !=!~! ",!O! '=!M! $$!,! #N!:! ":!8!.! !D!~! !,!M!.! !:!M!.! &
2561 !:!,!.! &Z" #D! !.!8!."M!.! !8!?!Z!M!.!M! #Z!~! !?!M!Z!.! %~!O!.!8!$!N!8!O!I!:!~! !+! #M!.! !.!M!.! !+!M! ".!~!M!+! $
2562 !.! 'D!I! #?!M!.!M!,! !.!Z! !.!8! #M&O!I!?! (~!I!M"." !M!Z!.! !M!N!.! "+!$!.! "M!.! !M!?!.! "8!M! $
2563 (O!8! $M! !M!.! ".!:! !+!=! #M! #.!M! !+" *$!M":!.! !M!~! "M!7! #M! #7!Z! "M"$!M!.! !.! #
2564 '$!Z! #.!7!+!M! $.!,! !+!:! #N! #.!M!.!+!M! +D!M! #=!N! ":!O! #=!M! #Z!D! $M!I! %
2565 $,! ".! $.!M" %$!.! !?!~! "+!7!." !.!M!,! !M! *,!N!M!.$M!?! "D!,! #M!.! #N! +
2566 ,M!Z! &M! "I!,! "M! %I!M! !?!=!.! (Z!8!M! $:!M!.! !,!M! $D! #.!M!.! )
2567 +8!O! &.!8! "I!,! !~!M! &N!M! !M!D! '?!N!O!." $?!7! "?!~! #M!.! #I!D!.! (
2568 3M!,! "N!.! !D" &.!+!M!.! !M":!.":!M!7!M!D! 'M!.! "M!.! "M!,! $I! )
2569 3I! #M! "M!,! !:! &.!M" ".!,! !.!$!M!I! #.! !:! !.!M!?! "N!+! ".! /
2570 1M!,! #.!M!8!M!=!.! +~!N"O!Z"~! *+!M!.! "M! 2
2571 0.!M! &M!.! 8:! %.!M!Z! "M!=! *O!,! %
2572 0?!$! &N! )." .,! %."M! ":!M!.! 0
2573 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0
2575 return App
::Ack
::__pic
($x);
2579 my($compressed) = @_;
2580 $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2581 App
::Ack
::print( $compressed );
2587 my $help_arg = shift || 0;
2589 return show_help_types
() if $help_arg =~ /^types?/;
2591 App
::Ack
::print( <<"END_OF_HELP" );
2592 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2594 Search for PATTERN in each source file in the tree from the current
2595 directory on down. If any files or directories are specified, then
2596 only those files and directories are checked. ack may also search
2597 STDIN, but only if no file or directory arguments are specified,
2598 or if one of them is "-".
2600 Default switches may be specified in ACK_OPTIONS environment variable or
2601 an .ackrc file. If you want no dependency on the environment, turn it
2604 Example: ack -i select
2607 -i, --ignore-case Ignore case distinctions in PATTERN
2608 --[no]smart-case Ignore case distinctions in PATTERN,
2609 only if PATTERN contains no upper case.
2610 Ignored if -i is specified
2611 -v, --invert-match Invert match: select non-matching lines
2612 -w, --word-regexp Force PATTERN to match only whole words
2613 -Q, --literal Quote all metacharacters; PATTERN is literal
2616 --lines=NUM Only print line(s) NUM of each file
2617 -l, --files-with-matches Only print filenames containing matches
2618 -L, --files-without-matches Only print filenames with no matches
2619 --output=expr Output the evaluation of expr for each line
2620 (turns off text highlighting)
2621 -o Show only the part of a line matching PATTERN
2622 Same as --output='\$&'
2623 --passthru Print all lines, whether matching or not
2624 --match PATTERN Specify PATTERN explicitly.
2625 -m, --max-count=NUM Stop searching in each file after NUM matches
2626 -1 Stop searching after one match of any kind
2627 -H, --with-filename Print the filename for each match (default:
2628 on unless explicitly searching a single file)
2629 -h, --no-filename Suppress the prefixing filename on output
2630 -c, --count Show number of lines matching per file
2631 --[no]column Show the column number of the first match
2633 -A NUM, --after-context=NUM Print NUM lines of trailing context after
2635 -B NUM, --before-context=NUM Print NUM lines of leading context before
2637 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2639 --print0 Print null byte as separator between filenames,
2640 only works with -f, -g, -l, -L or -c.
2642 -s Suppress error messages about nonexistent or
2647 --pager=COMMAND Pipes all ack output through COMMAND. For
2648 example, --pager="less -R". Ignored if output
2650 --nopager Do not send output through a pager. Cancels
2651 any setting in ~/.ackrc, ACK_PAGER or
2653 --[no]heading Print a filename heading above each file's
2654 results. (default: on when used interactively)
2655 --[no]break Print a break between results from different
2656 files. (default: on when used interactively)
2657 --group Same as --heading --break
2658 --nogroup Same as --noheading --nobreak
2659 --[no]color Highlight the matching text (default: on unless
2660 output is redirected, or on Windows)
2661 --[no]colour Same as --[no]color
2662 --color-filename=COLOR
2664 --color-lineno=COLOR Set the color for filenames, matches, and line
2666 --flush Flush output immediately, even when ack is used
2667 non-interactively (when output goes to a pipe or
2672 -f Only print the files selected, without
2673 searching. The PATTERN must not be specified.
2674 -g Same as -f, but only select files matching
2676 --sort-files Sort the found files lexically.
2677 --show-types Show which types each file has.
2678 --files-from=FILE Read the list of files to search from FILE.
2679 -x Read the list of files to search from STDIN.
2681 File inclusion/exclusion:
2682 --[no]ignore-dir=name Add/remove directory from list of ignored dirs
2683 --[no]ignore-directory=name Synonym for ignore-dir
2684 --ignore-file=filter Add filter for ignoring files
2685 -r, -R, --recurse Recurse into subdirectories (default: on)
2686 -n, --no-recurse No descending into subdirectories
2687 --[no]follow Follow symlinks. Default is off.
2688 -k, --known-types Include only files of types that ack recognizes.
2690 --type=X Include only X files, where X is a recognized
2692 --type=noX Exclude X files.
2693 See "ack --help-types" for supported filetypes.
2695 File type specification:
2696 --type-set TYPE:FILTER:FILTERARGS
2697 Files with the given FILTERARGS applied to the
2698 given FILTER are recognized as being of type
2699 TYPE. This replaces an existing definition for
2701 --type-add TYPE:FILTER:FILTERARGS
2702 Files with the given FILTERARGS applied to the
2703 given FILTER are recognized as being type TYPE.
2704 --type-del TYPE Removes all filters associated with TYPE.
2708 --[no]env Ignore environment variables and global ackrc
2709 files. --env is legal but redundant.
2710 --ackrc=filename Specify an ackrc file to use
2711 --ignore-ack-defaults Ignore default definitions included with ack.
2712 --create-ackrc Outputs a default ackrc for your customization
2714 --help, -? This help
2715 --help-types Display all known types
2716 --dump Dump information on which options are loaded
2718 --[no]filter Force ack to treat standard input as a pipe
2719 (--filter) or tty (--nofilter)
2721 --version Display version & copyright
2722 --thpppt Bill the Cat
2723 --bar The warning admiral
2724 --cathy Chocolate! Chocolate! Chocolate!
2726 Exit status is 0 if match, 1 if no match.
2728 ack's home page is at http://beyondgrep.com/
2730 The full ack manual is available by running "ack --man".
2732 This is version $VERSION of ack. Run "ack --version" for full version info.
2740 sub show_help_types
{
2741 App
::Ack
::print( <<'END_OF_HELP' );
2742 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2744 The following is the list of filetypes supported by ack. You can
2745 specify a file type with the --type=TYPE format, or the --TYPE
2746 format. For example, both --type=perl and --perl work.
2748 Note that some extensions may appear in multiple types. For example,
2749 .pod files are both Perl and Parrot.
2753 my @types = filetypes_supported
();
2756 $maxlen = length if $maxlen < length;
2758 for my $type ( sort @types ) {
2759 next if $type =~ /^-/; # Stuff to not show
2760 my $ext_list = $mappings{$type};
2762 if ( ref $ext_list ) {
2763 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
2765 App
::Ack
::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2774 Pod
::Usage
::pod2usage
({
2775 -input
=> $App::Ack
::orig_program_name
,
2784 sub get_version_statement
{
2787 my $copyright = get_copyright
();
2788 my $this_perl = $Config::Config
{perlpath
};
2790 my $ext = $Config::Config
{_exe
};
2791 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2793 my $ver = sprintf( '%vd', $^V );
2795 return <<"END_OF_VERSION";
2797 Running under Perl $ver at $this_perl
2801 This program is free software. You may modify or distribute it
2802 under the terms of the Artistic License v2.0.
2807 sub print_version_statement
{
2808 App
::Ack
::print( get_version_statement
() );
2819 # print*() subs added in order to make it easy for a third party
2820 # module (such as App::Wack) to redefine the display methods
2821 # and show the results in a different way.
2822 sub print { print {$fh} @_; return; }
2823 sub print_first_filename
{ App
::Ack
::print( $_[0], "\n" ); return; }
2824 sub print_blank_line
{ App
::Ack
::print( "\n" ); return; }
2825 sub print_separator
{ App
::Ack
::print( "--\n" ); return; }
2826 sub print_filename
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2827 sub print_line_no
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2828 sub print_column_no
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2830 my $filename = shift;
2831 my $nmatches = shift;
2834 my $show_filename = shift;
2836 if ($show_filename) {
2837 App
::Ack
::print( $filename );
2838 App
::Ack
::print( ':', $nmatches ) if $count;
2841 App
::Ack
::print( $nmatches ) if $count;
2843 App
::Ack
::print( $ors );
2849 my $filename = shift;
2851 my $show_filename = shift;
2853 if ($show_filename) {
2854 App
::Ack
::print( $filename, ':0', $ors );
2857 App
::Ack
::print( '0', $ors );
2864 my $command = shift;
2866 return if App
::Ack
::output_to_pipe
();
2869 if ( not open( $pager, '|-', $command ) ) {
2870 App
::Ack
::die( qq{Unable to pipe to pager "$command": $!} );
2878 sub output_to_pipe
{
2879 return $output_to_pipe;
2884 my $nmatches = shift;
2886 my $rc = $nmatches ? 0 : 1;
2892 1; # End of App::Ack
2893 package App
::Ack
::Resource
;
2903 Carp
::confess
( 'Must be overloaded' );
2932 sub needs_line_scan
{
2957 package App
::Ack
::Resources
;
2964 sub _generate_error_handler
{
2967 if ( $opt->{dont_report_bad_filenames
} ) {
2970 # XXX restricting to specific error messages for now; I would
2971 # prefer a different way of doing this
2972 if ( $msg =~ /Permission denied/ ) {
2975 App
::Ack
::warn( $msg );
2981 App
::Ack
::warn( $msg );
2992 my $self = bless {}, $class;
2994 my $file_filter = undef;
2995 my $descend_filter = $opt->{descend_filter
};
2998 $descend_filter = sub {
3004 File
::Next
::files
( {
3005 file_filter
=> $opt->{file_filter
},
3006 descend_filter
=> $descend_filter,
3007 error_handler
=> _generate_error_handler
($opt),
3008 warning_handler
=> sub {},
3009 sort_files
=> $opt->{sort_files
},
3010 follow_symlinks
=> $opt->{follow
},
3023 File
::Next
::from_file
( {
3024 error_handler
=> _generate_error_handler
($opt),
3025 warning_handler
=> _generate_error_handler
($opt),
3026 sort_files
=> $opt->{sort_files
},
3027 }, $file ) or return undef;
3034 # This is for reading input lines from STDIN, not the list of files from STDIN
3039 my $self = bless {}, $class;
3041 my $has_been_called = 0;
3043 $self->{iter
} = sub {
3044 if ( !$has_been_called ) {
3045 $has_been_called = 1;
3057 my $file = $self->{iter
}->() or return;
3059 return App
::Ack
::Resource
::Basic-
>new( $file );
3063 package App
::Ack
::Resource
::Basic
;
3073 our @ISA = 'App::Ack::Resource';
3080 my $filename = shift;
3083 filename
=> $filename,
3088 if ( $self->{filename
} eq '-' ) {
3089 $self->{fh
} = *STDIN
;
3090 $self->{opened
} = 1;
3098 return $_[0]->{filename
};
3104 # XXX definedness? pre-populate the slot with an undef?
3105 unless ( exists $self->{basename
} ) {
3106 $self->{basename
} = (File
::Spec-
>splitpath($self->name))[2];
3109 return $self->{basename
};
3113 sub needs_line_scan
{
3117 return 1 if $opt->{v
};
3119 my $size = -s
$self->{fh
};
3123 elsif ( $size > 100_000 ) {
3128 my $rc = sysread( $self->{fh
}, $buffer, $size );
3129 if ( !defined($rc) && $App::Ack
::report_bad_filenames
) {
3130 App
::Ack
::warn( "$self->{filename}: $!" );
3133 return 0 unless $rc && ( $rc == $size );
3135 my $regex = $opt->{regex
};
3136 return $buffer =~ /$regex/m;
3143 # return if we haven't opened the file yet
3144 if ( !defined($self->{fh
}) ) {
3148 if( !seek( $self->{fh
}, 0, 0 ) && $App::Ack
::report_bad_filenames
) {
3149 App
::Ack
::warn( "$self->{filename}: $!" );
3159 # return if we haven't opened the file yet
3160 if ( !defined($self->{fh
}) ) {
3164 if ( !close($self->{fh
}) && $App::Ack
::report_bad_filenames
) {
3165 App
::Ack
::warn( $self->name() . ": $!" );
3168 $self->{opened
} = 0;
3177 return __PACKAGE__-
>new($self->name);
3183 my $fh = $self->open();
3185 if ( !exists $self->{firstliney
} ) {
3187 my $rc = sysread( $fh, $buffer, 250 );
3188 unless($rc) { # XXX handle this better?
3191 $buffer =~ s/[\r\n].*//s;
3192 $self->{firstliney
} = $buffer;
3198 return $self->{firstliney
};
3204 return $self->{fh
} if $self->{opened
};
3206 if ( ! open $self->{fh
}, '<', $self->{filename
} ) {
3210 $self->{opened
} = 1;
3216 package App
::Ack
::ConfigDefault
;
3224 return split( /\n/, _options_block
() );
3229 return grep { /./ && !/^#/ } options
();
3233 sub _options_block
{
3234 my $lines = <<'HERE';
3235 # This is the default ackrc for ack version ==VERSION==.
3237 # There are four different ways to match
3239 # is: Match the filename exactly
3241 # ext: Match the extension of the filename exactly
3243 # match: Match the filename against a Perl regular expression
3245 # firstlinematch: Match the first 250 characters of the first line
3246 # of text against a Perl regular expression. This is only for
3247 # the --type-add option.
3250 ### Directories to ignore
3253 # http://bazaar.canonical.com/
3254 --ignore-directory=is:.bzr
3257 # http://freecode.com/projects/codeville
3258 --ignore-directory=is:.cdv
3260 # Interface Builder (Xcode)
3261 # http://en.wikipedia.org/wiki/Interface_Builder
3262 --ignore-directory=is:~.dep
3263 --ignore-directory=is:~.dot
3264 --ignore-directory=is:~.nib
3265 --ignore-directory=is:~.plst
3268 # http://git-scm.com/
3269 --ignore-directory=is:.git
3272 # http://mercurial.selenic.com/
3273 --ignore-directory=is:.hg
3276 # http://directory.fsf.org/wiki/Quilt
3277 --ignore-directory=is:.pc
3280 # http://subversion.tigris.org/
3281 --ignore-directory=is:.svn
3284 # http://www.monotone.ca/
3285 --ignore-directory=is:_MTN
3288 # http://savannah.nongnu.org/projects/cvs
3289 --ignore-directory=is:CVS
3292 # http://www.gnu.org/software/rcs/
3293 --ignore-directory=is:RCS
3296 # http://en.wikipedia.org/wiki/Source_Code_Control_System
3297 --ignore-directory=is:SCCS
3301 --ignore-directory=is:_darcs
3304 --ignore-directory=is:_sgbak
3307 # http://www.gnu.org/software/autoconf/
3308 --ignore-directory=is:autom4te.cache
3310 # Perl module building
3311 --ignore-directory=is:blib
3312 --ignore-directory=is:_build
3314 # Perl Devel::Cover module's output directory
3315 # https://metacpan.org/release/Devel-Cover
3316 --ignore-directory=is:cover_db
3318 # Node modules created by npm
3319 --ignore-directory=is:node_modules
3322 # http://www.cmake.org/
3323 --ignore-directory=is:CMakeFiles
3325 # Eclipse workspace folder
3326 # http://eclipse.org/
3327 --ignore-directory=is:.metadata
3329 # Cabal (Haskell) sandboxes
3330 # http://www.haskell.org/cabal/users-guide/installing-packages.html
3331 --ignore-directory=is:.cabal-sandbox
3336 --ignore-file=ext:bak
3337 --ignore-file=match:/~$/
3340 --ignore-file=match:/^#.+#$/
3342 # vi/vim swap files http://vim.org/
3343 --ignore-file=match:/[._].*\.swp$/
3346 --ignore-file=match:/core\.\d+$/
3348 # minified Javascript
3349 --ignore-file=match:/[.-]min[.]js$/
3350 --ignore-file=match:/[.]js[.]min$/
3353 --ignore-file=match:/[.]min[.]css$/
3354 --ignore-file=match:/[.]css[.]min$/
3356 # JS and CSS source maps
3357 --ignore-file=match:/[.]js[.]map$/
3358 --ignore-file=match:/[.]css[.]map$/
3360 # PDFs, because they pass Perl's -T detection
3361 --ignore-file=ext:pdf
3363 # Common graphics, just as an optimization
3364 --ignore-file=ext:gif,jpg,jpeg,png
3367 ### Filetypes defined
3371 --type-add=perl:ext:pl,pm,pod,t,psgi
3372 --type-add=perl:firstlinematch:/^#!.*\bperl/
3375 --type-add=perltest:ext:t
3378 # http://www.gnu.org/s/make/
3379 --type-add=make:ext:mk
3380 --type-add=make:ext:mak
3381 --type-add=make:is:makefile
3382 --type-add=make:is:Makefile
3383 --type-add=make:is:Makefile.Debug
3384 --type-add=make:is:Makefile.Release
3387 # http://rake.rubyforge.org/
3388 --type-add=rake:is:Rakefile
3391 # http://www.cmake.org/
3392 --type-add=cmake:is:CMakeLists.txt
3393 --type-add=cmake:ext:cmake
3396 --type-add=actionscript:ext:as,mxml
3399 # http://www.adaic.org/
3400 --type-add=ada:ext:ada,adb,ads
3403 # http://msdn.microsoft.com/en-us/library/aa286483.aspx
3404 --type-add=asp:ext:asp
3407 # http://www.asp.net/
3408 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
3411 --type-add=asm:ext:asm,s
3414 --type-add=batch:ext:bat,cmd
3417 # http://en.wikipedia.org/wiki/ColdFusion
3418 --type-add=cfmx:ext:cfc,cfm,cfml
3421 # http://clojure.org/
3422 --type-add=clojure:ext:clj
3425 # .xs are Perl C files
3426 --type-add=cc:ext:c,h,xs
3432 # http://coffeescript.org/
3433 --type-add=coffeescript:ext:coffee
3436 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
3439 --type-add=hpp:ext:hpp,hh,h,hxx
3442 --type-add=csharp:ext:cs
3445 # http://www.w3.org/Style/CSS/
3446 --type-add=css:ext:css
3449 # http://www.dartlang.org/
3450 --type-add=dart:ext:dart
3453 # http://en.wikipedia.org/wiki/Embarcadero_Delphi
3454 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
3457 # http://elixir-lang.org/
3458 --type-add=elixir:ext:ex,exs
3461 # http://www.gnu.org/software/emacs
3462 --type-add=elisp:ext:el
3465 # http://www.erlang.org/
3466 --type-add=erlang:ext:erl,hrl
3469 # http://en.wikipedia.org/wiki/Fortran
3470 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
3473 # http://golang.org/
3474 --type-add=go:ext:go
3477 # http://groovy.codehaus.org/
3478 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
3481 # http://www.haskell.org/
3482 --type-add=haskell:ext:hs,lhs
3485 --type-add=html:ext:htm,html
3488 # http://jade-lang.com/
3489 --type-add=jade:ext:jade
3492 # http://www.oracle.com/technetwork/java/index.html
3493 --type-add=java:ext:java,properties
3496 --type-add=js:ext:js
3499 # http://www.oracle.com/technetwork/java/javaee/jsp/index.html
3500 --type-add=jsp:ext:jsp,jspx,jhtm,jhtml
3503 # http://www.json.org/
3504 --type-add=json:ext:json
3507 # http://www.lesscss.org/
3508 --type-add=less:ext:less
3511 # http://common-lisp.net/
3512 --type-add=lisp:ext:lisp,lsp
3515 # http://www.lua.org/
3516 --type-add=lua:ext:lua
3517 --type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
3520 --type-add=objc:ext:m,h
3523 --type-add=objcpp:ext:mm,h
3526 # http://caml.inria.fr/
3527 --type-add=ocaml:ext:ml,mli
3530 # http://en.wikipedia.org/wiki/MATLAB
3531 --type-add=matlab:ext:m
3534 # http://www.parrot.org/
3535 --type-add=parrot:ext:pir,pasm,pmc,ops,pod,pg,tg
3538 # http://www.php.net/
3539 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
3540 --type-add=php:firstlinematch:/^#!.*\bphp/
3544 --type-add=plone:ext:pt,cpt,metadata,cpy,py
3547 # http://www.python.org/
3548 --type-add=python:ext:py
3549 --type-add=python:firstlinematch:/^#!.*\bpython/
3552 # http://www.r-project.org/
3556 # http://docutils.sourceforge.net/rst.html
3557 --type-add=rst:ext:rst
3560 # http://www.ruby-lang.org/
3561 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
3562 --type-add=ruby:is:Rakefile
3563 --type-add=ruby:firstlinematch:/^#!.*\bruby/
3566 # http://www.rust-lang.org/
3567 --type-add=rust:ext:rs
3570 # http://sass-lang.com
3571 --type-add=sass:ext:sass,scss
3574 # http://www.scala-lang.org/
3575 --type-add=scala:ext:scala
3578 # http://groups.csail.mit.edu/mac/projects/scheme/
3579 --type-add=scheme:ext:scm,ss
3582 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
3583 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
3586 # http://www.smalltalk.org/
3587 --type-add=smalltalk:ext:st
3590 # http://www.smarty.net/
3591 --type-add=smarty:ext:tpl
3594 # http://www.iso.org/iso/catalogue_detail.htm?csnumber=45498
3595 --type-add=sql:ext:sql,ctl
3598 # http://learnboost.github.io/stylus/
3599 --type-add=stylus:ext:styl
3602 # http://www.tcl.tk/
3603 --type-add=tcl:ext:tcl,itcl,itk
3606 # http://www.latex-project.org/
3607 --type-add=tex:ext:tex,cls,sty
3609 # Template Toolkit (Perl)
3610 # http://template-toolkit.org/
3611 --type-add=tt:ext:tt,tt2,ttml
3614 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
3617 --type-add=verilog:ext:v,vh,sv
3620 # http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
3621 --type-add=vhdl:ext:vhd,vhdl
3624 # http://www.vim.org/
3625 --type-add=vim:ext:vim
3628 # http://www.w3.org/TR/REC-xml/
3629 --type-add=xml:ext:xml,dtd,xsl,xslt,ent
3630 --type-add=xml:firstlinematch:/<[?]xml/
3634 --type-add=yaml:ext:yaml,yml
3636 $lines =~ s/==VERSION==/$App::Ack::VERSION/sm;
3642 package App
::Ack
::ConfigFinder
;
3649 use File
::Spec
3.00;
3651 use if ($^O eq 'MSWin32'), 'Win32';
3657 return bless {}, $class;
3661 sub _remove_redundancies
{
3665 foreach my $config (@configs) {
3666 my $key = $config->{path
};
3667 if ( not $App::Ack
::is_windows
) {
3668 # On Unix, uniquify on inode.
3669 my ($dev, $inode) = (stat $key)[0, 1];
3670 $key = "$dev:$inode" if defined $dev;
3672 undef $config if $seen{$key}++;
3674 return grep { defined } @configs;
3678 sub _check_for_ackrc
{
3679 return unless defined $_[0];
3681 my @files = grep { -f
}
3682 map { File
::Spec-
>catfile(@_, $_) }
3685 die File
::Spec-
>catdir(@_) . " contains both .ackrc and _ackrc.\n" .
3686 "Please remove one of those files.\n"
3689 return wantarray ? @files : $files[0];
3690 } # end _check_for_ackrc
3694 sub find_config_files
{
3697 if ( $App::Ack
::is_windows
) {
3698 push @config_files, map { +{ path
=> File
::Spec-
>catfile($_, 'ackrc') } } (
3699 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3700 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3704 push @config_files, { path
=> '/etc/ackrc' };
3708 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3709 push @config_files, { path
=> $ENV{'ACKRC'} };
3712 push @config_files, map { +{ path
=> $_ } } _check_for_ackrc
($ENV{'HOME'});
3715 # XXX This should go through some untainted cwd-fetching function, and not get untainted inline like this.
3716 my $cwd = Cwd
::getcwd
();
3719 my @dirs = File
::Spec-
>splitdir( $cwd );
3721 my $ackrc = _check_for_ackrc
(@dirs);
3722 if(defined $ackrc) {
3723 push @config_files, { project
=> 1, path
=> $ackrc };
3729 # We only test for existence here, so if the file is deleted out from under us, this will fail later.
3730 return _remove_redundancies
( @config_files );
3738 return unless defined $file && -e
$file;
3742 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
3743 while ( my $line = <$fh> ) {
3748 next if $line eq '';
3749 next if $line =~ /^\s*#/;
3751 push( @lines, $line );
3753 close $fh or App
::Ack
::die( "Unable to close $file: $!" );
3759 package App
::Ack
::ConfigLoader
;
3765 use Getopt
::Long
2.35 ();
3766 use Text
::ParseWords
3.1 ();
3769 my @INVALID_COMBINATIONS;
3772 my @context = qw( -A -B -C --after-context --before-context --context );
3773 my @pretty = qw( --heading --group --break );
3774 my @filename = qw( -h -H --with-filename --no-filename );
3776 @INVALID_COMBINATIONS = (
3778 [qw(-l)] => [@context, @pretty, @filename, qw(-L -o --passthru --output --max-count --column -f -g --show-types)],
3779 [qw(-L)] => [@context, @pretty, @filename, qw(-l -o --passthru --output --max-count --column -f -g --show-types -c --count)],
3780 [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)],
3781 [qw(-o)] => [@context, qw(--output -c --count --column --column -f --show-types)],
3782 [qw(--passthru)] => [@context, qw(--output --column -m --max-count -1 -c --count -f -g)],
3783 [qw(--output)] => [@context, qw(-c --count -f -g)],
3784 [qw(--match)] => [qw(-f -g)],
3785 [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
3786 [qw(-h --no-filename)] => [qw(-H --with-filename -f -g --group --heading)],
3787 [qw(-H --with-filename)] => [qw(-h --no-filename -f -g)],
3788 [qw(-c --count)] => [@context, @pretty, qw(--column -f -g)],
3789 [qw(--column)] => [qw(-f -g)],
3790 [@context] => [qw(-f -g)],
3791 [qw(-f)] => [qw(-g), @pretty],
3792 [qw(-g)] => [qw(-f), @pretty],
3796 sub _generate_ignore_dir
{
3797 my ( $option_name, $opt ) = @_;
3799 my $is_inverted = $option_name =~ /^--no/;
3802 my ( undef, $dir ) = @_;
3804 $dir = App
::Ack
::remove_dir_sep
( $dir );
3805 if ( $dir !~ /:/ ) {
3806 $dir = 'is:' . $dir;
3809 my ( $filter_type, $args ) = split /:/, $dir, 2;
3811 if ( $filter_type eq 'firstlinematch' ) {
3812 Carp
::croak
( qq{Invalid filter specification "$filter_type" for option '$option_name'} );
3815 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args));
3818 my $previous_inversion_matches = $opt->{idirs
} && !($is_inverted xor $opt->{idirs
}[-1]->is_inverted());
3820 if ( $previous_inversion_matches ) {
3821 $collection = $opt->{idirs
}[-1];
3823 if ( $is_inverted ) {
3824 # XXX this relies on invert of an inverted filter
3825 # to return the original
3826 $collection = $collection->invert()
3830 $collection = App
::Ack
::Filter
::Collection-
>new();
3832 if ( $is_inverted ) {
3833 push @{ $opt->{idirs
} }, $collection->invert();
3836 push @{ $opt->{idirs
} }, $collection;
3840 $collection->add($filter);
3842 if ( $filter_type eq 'is' ) {
3843 $collection->add(App
::Ack
::Filter
::IsPath-
>new($args));
3848 sub process_filter_spec
{
3851 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3852 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3854 return ( $type_name,
3855 App
::Ack
::Filter-
>create_filter($ext_type, split(/,/, $arguments)) );
3857 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3858 my ( $type_name, $extensions ) = ( $1, $2 );
3860 my @extensions = split(/,/, $extensions);
3861 foreach my $extension ( @extensions ) {
3862 $extension =~ s/^[.]//;
3865 return ( $type_name, App
::Ack
::Filter-
>create_filter('ext', @extensions) );
3868 Carp
::croak
"invalid filter specification '$spec'";
3873 sub uninvert_filter
{
3874 my ( $opt, @filters ) = @_;
3876 return unless defined $opt->{filters
} && @filters;
3878 # Loop through all the registered filters. If we hit one that
3879 # matches this extension and it's inverted, we need to delete it from
3881 for ( my $i = 0; $i < @{ $opt->{filters
} }; $i++ ) {
3882 my $opt_filter = @{ $opt->{filters
} }[$i];
3884 # XXX Do a real list comparison? This just checks string equivalence.
3885 if ( $opt_filter->is_inverted() && "$opt_filter->{filter}" eq "@filters" ) {
3886 splice @{ $opt->{filters
} }, $i, 1;
3893 sub process_filetypes
{
3894 my ( $opt, $arg_sources ) = @_;
3896 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3897 Getopt
::Long
::Configure
(
3902 my %additional_specs;
3904 my $add_spec = sub {
3905 my ( undef, $spec ) = @_;
3907 my ( $name, $filter ) = process_filter_spec
($spec);
3909 push @{ $App::Ack
::mappings
{$name} }, $filter;
3911 $additional_specs{$name . '!'} = sub {
3912 my ( undef, $value ) = @_;
3914 my @filters = @{ $App::Ack
::mappings
{$name} };
3916 @filters = map { $_->invert() } @filters;
3919 uninvert_filter
( $opt, @filters );
3922 push @{ $opt->{'filters'} }, @filters;
3926 my $set_spec = sub {
3927 my ( undef, $spec ) = @_;
3929 my ( $name, $filter ) = process_filter_spec
($spec);
3931 $App::Ack
::mappings
{$name} = [ $filter ];
3933 $additional_specs{$name . '!'} = sub {
3934 my ( undef, $value ) = @_;
3936 my @filters = @{ $App::Ack
::mappings
{$name} };
3938 @filters = map { $_->invert() } @filters;
3941 push @{ $opt->{'filters'} }, @filters;
3945 my $delete_spec = sub {
3946 my ( undef, $name ) = @_;
3948 delete $App::Ack
::mappings
{$name};
3949 delete $additional_specs{$name . '!'};
3952 my %type_arg_specs = (
3953 'type-add=s' => $add_spec,
3954 'type-set=s' => $set_spec,
3955 'type-del=s' => $delete_spec,
3958 foreach my $source (@{$arg_sources}) {
3959 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
3962 # $args are modified in place, so no need to munge $arg_sources
3963 local @ARGV = @{$args};
3964 Getopt
::Long
::GetOptions
(%type_arg_specs);
3968 ( undef, $source->{contents
} ) =
3969 Getopt
::Long
::GetOptionsFromString
($args, %type_arg_specs);
3973 $additional_specs{'k|known-types'} = sub {
3974 my ( undef, $value ) = @_;
3976 my @filters = map { @{$_} } values(%App::Ack
::mappings
);
3978 push @{ $opt->{'filters'} }, @filters;
3981 return \
%additional_specs;
3985 sub removed_option
{
3986 my ( $option, $explanation ) = @_;
3988 $explanation ||= '';
3990 warn "Option '$option' is not valid in ack 2\n$explanation";
3997 my ( $opt, $extra_specs ) = @_;
3999 my $dash_a_explanation = <<'EOT';
4000 This is because we now have -k/--known-types which makes it only select files
4001 of known types, rather than any text file (which is the behavior of ack 1.x).
4002 You may have options in a .ackrc, or in the ACKRC_OPTIONS environment variable.
4003 Try using the --dump flag.
4008 1 => sub { $opt->{1} = $opt->{m
} = 1 },
4009 'A|after-context=i' => \
$opt->{after_context
},
4010 'B|before-context=i'
4011 => \
$opt->{before_context
},
4012 'C|context:i' => sub { shift; my $val = shift; $opt->{before_context
} = $opt->{after_context
} = ($val || 2) },
4013 'a' => removed_option
('-a', $dash_a_explanation),
4014 'all' => removed_option
('--all', $dash_a_explanation),
4015 'break!' => \
$opt->{break},
4016 c
=> \
$opt->{count
},
4017 'color|colour!' => \
$opt->{color
},
4018 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
4019 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
4020 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
4021 'column!' => \
$opt->{column
},
4022 count
=> \
$opt->{count
},
4023 'create-ackrc' => sub { print "$_\n" for ( '--ignore-ack-defaults', App
::Ack
::ConfigDefault
::options
() ); exit; },
4025 my ( undef, $value ) = @_;
4028 $opt->{noenv_seen
} = 1;
4032 'files-from=s' => \
$opt->{files_from
},
4033 'filter!' => \
$App::Ack
::is_filter_mode
,
4034 flush
=> \
$opt->{flush
},
4035 'follow!' => \
$opt->{follow
},
4037 G
=> removed_option
('-G'),
4038 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
4039 'heading!' => \
$opt->{heading
},
4040 'h|no-filename' => \
$opt->{h
},
4041 'H|with-filename' => \
$opt->{H
},
4042 'i|ignore-case' => \
$opt->{i
},
4043 'ignore-directory|ignore-dir=s' => _generate_ignore_dir
('--ignore-dir', $opt),
4044 'ignore-file=s' => sub {
4045 my ( undef, $file ) = @_;
4047 my ( $filter_type, $args ) = split /:/, $file, 2;
4049 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args));
4051 if ( !$opt->{ifiles
} ) {
4052 $opt->{ifiles
} = App
::Ack
::Filter
::Collection-
>new();
4054 $opt->{ifiles
}->add($filter);
4056 'lines=s' => sub { shift; my $val = shift; push @{$opt->{lines
}}, $val },
4057 'l|files-with-matches'
4059 'L|files-without-matches'
4061 'm|max-count=i' => \
$opt->{m
},
4062 'match=s' => \
$opt->{regex
},
4063 'n|no-recurse' => \
$opt->{n
},
4064 o
=> sub { $opt->{output
} = '$&' },
4065 'output=s' => \
$opt->{output
},
4067 my ( undef, $value ) = @_;
4069 $opt->{pager
} = $value || $ENV{PAGER
};
4071 'noignore-directory|noignore-dir=s' => _generate_ignore_dir
('--noignore-dir', $opt),
4072 'nopager' => sub { $opt->{pager
} = undef },
4073 'passthru' => \
$opt->{passthru
},
4074 'print0' => \
$opt->{print0
},
4075 'Q|literal' => \
$opt->{Q
},
4076 'r|R|recurse' => sub { $opt->{n
} = 0 },
4077 's' => \
$opt->{dont_report_bad_filenames
},
4078 'show-types' => \
$opt->{show_types
},
4079 'smart-case!' => \
$opt->{smart_case
},
4080 'sort-files' => \
$opt->{sort_files
},
4082 my ( $getopt, $value ) = @_;
4085 if ( $value =~ s/^no// ) {
4089 my $callback = $extra_specs->{ $value . '!' };
4092 $callback->( $getopt, $cb_value );
4095 Carp
::croak
( "Unknown type '$value'" );
4098 'u' => removed_option
('-u'),
4099 'unrestricted' => removed_option
('--unrestricted'),
4100 'v|invert-match' => \
$opt->{v
},
4101 'w|word-regexp' => \
$opt->{w
},
4102 'x' => sub { $opt->{files_from
} = '-' },
4104 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
4105 'help|?:s' => sub { shift; App
::Ack
::show_help
(@_); exit; },
4106 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
4107 'man' => sub { App
::Ack
::show_man
(); exit; },
4108 $extra_specs ? %{$extra_specs} : (),
4114 my ( $opt, $extra_specs, $arg_sources ) = @_;
4116 # Start with default options, minus some annoying ones.
4117 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4118 Getopt
::Long
::Configure
(
4124 my $is_help_types_active;
4126 foreach my $source (@{$arg_sources}) {
4127 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4129 if ( $source_name eq 'ARGV' ) {
4130 $argv_source = $args;
4135 if ( $argv_source ) { # This *should* always be true, but you never know...
4136 my @copy = @{$argv_source};
4137 local @ARGV = @copy;
4139 Getopt
::Long
::Configure
('pass_through');
4141 Getopt
::Long
::GetOptions
(
4142 'help-types' => \
$is_help_types_active,
4145 Getopt
::Long
::Configure
('no_pass_through');
4148 my $arg_specs = get_arg_spec
($opt, $extra_specs);
4150 foreach my $source (@{$arg_sources}) {
4151 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4153 my $args_for_source = $arg_specs;
4155 if ( $source->{project
} ) {
4157 die "Options --output, --pager and --match are forbidden in project .ackrc files.\n";
4160 $args_for_source = { %$args_for_source,
4161 'output=s' => $illegal,
4162 'pager:s' => $illegal,
4163 'match=s' => $illegal,
4169 local @ARGV = @{$args};
4170 $ret = Getopt
::Long
::GetOptions
( %{$args_for_source} );
4174 ( $ret, $source->{contents
} ) =
4175 Getopt
::Long
::GetOptionsFromString
( $args, %{$args_for_source} );
4178 if ( !$is_help_types_active ) {
4179 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
4180 App
::Ack
::die( "Invalid option $where" );
4183 if ( $opt->{noenv_seen
} ) {
4184 App
::Ack
::die( "--noenv found in $source_name" );
4188 # XXX We need to check on a -- in the middle of a non-ARGV source
4194 sub should_dump_options
{
4195 my ( $sources ) = @_;
4197 foreach my $source (@{$sources}) {
4198 my ( $name, $options ) = @{$source}{qw
/name contents/};
4200 if($name eq 'ARGV') {
4202 local @ARGV = @{$options};
4203 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
4204 Getopt
::Long
::GetOptions
(
4207 @{$options} = @ARGV;
4215 sub explode_sources
{
4216 my ( $sources ) = @_;
4220 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
4223 my $arg_spec = get_arg_spec
(\
%opt);
4225 my $add_type = sub {
4226 my ( undef, $arg ) = @_;
4229 if ( $arg =~ /(\w+)=/) {
4230 $arg_spec->{$1} = sub {};
4233 ( $arg ) = split /:/, $arg;
4234 $arg_spec->{$arg} = sub {};
4238 my $del_type = sub {
4239 my ( undef, $arg ) = @_;
4241 delete $arg_spec->{$arg};
4244 foreach my $source (@{$sources}) {
4245 my ( $name, $options ) = @{$source}{qw
/name contents/};
4246 if ( ref($options) ne 'ARRAY' ) {
4247 $source->{contents
} = $options =
4248 [ Text
::ParseWords
::shellwords
($options) ];
4251 for my $j ( 0 .. @{$options}-1 ) {
4252 next unless $options->[$j] =~ /^-/;
4253 my @chunk = ( $options->[$j] );
4254 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
4258 local @ARGV = @chunk;
4259 Getopt
::Long
::GetOptions
(
4260 'type-add=s' => $add_type,
4261 'type-set=s' => $add_type,
4262 'type-del=s' => $del_type,
4264 Getopt
::Long
::GetOptions
( %{$arg_spec} );
4266 push @new_sources, {
4273 return \
@new_sources;
4280 my $first_a = $a->[0];
4281 my $first_b = $b->[0];
4283 $first_a =~ s/^--?//;
4284 $first_b =~ s/^--?//;
4286 return $first_a cmp $first_b;
4291 my ( $sources ) = @_;
4293 $sources = explode_sources
($sources);
4298 foreach my $source (@{$sources}) {
4299 my ( $name, $contents ) = @{$source}{qw
/name contents/};
4300 if ( not $opts_by_source{$name} ) {
4301 $opts_by_source{$name} = [];
4302 push @source_names, $name;
4304 push @{$opts_by_source{$name}}, $contents;
4307 foreach my $name (@source_names) {
4308 my $contents = $opts_by_source{$name};
4311 print '=' x
length($name), "\n";
4312 print ' ', join(' ', @{$_}), "\n" foreach sort { compare_opts
($a, $b) } @{$contents};
4319 sub remove_default_options_if_needed
{
4320 my ( $sources ) = @_;
4324 foreach my $index ( 0 .. $#{$sources} ) {
4325 if ( $sources->[$index]{'name'} eq 'Defaults' ) {
4326 $default_index = $index;
4331 return $sources unless defined $default_index;
4333 my $should_remove = 0;
4335 # Start with default options, minus some annoying ones.
4336 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4337 Getopt
::Long
::Configure
(
4343 foreach my $index ( $default_index + 1 .. $#{$sources} ) {
4344 my ( $name, $args ) = @{$sources->[$index]}{qw
/name contents/};
4347 local @ARGV = @{$args};
4348 Getopt
::Long
::GetOptions
(
4349 'ignore-ack-defaults' => \
$should_remove,
4354 ( undef, $sources->[$index]{contents
} ) = Getopt
::Long
::GetOptionsFromString
($args,
4355 'ignore-ack-defaults' => \
$should_remove,
4360 Getopt
::Long
::Configure
('default');
4361 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4363 return $sources unless $should_remove;
4365 my @copy = @{$sources};
4366 splice @copy, $default_index, 1;
4371 sub check_for_mutually_exclusive_options
{
4372 my ( $arg_sources ) = @_;
4374 my %mutually_exclusive_with;
4375 my @copy = @{$arg_sources};
4377 for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
4378 my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
4380 foreach my $l_opt ( @{$lhs} ) {
4381 foreach my $r_opt ( @{$rhs} ) {
4382 push @{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
4383 push @{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
4391 my $source = shift @copy;
4392 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4393 $args = ref($args) ? [ @{$args} ] : [ Text
::ParseWords
::shellwords
($args) ];
4395 foreach my $opt ( @{$args} ) {
4396 next unless $opt =~ /^[-+]/;
4397 last if $opt eq '--';
4399 if( $opt =~ /^(.*)=/ ) {
4402 elsif ( $opt =~ /^(-[^-]).+/ ) {
4406 $set_opts{ $opt } = 1;
4408 my $mutex_opts = $mutually_exclusive_with{ $opt };
4410 next unless $mutex_opts;
4412 foreach my $mutex_opt ( @{$mutex_opts} ) {
4413 if($set_opts{ $mutex_opt }) {
4414 die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
4423 my $arg_sources = \
@_;
4426 pager
=> $ENV{ACK_PAGER_COLOR
} || $ENV{ACK_PAGER
},
4429 check_for_mutually_exclusive_options
($arg_sources);
4431 $arg_sources = remove_default_options_if_needed
($arg_sources);
4433 if ( should_dump_options
($arg_sources) ) {
4434 dump_options
($arg_sources);
4438 my $type_specs = process_filetypes
(\
%opt, $arg_sources);
4439 process_other
(\
%opt, $type_specs, $arg_sources);
4440 while ( @{$arg_sources} ) {
4441 my $source = shift @{$arg_sources};
4442 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4444 # All of our sources should be transformed into an array ref
4446 if ( $source_name eq 'ARGV' ) {
4450 Carp
::croak
"source '$source_name' has extra arguments!";
4454 Carp
::croak
'The impossible has occurred!';
4457 my $filters = ($opt{filters
} ||= []);
4459 # Throw the default filter in if no others are selected.
4460 if ( not grep { !$_->is_inverted() } @{$filters} ) {
4461 push @{$filters}, App
::Ack
::Filter
::Default-
>new();
4467 sub retrieve_arg_sources
{
4473 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4474 Getopt
::Long
::Configure
('pass_through');
4475 Getopt
::Long
::Configure
('no_auto_abbrev');
4477 Getopt
::Long
::GetOptions
(
4479 'ackrc=s' => \
$ackrc,
4482 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4487 my $finder = App
::Ack
::ConfigFinder-
>new;
4488 @files = $finder->find_config_files;
4491 # We explicitly use open so we get a nice error message.
4492 # XXX This is a potential race condition!.
4493 if(open my $fh, '<', $ackrc) {
4497 die "Unable to load ackrc '$ackrc': $!"
4499 push( @files, { path
=> $ackrc } );
4502 push @arg_sources, {
4504 contents
=> [ App
::Ack
::ConfigDefault
::options_clean
() ],
4507 foreach my $file ( @files) {
4508 my @lines = App
::Ack
::ConfigFinder
::read_rcfile
($file->{path
});
4511 push @arg_sources, {
4512 name
=> $file->{path
},
4513 contents
=> \
@lines,
4514 project
=> $file->{project
},
4519 if ( $ENV{ACK_OPTIONS
} && !$noenv ) {
4520 push @arg_sources, {
4521 name
=> 'ACK_OPTIONS',
4522 contents
=> $ENV{ACK_OPTIONS
},
4526 push @arg_sources, {
4528 contents
=> [ @ARGV ],
4531 return @arg_sources;
4534 1; # End of App::Ack::ConfigLoader
4535 package App
::Ack
::Filter
;
4546 my ( undef, $type, @args ) = @_;
4548 if ( my $package = $filter_types{$type} ) {
4549 return $package->new(@args);
4551 Carp
::croak
"Unknown filter type '$type'";
4555 sub register_filter
{
4556 my ( undef, $type, $package ) = @_;
4558 $filter_types{$type} = $package;
4567 return App
::Ack
::Filter
::Inverse-
>new( $self );
4579 return '(unimplemented to_string)';
4590 package App
::Ack
::Filter
::Extension
;
4595 our @ISA = 'App::Ack::Filter';
4600 my ( $class, @extensions ) = @_;
4602 my $exts = join('|', map { "\Q$_\E"} @extensions);
4603 my $re = qr/[.](?:$exts)$/i;
4606 extensions
=> \
@extensions,
4608 groupname
=> 'ExtensionGroup',
4613 return App
::Ack
::Filter
::ExtensionGroup-
>new();
4617 my ( $self, $resource ) = @_;
4619 my $re = $self->{'regex'};
4621 return $resource->name =~ /$re/;
4627 my $re = $self->{'regex'};
4629 return ref($self) . " - $re";
4635 my $exts = $self->{'extensions'};
4637 return join(' ', map { ".$_" } @{$exts});
4641 App
::Ack
::Filter-
>register_filter(ext
=> __PACKAGE__
);
4645 package App
::Ack
::Filter
::FirstLineMatch
;
4650 our @ISA = 'App::Ack::Filter';
4654 my ( $class, $re ) = @_;
4656 $re =~ s{^/|/$}{}g; # XXX validate?
4664 # This test reads the first 250 characters of a file, then just uses the
4665 # first line found in that. This prevents reading something like an entire
4666 # .min.js file (which might be only one "line" long) into memory.
4669 my ( $self, $resource ) = @_;
4671 my $re = $self->{'regex'};
4673 my $line = $resource->firstliney;
4675 return $line =~ /$re/;
4681 my $re = $self->{'regex'};
4683 return ref($self) . " - $re";
4689 (my $re = $self->{regex
}) =~ s{\([^:]*:(.*)\)$}{$1};
4691 return "first line matches /$re/";
4695 App
::Ack
::Filter-
>register_filter(firstlinematch
=> __PACKAGE__
);
4699 package App
::Ack
::Filter
::Is
;
4704 our @ISA = 'App::Ack::Filter';
4707 use File
::Spec
3.00 ();
4710 my ( $class, $filename ) = @_;
4713 filename
=> $filename,
4714 groupname
=> 'IsGroup',
4719 return App
::Ack
::Filter
::IsGroup-
>new();
4723 my ( $self, $resource ) = @_;
4725 my $filename = $self->{'filename'};
4726 my $base = (File
::Spec-
>splitpath($resource->name))[2];
4728 return $base eq $filename;
4734 my $filename = $self->{'filename'};
4736 return ref($self) . " - $filename";
4742 my $filename = $self->{'filename'};
4748 App
::Ack
::Filter-
>register_filter(is => __PACKAGE__
);
4752 package App
::Ack
::Filter
::Match
;
4757 our @ISA = 'App::Ack::Filter';
4760 use File
::Spec
3.00;
4763 my ( $class, $re ) = @_;
4765 $re =~ s{^/|/$}{}g; # XXX validate?
4770 groupname
=> 'MatchGroup',
4775 return App
::Ack
::Filter
::MatchGroup-
>new;
4779 my ( $self, $resource ) = @_;
4781 my $re = $self->{'regex'};
4783 return $resource->basename =~ /$re/;
4789 my $re = $self->{'regex'};
4791 print ref($self) . " - $re";
4799 my $re = $self->{'regex'};
4801 return "filename matches $re";
4805 App
::Ack
::Filter-
>register_filter(match
=> __PACKAGE__
);
4809 package App
::Ack
::Filter
::Default
;
4814 our @ISA = 'App::Ack::Filter';
4820 return bless {}, $class;
4824 my ( $self, $resource ) = @_;
4826 return -T
$resource->name;
4830 package App
::Ack
::Filter
::Inverse
;
4835 our @ISA = 'App::Ack::Filter';
4839 my ( $class, $filter ) = @_;
4847 my ( $self, $resource ) = @_;
4849 my $filter = $self->{'filter'};
4850 return !$filter->filter( $resource );
4856 return $self->{'filter'};
4866 my $filter = $self->{'filter'};
4872 package App
::Ack
::Filter
::Collection
;
4877 our @ISA = 'App::Ack::Filter';
4890 my ( $self, $resource ) = @_;
4892 for my $group (values %{$self->{'groups'}}) {
4893 if ($group->filter($resource)) {
4898 for my $filter (@{$self->{'ungrouped'}}) {
4899 if ($filter->filter($resource)) {
4908 my ( $self, $filter ) = @_;
4910 if (exists $filter->{'groupname'}) {
4911 my $group = ($self->{groups
}->{$filter->{groupname
}} ||= $filter->create_group());
4912 $group->add($filter);
4915 push @{$self->{'ungrouped'}}, $filter;
4924 return ref($self) . " - $self";
4930 my $ungrouped = $self->{'ungrouped'};
4932 return join(', ', map { "($_)" } @{$ungrouped});
4936 package App
::Ack
::Filter
::IsGroup
;
4941 our @ISA = 'App::Ack::Filter';
4944 use File
::Spec
3.00 ();
4955 my ( $self, $filter ) = @_;
4957 $self->{data
}->{ $filter->{filename
} } = 1;
4963 my ( $self, $resource ) = @_;
4965 my $data = $self->{'data'};
4966 my $base = $resource->basename;
4968 return exists $data->{$base};
4974 return ref($self) . " - $self";
4980 return join(' ', keys %{$self->{data
}});
4984 package App
::Ack
::Filter
::ExtensionGroup
;
4989 our @ISA = 'App::Ack::Filter';
5001 my ( $self, $filter ) = @_;
5003 foreach my $ext (@{$filter->{extensions
}}) {
5004 $self->{data
}->{lc $ext} = 1;
5011 my ( $self, $resource ) = @_;
5013 if ($resource->name =~ /[.]([^.]*)$/) {
5014 return exists $self->{'data'}->{lc $1};
5023 return ref($self) . " - $self";
5029 return join(' ', map { ".$_" } sort keys %{$self->{data
}});
5033 package App
::Ack
::Filter
::MatchGroup
;
5038 our @ISA = 'App::Ack::Filter';
5051 my ( $self, $filter ) = @_;
5053 push @{ $self->{matches
} }, $filter->{regex
};
5055 my $re = join('|', map { "(?:$_)" } @{ $self->{matches
} });
5056 $self->{big_re
} = qr/$re/;
5062 my ( $self, $resource ) = @_;
5064 my $re = $self->{big_re
};
5066 return $resource->basename =~ /$re/;
5078 package App
::Ack
::Filter
::IsPath
;
5083 our @ISA = 'App::Ack::Filter';
5088 my ( $class, $filename ) = @_;
5091 filename
=> $filename,
5092 groupname
=> 'IsPathGroup',
5097 return App
::Ack
::Filter
::IsPathGroup-
>new();
5101 my ( $self, $resource ) = @_;
5103 return $resource->name eq $self->{'filename'};
5109 my $filename = $self->{'filename'};
5111 return ref($self) . " - $filename";
5117 my $filename = $self->{'filename'};
5123 package App
::Ack
::Filter
::IsPathGroup
;
5128 our @ISA = 'App::Ack::Filter';
5140 my ( $self, $filter ) = @_;
5142 $self->{data
}->{ $filter->{filename
} } = 1;
5148 my ( $self, $resource ) = @_;
5150 my $data = $self->{'data'};
5152 return exists $data->{$resource->name};
5158 return ref($self) . " - $self";
5164 return join(' ', keys %{$self->{data
}});
5174 our $VERSION = '1.12';
5180 our $name; # name of the current file
5181 our $dir; # dir of the current file
5183 our %files_defaults;
5188 file_filter
=> undef,
5189 descend_filter
=> undef,
5190 error_handler
=> sub { CORE
::die @_ },
5191 warning_handler
=> sub { CORE
::warn @_ },
5192 sort_files
=> undef,
5193 follow_symlinks
=> 1,
5196 %skip_dirs = map {($_,1)} (File
::Spec-
>curdir, File
::Spec-
>updir);
5201 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5203 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5204 my $filter = $parms->{file_filter
};
5208 my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 );
5209 if ( -f
$fullpath || -p
$fullpath || $fullpath =~ m{^/dev/fd} ) {
5212 local $File::Next
::dir
= $dirname;
5213 local $File::Next
::name
= $fullpath;
5214 next if not $filter->();
5216 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5219 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
5233 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5235 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5236 my $err = $parms->{error_handler
};
5237 my $warn = $parms->{error_handler
};
5239 my $filename = $queue[1];
5241 if ( !defined($filename) ) {
5242 $err->( 'Must pass a filename to from_file()' );
5247 if ( $filename eq '-' ) {
5251 if ( !open( $fh, '<', $filename ) ) {
5252 $err->( "Unable to open $filename: $!" );
5256 my $filter = $parms->{file_filter
};
5259 local $/ = $parms->{nul_separated
} ? "\x00" : $/;
5260 while ( my $fullpath = <$fh> ) {
5262 next unless $fullpath =~ /./;
5263 if ( not ( -f
$fullpath || -p _
) ) {
5264 $warn->( "$fullpath: No such file" );
5268 my ($volume,$dirname,$file) = File
::Spec-
>splitpath( $fullpath );
5271 local $File::Next
::dir
= $dirname;
5272 local $File::Next
::name
= $fullpath;
5273 next if not $filter->();
5275 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5283 sub _bad_invocation
{
5284 my $good = (caller(1))[3];
5286 $bad =~ s/(.+)::/$1->/;
5287 return "$good must not be invoked as $bad";
5290 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
5291 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
5296 my @parts = split( /\//, $path );
5298 return $path if @parts < 2;
5300 return File
::Spec-
>catfile( @parts );
5306 my $defaults = shift;
5307 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
5309 my %passed_parms = %{$passed_parms};
5312 for my $key ( keys %{$defaults} ) {
5314 exists $passed_parms{$key}
5315 ? delete $passed_parms{$key}
5316 : $defaults->{$key};
5319 # Any leftover keys are bogus
5320 for my $badkey ( keys %passed_parms ) {
5321 my $sub = (caller(1))[3];
5322 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
5325 # If it's not a code ref, assume standard sort
5326 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
5327 $parms->{sort_files
} = \
&sort_standard
;
5332 my $start = reslash
( $_ );
5334 push @queue, ($start,undef,$start);
5337 push @queue, (undef,$start,$start);
5341 return ($parms,@queue);
5345 sub _candidate_files
{
5347 my $dirname = shift;
5350 if ( !opendir $dh, $dirname ) {
5351 $parms->{error_handler
}->( "$dirname: $!" );
5356 my $descend_filter = $parms->{descend_filter
};
5357 my $follow_symlinks = $parms->{follow_symlinks
};
5358 my $sort_sub = $parms->{sort_files
};
5360 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
5363 # Only do directory checking if we have a descend_filter
5364 my $fullpath = File
::Spec-
>catdir( $dirname, $file );
5365 if ( !$follow_symlinks ) {
5366 next if -l
$fullpath;
5370 if ( $descend_filter ) {
5371 if ( $has_stat ? (-d _
) : (-d
$fullpath) ) {
5372 local $File::Next
::dir
= $fullpath;
5374 next if not $descend_filter->();
5378 push( @newfiles, [ $dirname, $file, $fullpath ] );
5381 push( @newfiles, $dirname, $file, $fullpath );
5387 return map { @{$_} } sort $sort_sub @newfiles;
5394 1; # End of File::Next