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.14'; # Check http://beyondgrep.com/ for updates
20 use Getopt
::Long
2.35 ();
26 # XXX Don't make this so brute force
27 # See also: https://github.com/petdance/ack2/issues/89
29 # These are all our globals.
32 $App::Ack
::orig_program_name
= $0;
33 $0 = join(' ', 'ack', $0);
34 if ( $App::Ack
::VERSION
ne $main::VERSION
) {
35 App
::Ack
::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
38 # Do preliminary arg checking;
39 my $env_is_usable = 1;
40 for my $arg ( @ARGV ) {
41 last if ( $arg eq '--' );
43 # Get the --thpppt, --bar, --cathy checking out of the way.
44 $arg =~ /^--th[pt]+t+$/ and App
::Ack
::_thpppt
($arg);
45 $arg eq '--bar' and App
::Ack
::_bar
();
46 $arg eq '--cathy' and App
::Ack
::_cathy
();
48 # See if we want to ignore the environment. (Don't tell Al Gore.)
49 $arg eq '--env' and $env_is_usable = 1;
50 $arg eq '--noenv' and $env_is_usable = 0;
53 if ( !$env_is_usable ) {
54 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
59 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
60 Getopt
::Long
::Configure
('pass_through', 'no_auto_abbrev');
61 Getopt
::Long
::GetOptions
(
62 'help' => sub { App
::Ack
::show_help
(); exit; },
63 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
64 'man' => sub { App
::Ack
::show_man
(); exit; },
66 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
69 App
::Ack
::show_help
();
76 sub _compile_descend_filter
{
79 my $idirs = $opt->{idirs
};
80 my $dont_ignore_dirs = $opt->{no_ignore_dirs
};
82 # if we have one or more --noignore-dir directives, we can't ignore
83 # entire subdirectory hierarchies, so we return an "accept all"
84 # filter and scrutinize the files more in _compile_file_filter
85 return if $dont_ignore_dirs;
86 return unless $idirs && @
{$idirs};
90 foreach my $idir (@
{$idirs}) {
91 if ( $idir =~ /^(\w+):(.*)/ ) {
96 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
100 Carp
::croak
( qq{Invalid filter specification
"$idir"} );
105 return !exists $ignore_dirs{$_} && !exists $ignore_dirs{$File::Next
::dir
};
109 sub _compile_file_filter
{
110 my ( $opt, $start ) = @_;
112 my $ifiles = $opt->{ifiles
};
115 my $ifiles_filters = App
::Ack
::Filter
::Collection
->new();
117 foreach my $filter_spec (@
{$ifiles}) {
118 if ( $filter_spec =~ /^(\w+):(.+)/ ) {
119 my ($how,$what) = ($1,$2);
120 my $filter = App
::Ack
::Filter
->create_filter($how, split(/,/, $what));
121 $ifiles_filters->add($filter);
124 Carp
::croak
( qq{Invalid filter specification
"$filter_spec"} );
128 my $filters = $opt->{'filters'} || [];
129 my $direct_filters = App
::Ack
::Filter
::Collection
->new();
130 my $inverse_filters = App
::Ack
::Filter
::Collection
->new();
132 foreach my $filter (@
{$filters}) {
133 if ($filter->is_inverted()) {
134 # We want to check if files match the uninverted filters
135 $inverse_filters->add($filter->invert());
138 $direct_filters->add($filter);
142 my %is_member_of_starting_set = map { (get_file_id
($_) => 1) } @
{$start};
144 my $ignore_dir_list = $opt->{idirs
};
145 my $dont_ignore_dir_list = $opt->{no_ignore_dirs
};
148 my %dont_ignore_dir_set;
150 foreach my $filter (@
{ $ignore_dir_list }) {
151 if ( $filter =~ /^(\w+):(.*)/ ) {
153 $ignore_dir_set{ $2 } = 1;
155 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
158 Carp
::croak
( qq{Invalid filter specification
"$filter"} );
161 foreach my $filter (@
{ $dont_ignore_dir_list }) {
162 if ( $filter =~ /^(\w+):(.*)/ ) {
164 $dont_ignore_dir_set{ $2 } = 1;
166 Carp
::croak
( 'Non-is filters are not yet supported for --ignore-dir' );
169 Carp
::croak
( qq{Invalid filter specification
"$filter"} );
173 my $match_filenames = $opt->{g
};
174 my $match_regex = $opt->{regex
};
175 my $is_inverted = $opt->{v
};
178 if ( $match_filenames ) {
179 if ( $File::Next
::name
=~ /$match_regex/ && $is_inverted ) {
182 if ( $File::Next
::name
!~ /$match_regex/ && !$is_inverted ) {
186 # ack always selects files that are specified on the command
187 # line, regardless of filetype. If you want to ack a JPEG,
188 # and say "ack foo whatever.jpg" it will do it for you.
189 return 1 if $is_member_of_starting_set{ get_file_id
($File::Next
::name
) };
191 if ( $dont_ignore_dir_list ) {
192 my ( undef, $dirname ) = File
::Spec
->splitpath($File::Next
::name
);
193 my @dirs = File
::Spec
->splitdir($dirname);
197 foreach my $dir ( @dirs ) {
198 if ( $ignore_dir_set{ $dir } ) {
201 elsif ( $dont_ignore_dir_set{ $dir } ) {
205 if ( $is_ignoring ) {
210 # Ignore named pipes found in directory searching. Named
211 # pipes created by subprocesses get specified on the command
212 # line, so the rule of "always select whatever is on the
213 # command line" wins.
214 return 0 if -p
$File::Next
::name
;
216 # We can't handle unreadable filenames; report them.
218 use filetest
'access';
220 if ( not -R
$File::Next
::name
) {
221 if ( $App::Ack
::report_bad_filenames
) {
222 App
::Ack
::warn( "${File::Next::name}: cannot open file for reading" );
228 my $resource = App
::Ack
::Resource
::Basic
->new($File::Next
::name
);
229 return 0 if !$resource || $ifiles_filters->filter($resource);
231 my $match_found = $direct_filters->filter($resource);
233 # Don't bother invoking inverse filters unless we consider the current resource a match
234 if ( $match_found && $inverse_filters->filter( $resource ) ) {
242 my $resource = shift;
245 my @types = filetypes
( $resource );
246 my $types = join( ',', @types );
247 my $arrow = @types ?
' => ' : ' =>';
248 App
::Ack
::print( $resource->name, $arrow, join( ',', @types ), $ors );
253 # Set default colors, load Term::ANSIColor
255 eval 'use Term::ANSIColor 1.10 ()';
256 eval 'use Win32::Console::ANSI' if $App::Ack
::is_windows
;
258 $ENV{ACK_COLOR_MATCH
} ||= 'black on_yellow';
259 $ENV{ACK_COLOR_FILENAME
} ||= 'bold green';
260 $ENV{ACK_COLOR_LINENO
} ||= 'bold yellow';
266 my ( $resource ) = @_;
270 foreach my $k (keys %App::Ack
::mappings
) {
271 my $filters = $App::Ack
::mappings
{$k};
273 foreach my $filter (@
{$filters}) {
275 my $clone = $resource->clone;
276 if ( $filter->filter($clone) ) {
283 # http://search.cpan.org/dist/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm
284 @matches = sort @matches;
288 # Returns a (fairly) unique identifier for a file.
289 # Use this function to compare two files to see if they're
290 # equal (ie. the same file, but with a different path/links/etc).
292 my ( $filename ) = @_;
294 if ( $App::Ack
::is_windows
) {
295 return File
::Next
::reslash
( $filename );
298 # XXX is this the best method? it always hits the FS
299 if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
300 return join(':', $dev, $inode);
303 # XXX this could be better
309 # Returns a regex object based on a string and command-line options.
310 # Dies when the regex $str is undefined (i.e. not given on command line).
316 defined $str or App
::Ack
::die( 'No regular expression found.' );
318 $str = quotemeta( $str ) if $opt->{Q
};
320 my $pristine_str = $str;
323 $str = "\\b$str" if $pristine_str =~ /^\w/;
324 $str = "$str\\b" if $pristine_str =~ /\w$/;
327 my $regex_is_lc = $str eq lc $str;
328 if ( $opt->{i
} || ($opt->{smart_case
} && $regex_is_lc) ) {
332 my $re = eval { qr/$str/ };
334 die "Invalid regex '$str':\n $@";
343 my @before_ctx_lines;
347 my $has_printed_something;
350 $has_printed_something = 0;
353 sub print_matches_in_resource
{
354 my ( $resource, $opt ) = @_;
356 my $passthru = $opt->{passthru
};
357 my $max_count = $opt->{m
} || -1;
359 my $filename = $resource->name;
360 my $break = $opt->{break};
361 my $heading = $opt->{heading
};
362 my $ors = $opt->{print0
} ?
"\0" : "\n";
363 my $color = $opt->{color
};
364 my $print_filename = $opt->{show_filename
};
366 my $has_printed_for_this_resource = 0;
370 local $opt->{before_context
} = $opt->{output
} ?
0 : $opt->{before_context
};
371 local $opt->{after_context
} = $opt->{output
} ?
0 : $opt->{after_context
};
373 my $n_before_ctx_lines = $opt->{before_context
} || 0;
374 my $n_after_ctx_lines = $opt->{after_context
} || 0;
376 @after_ctx_lines = @before_ctx_lines = ();
378 my $fh = $resource->open();
380 if ( $App::Ack
::report_bad_filenames
) {
381 App
::Ack
::warn( "$filename: $!" );
386 my $display_filename = $filename;
387 if ( $print_filename && $heading && $color ) {
388 $display_filename = Term
::ANSIColor
::colored
($display_filename, $ENV{ACK_COLOR_FILENAME
});
391 # check for context before the main loop, so we don't
392 # pay for it if we don't need it
393 if ( $n_before_ctx_lines || $n_after_ctx_lines ) {
394 my $current_line = <$fh>; # prime the first line of input
396 while ( defined $current_line ) {
397 while ( (@after_ctx_lines < $n_after_ctx_lines) && defined($_ = <$fh>) ) {
398 push @after_ctx_lines, $_;
401 local $_ = $current_line;
402 my $former_dot_period = $.;
403 $. -= @after_ctx_lines;
405 if ( does_match
($opt, $_) ) {
406 if ( !$has_printed_for_this_resource ) {
407 if ( $break && $has_printed_something ) {
408 App
::Ack
::print_blank_line
();
410 if ( $print_filename && $heading ) {
411 App
::Ack
::print_filename
( $display_filename, $ors );
414 print_line_with_context
($opt, $filename, $_, $.);
415 $has_printed_for_this_resource = 1;
419 elsif ( $passthru ) {
420 chomp; # XXX proper newline handling?
421 # XXX inline this call?
422 if ( $break && !$has_printed_for_this_resource && $has_printed_something ) {
423 App
::Ack
::print_blank_line
();
425 print_line_with_options
($opt, $filename, $_, $., ':');
426 $has_printed_for_this_resource = 1;
428 last unless $max_count != 0;
430 # I tried doing this with local(), but for some reason,
431 # $. continued to have its new value after the exit of the
432 # enclosing block. I'm guessing that $. has some extra
433 # magic associated with it or something. If someone can
434 # tell me why this happened, I would love to know!
435 $. = $former_dot_period; # XXX this won't happen on an exception
437 if ( $n_before_ctx_lines ) {
438 push @before_ctx_lines, $current_line;
439 shift @before_ctx_lines while @before_ctx_lines > $n_before_ctx_lines;
441 if ( $n_after_ctx_lines ) {
442 $current_line = shift @after_ctx_lines;
445 $current_line = <$fh>;
453 if ( does_match
($opt, $_) ) {
454 if ( !$has_printed_for_this_resource ) {
455 if ( $break && $has_printed_something ) {
456 App
::Ack
::print_blank_line
();
458 if ( $print_filename && $heading ) {
459 App
::Ack
::print_filename
( $display_filename, $ors );
462 print_line_with_context
($opt, $filename, $_, $.);
463 $has_printed_for_this_resource = 1;
467 elsif ( $passthru ) {
468 chomp; # XXX proper newline handling?
469 if ( $break && !$has_printed_for_this_resource && $has_printed_something ) {
470 App
::Ack
::print_blank_line
();
472 print_line_with_options
($opt, $filename, $_, $., ':');
473 $has_printed_for_this_resource = 1;
475 last unless $max_count != 0;
479 $is_iterating = 0; # XXX this won't happen on an exception
480 # then again, do we care? ack doesn't really
481 # handle exceptions anyway.
486 sub print_line_with_options
{
487 my ( $opt, $filename, $line, $line_no, $separator ) = @_;
489 $has_printed_something = 1;
491 my $print_filename = $opt->{show_filename
};
492 my $print_column = $opt->{column
};
493 my $ors = $opt->{print0
} ?
"\0" : "\n";
494 my $heading = $opt->{heading
};
495 my $output_expr = $opt->{output
};
496 my $color = $opt->{color
};
501 $filename = Term
::ANSIColor
::colored
($filename,
502 $ENV{ACK_COLOR_FILENAME
});
503 $line_no = Term
::ANSIColor
::colored
($line_no,
504 $ENV{ACK_COLOR_LINENO
});
507 if($print_filename) {
509 push @line_parts, $line_no;
512 push @line_parts, $filename, $line_no;
515 if( $print_column ) {
516 push @line_parts, get_match_column
();
520 while ( $line =~ /$opt->{regex}/og ) {
521 # XXX We need to stop using eval() for --output. See https://github.com/petdance/ack2/issues/421
522 my $output = eval $output_expr;
523 App
::Ack
::print( join( $separator, @line_parts, $output ), $ors );
528 $line =~ /$opt->{regex}/o; # this match is redundant, but we need
529 # to perfom it in order to get if
530 # capture groups are set
532 if ( @
+ > 1 ) { # if we have captures
533 while ( $line =~ /$opt->{regex}/og ) {
534 my $offset = 0; # additional offset for when we add stuff
535 my $previous_match_end = 0;
537 for ( my $i = 1; $i < @
+; $i++ ) {
538 my ( $match_start, $match_end ) = ( $-[$i], $+[$i] );
540 next unless defined($match_start);
541 next if $match_start < $previous_match_end;
543 my $substring = substr( $line,
544 $offset + $match_start, $match_end - $match_start );
545 my $substitution = Term
::ANSIColor
::colored
( $substring,
546 $ENV{ACK_COLOR_MATCH
} );
548 substr( $line, $offset + $match_start,
549 $match_end - $match_start, $substitution );
551 $previous_match_end = $match_end; # offsets do not need to be applied
552 $offset += length( $substitution ) - length( $substring );
555 pos($line) = $+[0] + $offset;
559 my $matched = 0; # flag; if matched, need to escape afterwards
561 while ( $line =~ /$opt->{regex}/og ) {
564 my ( $match_start, $match_end ) = ($-[0], $+[0]);
565 next unless defined($match_start);
567 my $substring = substr( $line, $match_start,
568 $match_end - $match_start );
569 my $substitution = Term
::ANSIColor
::colored
( $substring,
570 $ENV{ACK_COLOR_MATCH
} );
572 substr( $line, $match_start, $match_end - $match_start,
575 pos($line) = $match_end +
576 (length( $substitution ) - length( $substring ));
578 # XXX why do we do this?
579 $line .= "\033[0m\033[K" if $matched;
583 push @line_parts, $line;
584 App
::Ack
::print( join( $separator, @line_parts ), $ors );
591 my ( $resource, $opt, $cb ) = @_;
595 local $opt->{before_context
} = $opt->{output
} ?
0 : $opt->{before_context
};
596 local $opt->{after_context
} = $opt->{output
} ?
0 : $opt->{after_context
};
598 my $n_before_ctx_lines = $opt->{before_context
} || 0;
599 my $n_after_ctx_lines = $opt->{after_context
} || 0;
601 @after_ctx_lines = @before_ctx_lines = ();
603 my $fh = $resource->open();
605 if ( $App::Ack
::report_bad_filenames
) {
606 App
::Ack
::warn( $resource->name . ': ' . $! );
611 # Check for context before the main loop, so we don't pay for it if we don't need it.
612 if ( $n_before_ctx_lines || $n_after_ctx_lines ) {
613 my $current_line = <$fh>; # prime the first line of input
615 while ( defined $current_line ) {
616 while ( (@after_ctx_lines < $n_after_ctx_lines) && defined($_ = <$fh>) ) {
617 push @after_ctx_lines, $_;
620 local $_ = $current_line;
621 my $former_dot_period = $.;
622 $. -= @after_ctx_lines;
626 # I tried doing this with local(), but for some reason,
627 # $. continued to have its new value after the exit of the
628 # enclosing block. I'm guessing that $. has some extra
629 # magic associated with it or something. If someone can
630 # tell me why this happened, I would love to know!
631 $. = $former_dot_period; # XXX this won't happen on an exception
633 if ( $n_before_ctx_lines ) {
634 push @before_ctx_lines, $current_line;
635 shift @before_ctx_lines while @before_ctx_lines > $n_before_ctx_lines;
637 if ( $n_after_ctx_lines ) {
638 $current_line = shift @after_ctx_lines;
641 $current_line = <$fh>;
653 $is_iterating = 0; # XXX this won't happen on an exception
654 # then again, do we care? ack doesn't really
655 # handle exceptions anyway.
661 if ( not $is_iterating ) {
662 Carp
::croak
( 'get_context() called outside of iterate()' );
666 scalar(@before_ctx_lines) ? \
@before_ctx_lines : undef,
667 scalar(@after_ctx_lines) ? \
@after_ctx_lines : undef,
676 my $previous_file_processed;
677 my $previous_line_printed;
681 $previous_line_printed = -1;
684 sub print_line_with_context
{
685 my ( $opt, $filename, $matching_line, $line_no ) = @_;
687 my $heading = $opt->{heading
};
689 if( !defined($previous_file_processed) ||
690 $previous_file_processed ne $filename ) {
691 $previous_file_processed = $filename;
692 $previous_line_printed = -1;
699 my $ors = $opt->{print0
} ?
"\0" : "\n";
700 my $match_word = $opt->{w
};
701 my $is_tracking_context = $opt->{after_context
} || $opt->{before_context
};
702 my $output_expr = $opt->{output
};
704 $matching_line =~ s/[\r\n]+$//g;
706 my ( $before_context, $after_context ) = get_context
();
708 if ( $before_context ) {
709 my $first_line = $. - @
{$before_context};
711 if ( $first_line <= $previous_line_printed ) {
712 splice @
{$before_context}, 0, $previous_line_printed - $first_line + 1;
713 $first_line = $. - @
{$before_context};
715 if ( @
{$before_context} ) {
716 my $offset = @
{$before_context};
718 if( !$is_first_match && $previous_line_printed != $first_line - 1 ) {
719 App
::Ack
::print('--', $ors);
721 foreach my $line (@
{$before_context}) {
722 my $context_line_no = $. - $offset;
723 if ( $context_line_no <= $previous_line_printed ) {
728 local $opt->{column
};
730 print_line_with_options
($opt, $filename, $line, $context_line_no, '-');
731 $previous_line_printed = $context_line_no;
737 if ( $. > $previous_line_printed ) {
738 if( $is_tracking_context && !$is_first_match && $previous_line_printed != $. - 1 ) {
739 App
::Ack
::print('--', $ors);
742 print_line_with_options
($opt, $filename, $matching_line, $line_no, ':');
743 $previous_line_printed = $.;
748 foreach my $line (@
{$after_context}) {
750 if ( $previous_line_printed >= $. + $offset ) {
756 if ( $opt->{regex
} && does_match
( $opt, $line ) ) {
757 print_line_with_options
($opt, $filename, $line, $. + $offset, ':');
760 local $opt->{column
};
761 print_line_with_options
($opt, $filename, $line, $. + $offset, '-');
763 $previous_line_printed = $. + $offset;
777 my $match_column_number;
779 # does_match() MUST have an $opt->{regex} set.
782 my ( $opt, $line ) = @_;
784 $match_column_number = undef;
787 return ( $line !~ /$opt->{regex}/o );
790 if ( $line =~ /$opt->{regex}/o ) {
791 # @- = @LAST_MATCH_START
792 # @+ = @LAST_MATCH_END
793 $match_column_number = $-[0] + 1;
802 sub get_match_column
{
803 return $match_column_number;
808 sub resource_has_match
{
809 my ( $resource, $opt ) = @_;
812 my $fh = $resource->open();
814 if ( $App::Ack
::report_bad_filenames
) {
815 App
::Ack
::warn( $resource->name . ': ' . $! );
819 my $re = $opt->{regex
};
830 # XXX only do this for certain file sizes?
835 $has_match = $content =~ /$re/og;
843 sub count_matches_in_resource
{
844 my ( $resource, $opt ) = @_;
847 my $fh = $resource->open();
849 if ( $App::Ack
::report_bad_filenames
) {
850 App
::Ack
::warn( $resource->name . ': ' . $! );
854 my $re = $opt->{regex
};
857 ++$nmatches if (!/$re/o);
865 $nmatches =()= ($content =~ /$re/og);
874 my @arg_sources = App
::Ack
::ConfigLoader
::retrieve_arg_sources
();
876 my $opt = App
::Ack
::ConfigLoader
::process_args
( @arg_sources );
878 $App::Ack
::report_bad_filenames
= !$opt->{dont_report_bad_filenames
};
880 if ( $opt->{flush
} ) {
884 if ( !defined($opt->{color
}) && !$opt->{g
} ) {
885 my $windows_color = 1;
886 if ( $App::Ack
::is_windows
) {
887 $windows_color = eval { require Win32
::Console
::ANSI
; };
889 $opt->{color
} = !App
::Ack
::output_to_pipe
() && $windows_color;
891 if ( not defined $opt->{heading
} and not defined $opt->{break} ) {
892 $opt->{heading
} = $opt->{break} = !App
::Ack
::output_to_pipe
();
895 if ( defined($opt->{H
}) || defined($opt->{h
}) ) {
896 $opt->{show_filename
}= $opt->{H
} && !$opt->{h
};
899 if ( my $output = $opt->{output
} ) {
900 $output =~ s{\\}{\\\\}g;
901 $output =~ s{"}{\\"}g;
902 $opt->{output
} = qq{"$output"};
906 if ( $App::Ack
::is_filter_mode
&& !$opt->{files_from
} ) { # probably -x
907 $resources = App
::Ack
::Resources
->from_stdin( $opt );
908 my $regex = $opt->{regex
};
909 $regex = shift @ARGV if not defined $regex;
910 $opt->{regex
} = build_regex
( $regex, $opt );
913 if ( $opt->{f
} || $opt->{lines
} ) {
914 if ( $opt->{regex
} ) {
915 App
::Ack
::warn( "regex ($opt->{regex}) specified with -f or --lines" );
916 App
::Ack
::exit_from_ack
( 0 ); # XXX the 0 is misleading
920 my $regex = $opt->{regex
};
921 $regex = shift @ARGV if not defined $regex;
922 $opt->{regex
} = build_regex
( $regex, $opt );
925 if ( not defined $opt->{files_from
} ) {
928 if ( !exists($opt->{show_filename
}) ) {
929 unless(@start == 1 && !(-d
$start[0])) {
930 $opt->{show_filename
} = 1;
934 if ( defined $opt->{files_from
} ) {
935 $resources = App
::Ack
::Resources
->from_file( $opt, $opt->{files_from
} );
936 exit 1 unless $resources;
939 @start = ('.') unless @start;
940 foreach my $target (@start) {
941 if ( !-e
$target && $App::Ack
::report_bad_filenames
) {
942 App
::Ack
::warn( "$target: No such file or directory" );
946 $opt->{file_filter
} = _compile_file_filter
($opt, \
@start);
947 $opt->{descend_filter
} = _compile_descend_filter
($opt);
949 $resources = App
::Ack
::Resources
->from_argv( $opt, \
@start );
952 App
::Ack
::set_up_pager
( $opt->{pager
} ) if defined $opt->{pager
};
954 my $print_filenames = $opt->{show_filename
};
955 my $max_count = $opt->{m
};
956 my $ors = $opt->{print0
} ?
"\0" : "\n";
957 my $only_first = $opt->{1};
962 while ( my $resource = $resources->next ) {
963 # XXX Combine the -f and -g functions
965 # XXX printing should probably happen inside of App::Ack
966 if ( $opt->{show_types
} ) {
967 show_types
( $resource, $ors );
970 App
::Ack
::print( $resource->name, $ors );
973 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
975 elsif ( $opt->{g
} ) {
976 if ( $opt->{show_types
} ) {
977 show_types
( $resource, $ors );
980 local $opt->{show_filename
} = 0; # XXX Why is this local?
982 print_line_with_options
($opt, '', $resource->name, 0, $ors);
985 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
987 elsif ( $opt->{lines
} ) {
988 my $print_filename = $opt->{show_filename
};
989 my $passthru = $opt->{passthru
};
992 foreach my $line ( @
{ $opt->{lines
} } ) {
993 my @lines = split /,/, $line;
999 @line_numbers{@lines} = (1) x
@lines;
1002 my $filename = $resource->name;
1004 local $opt->{color
} = 0;
1006 iterate
($resource, $opt, sub {
1009 if ( $line_numbers{$.} ) {
1010 print_line_with_context
($opt, $filename, $_, $.);
1012 elsif ( $passthru ) {
1013 print_line_with_options
($opt, $filename, $_, $., ':');
1018 elsif ( $opt->{count
} ) {
1019 my $matches_for_this_file = count_matches_in_resource
( $resource, $opt );
1021 if ( not $opt->{show_filename
} ) {
1022 $total_count += $matches_for_this_file;
1026 if ( !$opt->{l
} || $matches_for_this_file > 0) {
1027 if ( $print_filenames ) {
1028 App
::Ack
::print( $resource->name, ':', $matches_for_this_file, $ors );
1031 App
::Ack
::print( $matches_for_this_file, $ors );
1035 elsif ( $opt->{l
} || $opt->{L
} ) {
1036 my $is_match = resource_has_match
( $resource, $opt );
1038 if ( $opt->{L
} ?
!$is_match : $is_match ) {
1039 App
::Ack
::print( $resource->name, $ors );
1042 last RESOURCES
if $only_first;
1043 last RESOURCES
if defined($max_count) && $nmatches >= $max_count;
1047 $nmatches += print_matches_in_resource
( $resource, $opt );
1048 if ( $nmatches && $only_first ) {
1054 if ( $opt->{count
} && !$opt->{show_filename
} ) {
1055 App
::Ack
::print( $total_count, "\n" );
1058 close $App::Ack
::fh
;
1059 App
::Ack
::exit_from_ack
( $nmatches );
1066 ack - grep-like text finder
1070 ack [options] PATTERN [FILE...]
1071 ack -f [options] [DIRECTORY...]
1075 Ack is designed as an alternative to F<grep> for programmers.
1077 Ack searches the named input FILEs (or standard input if no files
1078 are named, or the file name - is given) for lines containing a match
1079 to the given PATTERN. By default, ack prints the matching lines.
1081 PATTERN is a Perl regular expression. Perl regular expressions
1082 are commonly found in other programming languages, but for the particulars
1083 of their behavior, please consult
1084 L<http://perldoc.perl.org/perlreref.html|perlreref>. If you don't know
1085 how to use regular expression but are interested in learning, you may
1086 consult L<http://perldoc.perl.org/perlretut.html|perlretut>. If you do not
1087 need or want ack to use regular expressions, please see the
1088 C<-Q>/C<--literal> option.
1090 Ack can also list files that would be searched, without actually
1091 searching them, to let you take advantage of ack's file-type filtering
1094 =head1 FILE SELECTION
1096 If files are not specified for searching, either on the command
1097 line or piped in with the C<-x> option, I<ack> delves into
1098 subdirectories selecting files for searching.
1100 I<ack> is intelligent about the files it searches. It knows about
1101 certain file types, based on both the extension on the file and,
1102 in some cases, the contents of the file. These selections can be
1103 made with the B<--type> option.
1105 With no file selection, I<ack> searches through regular files that
1106 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
1107 options, either present in F<ackrc> files or on the command line.
1109 The default options for I<ack> ignore certain files and directories. These
1114 =item * Backup files: Files matching F<#*#> or ending with F<~>.
1116 =item * Coredumps: Files matching F<core.\d+>
1118 =item * Version control directories like F<.svn> and F<.git>.
1122 Run I<ack> with the C<--dump> option to see what settings are set.
1124 However, I<ack> always searches the files given on the command line,
1125 no matter what type. If you tell I<ack> to search in a coredump,
1126 it will search in a coredump.
1128 =head1 DIRECTORY SELECTION
1130 I<ack> descends through the directory tree of the starting directories
1131 specified. If no directories are specified, the current working directory is
1132 used. However, it will ignore the shadow directories used by
1133 many version control systems, and the build directories used by the
1134 Perl MakeMaker system. You may add or remove a directory from this
1135 list with the B<--[no]ignore-dir> option. The option may be repeated
1136 to add/remove multiple directories from the ignore list.
1138 For a complete list of directories that do not get searched, run
1141 =head1 WHEN TO USE GREP
1143 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
1144 throw I<grep> away, because there are times you'll still need it.
1146 E.g., searching through huge files looking for regexes that can be
1147 expressed with I<grep> syntax should be quicker with I<grep>.
1149 If your script or parent program uses I<grep> C<--quiet> or C<--silent>
1150 or needs exit 2 on IO error, use I<grep>.
1158 Specifies an ackrc file to load after all others; see L</"ACKRC LOCATION SEMANTICS">.
1160 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
1162 Print I<NUM> lines of trailing context after matching lines.
1164 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
1166 Print I<NUM> lines of leading context before matching lines.
1168 =item B<--[no]break>
1170 Print a break between results from different files. On by default
1171 when used interactively.
1173 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
1175 Print I<NUM> lines (default 2) of context around matching lines.
1177 =item B<-c>, B<--count>
1179 Suppress normal output; instead print a count of matching lines for
1180 each input file. If B<-l> is in effect, it will only show the
1181 number of lines for each file that has lines matching. Without
1182 B<-l>, some line counts may be zeroes.
1184 If combined with B<-h> (B<--no-filename>) ack outputs only one total
1187 =item B<--[no]color>, B<--[no]colour>
1189 B<--color> highlights the matching text. B<--nocolor> suppresses
1190 the color. This is on by default unless the output is redirected.
1192 On Windows, this option is off by default unless the
1193 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
1194 environment variable is used.
1196 =item B<--color-filename=I<color>>
1198 Sets the color to be used for filenames.
1200 =item B<--color-match=I<color>>
1202 Sets the color to be used for matches.
1204 =item B<--color-lineno=I<color>>
1206 Sets the color to be used for line numbers.
1208 =item B<--[no]column>
1210 Show the column number of the first match. This is helpful for
1211 editors that can place your cursor at a given position.
1213 =item B<--create-ackrc>
1215 Dumps the default ack options to standard output. This is useful for
1216 when you want to customize the defaults.
1220 Writes the list of options loaded and where they came from to standard
1221 output. Handy for debugging.
1225 B<--noenv> disables all environment processing. No F<.ackrc> is
1226 read and all environment variables are ignored. By default, F<ack>
1227 considers F<.ackrc> and settings in the environment.
1231 B<--flush> flushes output immediately. This is off by default
1232 unless ack is running interactively (when output goes to a pipe or
1237 Only print the files that would be searched, without actually doing
1238 any searching. PATTERN must not be specified, or it will be taken
1239 as a path to search.
1241 =item B<--files-from=I<FILE>>
1243 The list of files to be searched is specified in I<FILE>. The list of
1244 files are separated by newlines. If I<FILE> is C<->, the list is loaded
1245 from standard input.
1247 =item B<--[no]filter>
1249 Forces ack to act as if it were receiving input via a pipe.
1251 =item B<--[no]follow>
1253 Follow or don't follow symlinks, other than whatever starting files
1254 or directories were specified on the command line.
1256 This is off by default.
1258 =item B<-g I<PATTERN>>
1260 Print files where the relative path + filename matches I<PATTERN>.
1261 This option can be combined with B<--color> to make it easier to spot
1264 =item B<--[no]group>
1266 B<--group> groups matches by file name. This is the default
1267 when used interactively.
1269 B<--nogroup> prints one result per line, like grep. This is the
1270 default when output is redirected.
1272 =item B<-H>, B<--with-filename>
1274 Print the filename for each match. This is the default unless searching
1275 a single explicitly specified file.
1277 =item B<-h>, B<--no-filename>
1279 Suppress the prefixing of filenames on output when multiple files are
1282 =item B<--[no]heading>
1284 Print a filename heading above each file's results. This is the default
1285 when used interactively.
1287 =item B<--help>, B<-?>
1289 Print a short help statement.
1291 =item B<--help-types>, B<--help=types>
1293 Print all known types.
1295 =item B<-i>, B<--ignore-case>
1297 Ignore case distinctions in PATTERN
1299 =item B<--ignore-ack-defaults>
1301 Tells ack to completely ignore the default definitions provided with ack.
1302 This is useful in combination with B<--create-ackrc> if you I<really> want
1305 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
1307 Ignore directory (as CVS, .svn, etc are ignored). May be used
1308 multiple times to ignore multiple directories. For example, mason
1309 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
1310 option allows users to search directories which would normally be
1311 ignored (perhaps to research the contents of F<.svn/props> directories).
1313 The I<DIRNAME> must always be a simple directory name. Nested
1314 directories like F<foo/bar> are NOT supported. You would need to
1315 specify B<--ignore-dir=foo> and then no files from any foo directory
1316 are taken into account by ack unless given explicitly on the command
1319 =item B<--ignore-file=I<FILTERTYPE:FILTERARGS>>
1321 Ignore files matching I<FILTERTYPE:FILTERARGS>. The filters are specified
1322 identically to file type filters as seen in L</"Defining your own types">.
1324 =item B<-k>, B<--known-types>
1326 Limit selected files to those with types that ack knows about. This is
1327 equivalent to the default behavior found in ack 1.
1329 =item B<--lines=I<NUM>>
1331 Only print line I<NUM> of each file. Multiple lines can be given with multiple
1332 B<--lines> options or as a comma separated list (B<--lines=3,5,7>). B<--lines=4-7>
1333 also works. The lines are always output in ascending order, no matter the
1334 order given on the command line.
1336 =item B<-l>, B<--files-with-matches>
1338 Only print the filenames of matching files, instead of the matching text.
1340 =item B<-L>, B<--files-without-matches>
1342 Only print the filenames of files that do I<NOT> match.
1344 =item B<--match I<PATTERN>>
1346 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
1347 regex as your first argument, e.g. when executing multiple searches over the
1350 # search for foo and bar in given files
1351 ack file1 t/file* --match foo
1352 ack file1 t/file* --match bar
1354 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
1356 Stop reading a file after I<NUM> matches.
1360 Print this manual page.
1362 =item B<-n>, B<--no-recurse>
1364 No descending into subdirectories.
1368 Show only the part of each line matching PATTERN (turns off text
1371 =item B<--output=I<expr>>
1373 Output the evaluation of I<expr> for each line (turns off text
1375 If PATTERN matches more than once then a line is output for each non-overlapping match.
1376 For more information please see the section L</"Examples of F<--output>">.
1378 =item B<--pager=I<program>>, B<--nopager>
1380 B<--pager> directs ack's output through I<program>. This can also be specified
1381 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
1383 Using --pager does not suppress grouping and coloring like piping
1384 output on the command-line does.
1386 B<--nopager> cancels any setting in ~/.ackrc, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
1387 No output will be sent through a pager.
1391 Prints all lines, whether or not they match the expression. Highlighting
1392 will still work, though, so it can be used to highlight matches while
1393 still seeing the entire file, as in:
1395 # Watch a log file, and highlight a certain IP address
1396 $ tail -f ~/access.log | ack --passthru 123.45.67.89
1400 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
1401 are output separated with a null byte instead of the usual newline. This is
1402 helpful when dealing with filenames that contain whitespace, e.g.
1404 # remove all files of type html
1405 ack -f --html --print0 | xargs -0 rm -f
1407 =item B<-Q>, B<--literal>
1409 Quote all metacharacters in PATTERN, it is treated as a literal.
1411 =item B<-r>, B<-R>, B<--recurse>
1413 Recurse into sub-directories. This is the default and just here for
1414 compatibility with grep. You can also use it for turning B<--no-recurse> off.
1418 Suppress error messages about nonexistent or unreadable files. This is taken
1421 =item B<--[no]smart-case>, B<--no-smart-case>
1423 Ignore case in the search strings if PATTERN contains no uppercase
1424 characters. This is similar to C<smartcase> in vim. This option is
1425 off by default, and ignored if C<-i> is specified.
1427 B<-i> always overrides this option.
1429 =item B<--sort-files>
1431 Sorts the found files lexicographically. Use this if you want your file
1432 listings to be deterministic between runs of I<ack>.
1434 =item B<--show-types>
1436 Outputs the filetypes that ack associates with each file.
1438 Works with B<-f> and B<-g> options.
1440 =item B<--type=[no]TYPE>
1442 Specify the types of files to include or exclude from a search.
1443 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
1444 also be specified as B<--perl>, and B<--type=noperl> can be done
1447 If a file is of both type "foo" and "bar", specifying --foo and
1448 --nobar will exclude the file, because an exclusion takes precedence
1451 Type specifications can be repeated and are ORed together.
1453 See I<ack --help=types> for a list of valid types.
1455 =item B<--type-add I<TYPE>:I<FILTER>:I<FILTERARGS>>
1457 Files with the given FILTERARGS applied to the given FILTER
1458 are recognized as being of (the existing) type TYPE.
1459 See also L</"Defining your own types">.
1462 =item B<--type-set I<TYPE>:I<FILTER>:I<FILTERARGS>>
1464 Files with the given FILTERARGS applied to the given FILTER are recognized as
1465 being of type TYPE. This replaces an existing definition for type TYPE. See
1466 also L</"Defining your own types">.
1468 =item B<--type-del I<TYPE>>
1470 The filters associated with TYPE are removed from Ack, and are no longer considered
1473 =item B<-v>, B<--invert-match>
1475 Invert match: select non-matching lines
1479 Display version and copyright information.
1481 =item B<-w>, B<--word-regexp>
1483 Force PATTERN to match only whole words. The PATTERN is wrapped with
1484 C<\b> metacharacters.
1488 An abbreviation for B<--files-from=->; the list of files to search are read
1489 from standard input, with one line per file.
1493 Stops after reporting first match of any kind. This is different
1494 from B<--max-count=1> or B<-m1>, where only one match per file is
1495 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
1500 Display the all-important Bill The Cat logo. Note that the exact
1501 spelling of B<--thpppppt> is not important. It's checked against
1502 a regular expression.
1506 Check with the admiral for traps.
1510 Chocolate, Chocolate, Chocolate!
1514 =head1 THE .ackrc FILE
1516 The F<.ackrc> file contains command-line options that are prepended
1517 to the command line before processing. Multiple options may live
1518 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
1519 might look like this:
1521 # Always sort the files
1524 # Always color, even if piping to a another program
1527 # Use "less -r" as my pager
1530 Note that arguments with spaces in them do not need to be quoted,
1531 as they are not interpreted by the shell. Basically, each I<line>
1532 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
1534 F<ack> looks in several locations for F<.ackrc> files; the searching
1535 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
1536 files are not considered if B<--noenv> is specified on the command line.
1538 =head1 Defining your own types
1540 ack allows you to define your own types in addition to the predefined
1541 types. This is done with command line options that are best put into
1542 an F<.ackrc> file - then you do not have to define your types over and
1543 over again. In the following examples the options will always be shown
1544 on one command line so that they can be easily copy & pasted.
1546 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
1547 tells you, that perl files are files ending
1548 in .pl, .pm, .pod or .t. So what if you would like to include .xs
1549 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
1550 does this for you. B<--type-add> appends
1551 additional extensions to an existing type.
1553 If you want to define a new type, or completely redefine an existing
1554 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
1555 the type I<eiffel> to include files with
1556 the extensions .e or .eiffel. So to search for all eiffel files
1557 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
1558 As usual, you can also write B<--type=eiffel>
1559 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
1560 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
1561 and I<.xs> files no longer belong to the type I<cc>.
1563 When defining your own types in the F<.ackrc> file you have to use
1566 --type-set=eiffel:ext:e,eiffel
1568 or writing on separate lines
1573 The following does B<NOT> work in the F<.ackrc> file:
1575 --type-set eiffel:ext:e,eiffel
1578 In order to see all currently defined types, use I<--help-types>, e.g.
1579 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
1581 In addition to filtering based on extension (like ack 1.x allowed), ack 2
1582 offers additional filter types. The generic syntax is
1583 I<--type-set TYPE:FILTER:FILTERARGS>; I<FILTERARGS> depends on the value
1588 =item is:I<FILENAME>
1590 I<is> filters match the target filename exactly. It takes exactly one
1591 argument, which is the name of the file to match.
1595 --type-set make:is:Makefile
1597 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
1599 I<ext> filters match the extension of the target file against a list
1600 of extensions. No leading dot is needed for the extensions.
1604 --type-set perl:ext:pl,pm,t
1606 =item match:I<PATTERN>
1608 I<match> filters match the target filename against a regular expression.
1609 The regular expression is made case insensitive for the search.
1613 --type-set make:match:/(gnu)?makefile/
1615 =item firstlinematch:I<PATTERN>
1617 I<firstlinematch> matches the first line of the target file against a
1618 regular expression. Like I<match>, the regular expression is made
1623 --type-add perl:firstlinematch:/perl/
1627 More filter types may be made available in the future.
1629 =head1 ENVIRONMENT VARIABLES
1631 For commonly-used ack options, environment variables can make life
1632 much easier. These variables are ignored if B<--noenv> is specified
1633 on the command line.
1639 Specifies the location of the user's F<.ackrc> file. If this file doesn't
1640 exist, F<ack> looks in the default location.
1644 This variable specifies default options to be placed in front of
1645 any explicit options on the command line.
1647 =item ACK_COLOR_FILENAME
1649 Specifies the color of the filename when it's printed in B<--group>
1650 mode. By default, it's "bold green".
1652 The recognized attributes are clear, reset, dark, bold, underline,
1653 underscore, blink, reverse, concealed black, red, green, yellow,
1654 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
1655 on_magenta, on_cyan, and on_white. Case is not significant.
1656 Underline and underscore are equivalent, as are clear and reset.
1657 The color alone sets the foreground color, and on_color sets the
1660 This option can also be set with B<--color-filename>.
1662 =item ACK_COLOR_MATCH
1664 Specifies the color of the matching text when printed in B<--color>
1665 mode. By default, it's "black on_yellow".
1667 This option can also be set with B<--color-match>.
1669 See B<ACK_COLOR_FILENAME> for the color specifications.
1671 =item ACK_COLOR_LINENO
1673 Specifies the color of the line number when printed in B<--color>
1674 mode. By default, it's "bold yellow".
1676 This option can also be set with B<--color-lineno>.
1678 See B<ACK_COLOR_FILENAME> for the color specifications.
1682 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
1683 ack will send its output.
1685 Using C<ACK_PAGER> does not suppress grouping and coloring like
1686 piping output on the command-line does, except that on Windows
1687 ack will assume that C<ACK_PAGER> does not support color.
1689 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
1691 =item ACK_PAGER_COLOR
1693 Specifies a pager program that understands ANSI color sequences.
1694 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
1695 like piping output on the command-line does.
1697 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
1701 =head1 AVAILABLE COLORS
1703 F<ack> uses the colors available in Perl's L<Term::ANSIColor> module, which
1704 provides the following listed values. Note that case does not matter when using
1707 =head2 Foreground colors
1709 black red green yellow blue magenta cyan white
1711 bright_black bright_red bright_green bright_yellow
1712 bright_blue bright_magenta bright_cyan bright_white
1714 =head2 Background colors
1716 on_black on_red on_green on_yellow
1717 on_blue on_magenta on_cyan on_white
1719 on_bright_black on_bright_red on_bright_green on_bright_yellow
1720 on_bright_blue on_bright_magenta on_bright_cyan on_bright_white
1722 =head1 ACK & OTHER TOOLS
1724 =head2 Vim integration
1726 F<ack> integrates easily with the Vim text editor. Set this in your
1727 F<.vimrc> to use F<ack> instead of F<grep>:
1731 That example uses C<-k> to search through only files of the types ack
1732 knows about, but you may use other default flags. Now you can search
1733 with F<ack> and easily step through the results in Vim:
1735 :grep Dumper perllib
1737 Miles Sterrett has written a Vim plugin for F<ack> which allows you to use
1738 C<:Ack> instead of C<:grep>, as well as several other advanced features.
1740 L<https://github.com/mileszs/ack.vim>
1742 =head2 Emacs integration
1744 Phil Jackson put together an F<ack.el> extension that "provides a
1745 simple compilation mode ... has the ability to guess what files you
1746 want to search for based on the major-mode."
1748 L<http://www.shellarchive.co.uk/content/emacs.html>
1750 =head2 TextMate integration
1752 Pedro Melo is a TextMate user who writes "I spend my day mostly
1753 inside TextMate, and the built-in find-in-project sucks with large
1754 projects. So I hacked a TextMate command that was using find +
1755 grep to use ack. The result is the Search in Project with ack, and
1756 you can find it here:
1757 L<http://www.simplicidade.org/notes/archives/2008/03/search_in_proje.html>"
1759 =head2 Shell and Return Code
1761 For greater compatibility with I<grep>, I<ack> in normal use returns
1762 shell return or exit code of 0 only if something is found and 1 if
1765 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
1767 The I<grep> code 2 for errors is not used.
1769 If C<-f> or C<-g> are specified, then 0 is returned if at least one
1770 file is found. If no files are found, then 1 is returned.
1774 =head1 DEBUGGING ACK PROBLEMS
1776 If ack gives you output you're not expecting, start with a few simple steps.
1778 =head2 Use B<--noenv>
1780 Your environment variables and F<.ackrc> may be doing things you're
1781 not expecting, or forgotten you specified. Use B<--noenv> to ignore
1782 your environment and F<.ackrc>.
1784 =head2 Use B<-f> to see what files have been selected
1786 Ack's B<-f> was originally added as a debugging tool. If ack is
1787 not finding matches you think it should find, run F<ack -f> to see
1788 what files have been selected. You can also add the C<--show-types>
1789 options to show the type of each file selected.
1791 =head2 Use B<--dump>
1793 This lists the ackrc files that are loaded and the options loaded
1795 So for example you can find a list of directories that do not get searched or where filetypes are defined.
1799 =head2 Use the F<.ackrc> file.
1801 The F<.ackrc> is the place to put all your options you use most of
1802 the time but don't want to remember. Put all your --type-add and
1803 --type-set definitions in it. If you like --smart-case, set it
1804 there, too. I also set --sort-files there.
1806 =head2 Use F<-f> for working with big codesets
1808 Ack does more than search files. C<ack -f --perl> will create a
1809 list of all the Perl files in a tree, ideal for sending into F<xargs>.
1812 # Change all "this" to "that" in all Perl files in a tree.
1813 ack -f --perl | xargs perl -p -i -e's/this/that/g'
1817 perl -p -i -e's/this/that/g' $(ack -f --perl)
1819 =head2 Use F<-Q> when in doubt about metacharacters
1821 If you're searching for something with a regular expression
1822 metacharacter, most often a period in a filename or IP address, add
1823 the -Q to avoid false positives without all the backslashing. See
1824 the following example for more...
1826 =head2 Use ack to watch log files
1828 Here's one I used the other day to find trouble spots for a website
1829 visitor. The user had a problem loading F<troublesome.gif>, so I
1830 took the access log and scanned it with ack twice.
1832 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
1834 The first ack finds only the lines in the Apache log for the given
1835 IP. The second finds the match on my troublesome GIF, and shows
1836 the previous five lines from the log in each case.
1838 =head2 Examples of F<--output>
1840 Following variables are useful in the expansion string:
1846 The whole string matched by PATTERN.
1848 =item C<$1>, C<$2>, ...
1850 The contents of the 1st, 2nd ... bracketed group in PATTERN.
1854 The string before the match.
1858 The string after the match.
1862 For more details and other variables see
1863 L<http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions|perlvar>.
1865 This example shows how to add text around a particular pattern
1866 (in this case adding _ around word with "e")
1868 ack2.pl "\w*e\w*" quick.txt --output="$`_$&_$'"
1869 _The_ quick brown fox jumps over the lazy dog
1870 The quick brown fox jumps _over_ the lazy dog
1871 The quick brown fox jumps over _the_ lazy dog
1873 This shows how to pick out particular parts of a match using ( ) within regular expression.
1875 ack '=head(\d+)\s+(.*)' --output=' $1 : $2'
1876 input file contains "=head1 NAME"
1879 =head2 Share your knowledge
1881 Join the ack-users mailing list. Send me your tips and I may add
1886 =head2 Why isn't ack finding a match in (some file)?
1888 Probably because it's of a type that ack doesn't recognize. ack's
1889 searching behavior is driven by filetype. B<If ack doesn't know
1890 what kind of file it is, ack ignores the file.>
1892 Use the C<-f> switch to see a list of files that ack will search
1893 for you. You can use the C<--show-types> switch to show which type
1894 ack thinks each file is.
1896 =head2 Wouldn't it be great if F<ack> did search & replace?
1898 No, ack will always be read-only. Perl has a perfectly good way
1899 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
1902 You can certainly use ack to select your files to update. For
1903 example, to change all "foo" to "bar" in all PHP files, you can do
1904 this from the Unix shell:
1906 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
1908 =head2 Can I make ack recognize F<.xyz> files?
1910 Yes! Please see L</"Defining your own types">. If you think
1911 that F<ack> should recognize a type by default, please see
1914 =head2 There's already a program/package called ack.
1918 =head2 Why is it called ack if it's called ack-grep?
1920 The name of the program is "ack". Some packagers have called it
1921 "ack-grep" when creating packages because there's already a package
1922 out there called "ack" that has nothing to do with this ack.
1924 I suggest you make a symlink named F<ack> that points to F<ack-grep>
1925 because one of the crucial benefits of ack is having a name that's
1926 so short and simple to type.
1928 To do that, run this with F<sudo> or as root:
1930 ln -s /usr/bin/ack-grep /usr/bin/ack
1932 Alternatively, you could use a shell alias:
1940 =head2 What does F<ack> mean?
1942 Nothing. I wanted a name that was easy to type and that you could
1943 pronounce as a single syllable.
1945 =head2 Can I do multi-line regexes?
1947 No, ack does not support regexes that match multiple lines. Doing
1948 so would require reading in the entire file at a time.
1950 If you want to see lines near your match, use the C<--A>, C<--B>
1951 and C<--C> switches for displaying context.
1953 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
1955 ack treats command line options beginning with C<+> or C<-> as options; if you
1956 would like to search for these, you may prefix your search term with C<--> or
1957 use the C<--match> option. (However, don't forget that C<+> is a regular
1958 expression metacharacter!)
1960 =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex?
1962 The Perl language limits the repetition quanitifier to 32K. You
1963 can search for C<.{32767}> but not C<.{32768}>.
1965 =head1 ACKRC LOCATION SEMANTICS
1967 Ack can load its configuration from many sources. This list
1968 specifies the sources Ack looks for configuration; each one
1969 that is found is loaded in the order specified here, and
1970 each one overrides options set in any of the sources preceding
1971 it. (For example, if I set --sort-files in my user ackrc, and
1972 --nosort-files on the command line, the command line takes
1979 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
1980 using C<--ignore-ack-defaults>.
1982 =item * Global ackrc
1984 Options are then loaded from the global ackrc. This is located at
1985 C</etc/ackrc> on Unix-like systems.
1987 Under Windows XP and earlier, the ackrc is at
1988 C<C:\Documents and Settings\All Users\Application Data\ackrc>.
1990 Under Windows Vista/7, the global ackrc is at
1993 The C<--noenv> option prevents all ackrc files from being loaded.
1997 Options are then loaded from the user's ackrc. This is located at
1998 C<$HOME/.ackrc> on Unix-like systems.
2000 Under Windows XP and earlier, the user's ackrc is at
2001 C<C:\Documents and Settings\$USER\Application Data\ackrc>.
2003 Under Windows Vista/7, the user's ackrc is at
2004 <C:\Users\$USER\AppData\Roaming>.
2006 If you want to load a different user-level ackrc, it may be specified
2007 with the C<$ACKRC> environment variable.
2009 The C<--noenv> option prevents all ackrc files from being loaded.
2011 =item * Project ackrc
2013 Options are then loaded from the project ackrc. The project ackrc is
2014 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
2015 in the current directory, then the parent directory, then the grandparent
2016 directory, etc. This can be omitted using C<--noenv>.
2020 The C<--ackrc> option may be included on the command line to specify an
2021 ackrc file that can override all others. It is consulted even if C<--noenv>
2026 Options are then loaded from the environment variable C<ACK_OPTIONS>. This can
2027 be omitted using C<--noenv>.
2029 =item * Command line
2031 Options are then loaded from the command line.
2035 =head1 DIFFERENCES BETWEEN ACK 1.X AND ACK 2.X
2037 A lot of changes were made for ack 2; here is a list of them.
2039 =head2 GENERAL CHANGES
2045 When no selectors are specified, ack 1.x only searches through files that
2046 it can map to a file type. ack 2.x, by contrast, will search through
2047 every regular, non-binary file that is not explicitly ignored via
2048 B<--ignore-file> or B<--ignore-dir>. This is similar to the behavior of the
2049 B<-a/--all> option in ack 1.x.
2053 A more flexible filter system has been added, so that more powerful file types
2054 may be created by the user. For details, please consult
2055 L</"Defining your own types">.
2059 ack now loads multiple ackrc files; see L</"ACKRC LOCATION SEMANTICS"> for
2064 ack's default filter definitions aren't special; you may tell ack to
2065 completely disregard them if you don't like them.
2069 =head2 REMOVED OPTIONS
2075 Because of the change in default search behavior, the B<-a/--all> and
2076 B<-u/--unrestricted> options have been removed. In addition, the
2077 B<-k/--known-types> option was added to cause ack to behave with
2078 the default search behavior of ack 1.x.
2082 The B<-G> option has been removed. Two regular expressions on the
2083 command line was considered too confusing; to simulate B<-G>'s functionality,
2084 you may use the new B<-x> option to pipe filenames from one invocation of
2089 The B<--binary> option has been removed.
2093 The B<--skipped> option has been removed.
2097 The B<--text> option has been removed.
2101 The B<--invert-file-match> option has been removed. Instead, you may
2102 use B<-v> with B<-g>.
2106 =head2 CHANGED OPTIONS
2112 The options that modify the regular expression's behavior (B<-i>, B<-w>,
2113 B<-Q>, and B<-v>) may now be used with B<-g>.
2117 =head2 ADDED OPTIONS
2123 B<--files-from> was added so that a user may submit a list of filenames as
2124 a list of files to search.
2128 B<-x> was added to tell ack to accept a list of filenames via standard input;
2129 this list is the list of filenames that will be used for the search.
2133 B<-s> was added to tell ack to suppress error messages about non-existent or
2138 B<--ignore-directory> and B<--noignore-directory> were added as aliases for
2139 B<--ignore-dir> and B<--noignore-dir> respectively.
2143 B<--ignore-file> was added so that users may specify patterns of files to
2144 ignore (ex. /.*~$/).
2148 B<--dump> was added to allow users to easily find out which options are
2153 B<--create-ackrc> was added so that users may create custom ackrc files based
2154 on the default settings loaded by ack, and so that users may easily view those
2159 B<--type-del> was added to selectively remove file type definitions.
2163 B<--ignore-ack-defaults> was added so that users may ignore ack's default
2164 options in favor of their own.
2168 B<--bar> was added so ack users may consult Admiral Ackbar.
2174 Andy Lester, C<< <andy at petdance.com> >>
2178 Please report any bugs or feature requests to the issues list at
2179 Github: L<https://github.com/petdance/ack2/issues>
2183 All enhancement requests MUST first be posted to the ack-users
2184 mailing list at L<http://groups.google.com/group/ack-users>. I
2185 will not consider a request without it first getting seen by other
2186 ack users. This includes requests for new filetypes.
2188 There is a list of enhancements I want to make to F<ack> in the ack
2189 issues list at Github: L<https://github.com/petdance/ack2/issues>
2191 Patches are always welcome, but patches with tests get the most
2196 Support for and information about F<ack> can be found at:
2200 =item * The ack homepage
2202 L<http://beyondgrep.com/>
2204 =item * The ack-users mailing list
2206 L<http://groups.google.com/group/ack-users>
2208 =item * The ack issues list at Github
2210 L<https://github.com/petdance/ack2/issues>
2212 =item * AnnoCPAN: Annotated CPAN documentation
2214 L<http://annocpan.org/dist/ack>
2216 =item * CPAN Ratings
2218 L<http://cpanratings.perl.org/d/ack>
2222 L<http://search.cpan.org/dist/ack>
2224 =item * Git source repository
2226 L<https://github.com/petdance/ack2>
2230 =head1 ACKNOWLEDGEMENTS
2232 How appropriate to have I<ack>nowledgements!
2234 Thanks to everyone who has contributed to ack in any way, including
2239 RaE<uacute>l GundE<iacute>n,
2245 RaE<aacute>l GundE<aacute>n,
2281 Eric Van Dewoestine,
2290 Christopher J. Madsen,
2302 GE<aacute>bor SzabE<oacute>,
2305 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
2309 Mark Leighton Fisher,
2315 Nilson Santos F. Jr,
2320 Ask BjE<oslash>rn Hansen,
2324 Slaven ReziE<0x107>,
2334 =head1 COPYRIGHT & LICENSE
2336 Copyright 2005-2014 Andy Lester.
2338 This program is free software; you can redistribute it and/or modify
2339 it under the terms of the Artistic License v2.0.
2341 See http://www.perlfoundation.org/artistic_license_2_0 or the LICENSE.md
2342 file that comes with the ack distribution.
2355 $COPYRIGHT = 'Copyright 2005-2014 Andy Lester.';
2370 our $is_filter_mode;
2371 our $output_to_pipe;
2377 use File
::Spec
1.00015 ();
2380 # These have to be checked before any filehandle diddling.
2381 $output_to_pipe = not -t
*STDOUT
;
2382 $is_filter_mode = -p STDIN
;
2384 $is_cygwin = ($^O
eq 'cygwin');
2385 $is_windows = ($^O
eq 'MSWin32');
2386 $dir_sep_chars = $is_windows ?
quotemeta( '\\/' ) : quotemeta( File
::Spec
->catfile( '', '' ) );
2391 sub remove_dir_sep
{
2393 $path =~ s/[$dir_sep_chars]$//;
2401 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2406 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2410 require File
::Basename
;
2411 return File
::Basename
::basename
( $0 );
2416 sub filetypes_supported
{
2417 return keys %mappings;
2421 my $y = q{_ /|,\\'!.x',=(www)=, U };
2422 $y =~ tr/,x!w/\nOo_/;
2427 my $y = _get_thpppt();
2428 App::Ack::print( "$y ack $_[0]!\n" );
2436 3~!I#7#I"7#I!?!+!="+"="+!:!
2437 2?#I!7!I!?#I!7!I"+"=%+"=#
2438 1?"+!?*+!=#~"=!+#?"="+!
2439 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2440 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2442 ,,!?%I"?(+$=$~!=#:"~$:!~!
2443 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2444 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2445 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2446 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2447 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2448 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2449 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2450 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2451 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2452 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2453 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2454 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2455 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2456 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2457 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2458 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2459 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2460 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2461 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2462 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2463 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2464 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2465 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2466 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2467 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2468 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2469 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2470 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2471 7+:!,!~#,"=!7'I!?#I"7/+!7+
2472 77I!+!7!?!7!I"71+!7,
2475 return App::Ack::__pic($x);
2481 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2482 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2483 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2489 4.! $\! /M!~!.!8! +.!M# 4
2490 0,!.! (\! .~!M!N! ,+!I!.!M!.! 3
2491 /?!O!.!M!:! '\! .O!.! +~!Z!=!N!.! 4
2492 ..! !D!Z!.!Z!.! '\! 9=!M".! 6
2493 /.! !.!~!M".! '\! 8~! 9
2495 4.! &:!M! !N"M# !M"N!M! #D!M&=! =
2496 :M!7!M#:! !~!M!7!,!$!M!:! #.! !O!N!.!M!:!M# ;
2497 8Z!M"~!N!$!D!.!N!?! !I!N!.! (?!M! !M!,!D!M".! 9
2498 (?!Z!M!N!:! )=!M!O!8!.!M!+!M! !M!,! !O!M! +,!M!.!M!~!Z!N!M!:! &:!~! 0
2499 &8!7!.!~!M"D!M!,! &M!?!=!8! !M!,!O! !M!+! !+!O!.!M! $M#~! !.!8!M!Z!.!M! !O!M"Z! %:!~!M!Z!M!Z!.! +
2500 &:!M!7!,! *M!.!Z!M! !8"M!.!M!~! !.!M!.!=! #~!8!.!M! !7!M! "N!Z#I! !D!M!,!M!.! $."M!,! !M!.! *
2501 2$!O! "N! !.!M!I! !7" "M! "+!O! !~!M! !d!O!.!7!I!M!.! !.!O!=!M!.! !M",!M!.! %.!$!O!D! +
2502 1~!O! "M!+! !8!$! "M! "?!O! %Z!8!D!M!?!8!I!O!7!M! #M!.!M! "M",!M! 4
2503 07!~! ".!8! !.!M! "I!+! !.!M! &Z!D!.!7!=!M! !:!.!M! #:!8"+! !.!+!8! !8! 3
2504 /~!M! #N! !~!M!$! !.!M! !.!M" &~!M! "~!M!O! "D! $M! !8! "M!,!M!+!D!.! 1
2505 #.! #?!M!N!.! #~!O! $M!.!7!$! "?" !?!~!M! '7!8!?!M!.!+!M"O! $?"$!D! !.!O! !$!7!I!.! 0
2506 $,!M!:!O!?! ".! !?!=! $=!:!O! !M! "M! !M! !+!$! (.! +.!M! !M!.! !8! !+"Z!~! $:!M!$! !.! '
2507 #.!8!.!I!$! $7!I! %M" !=!M! !~!M!D! "7!I! .I!O! %?!=!,!D! !,!M! !D!~!8!~! %D!M! (
2508 #.!M"?! $=!O! %=!N! "8!.! !Z!M! #M!~! (M!:! #.!M" &O! !M!.! !?!,! !8!.!N!~! $8!N!M!,!.! %
2509 *$!O! &M!,! "O! !.!M!.! #M! (~!M( &O!.! !7! "M! !.!M!.!M!,! #.!M! !M! &
2510 )=!8!.! $.!M!O!.! "$!.!I!N! !I!M# (7!M(I! %D"Z!M! "=!I! "M! !M!:! #~!D! '
2511 )D! &8!N!:! ".!O! !M!="M! "M! (7!M) %." !M!D!."M!.! !$!=! !M!,! +
2512 (M! &+!.!M! #Z!7!O!M!.!~!8! +,!M#D!?!M#D! #.!Z!M#,!Z!?! !~!N! "N!.! !M! +
2513 'D!:! %$!D! !?! #M!Z! !8!.! !M"?!7!?!7! '+!I!D! !?!O!:!M!:! ":!M!:! !M!7".!M! "8!+! !:!D! !.!M! *
2514 %.!O!:! $.!O!+! !D!.! #M! "M!.!+!N!I!Z! "7!M!N!M!N!?!I!7!Z!=!M'D"~! #M!.!8!$! !:! !.!M! "N!?! !,!O! )
2515 !.!?!M!:!M!I! %8!,! "M!.! #M! "N! !M!.! !M!.! !+!~! !.!M!.! ':!M! $M! $M!Z!$! !M!.! "D! "M! "?!M! (
2516 !7!8! !+!I! ".! "$!=! ":!$! "+! !M!.! !O! !M!I!M".! !=!~! ",!O! '=!M! $$!,! #N!:! ":!8!.! !D!~! !,!M!.! !:!M!.! &
2517 !:!,!.! &Z" #D! !.!8!."M!.! !8!?!Z!M!.!M! #Z!~! !?!M!Z!.! %~!O!.!8!$!N!8!O!I!:!~! !+! #M!.! !.!M!.! !+!M! ".!~!M!+! $
2518 !.! 'D!I! #?!M!.!M!,! !.!Z! !.!8! #M&O!I!?! (~!I!M"." !M!Z!.! !M!N!.! "+!$!.! "M!.! !M!?!.! "8!M! $
2519 (O!8! $M! !M!.! ".!:! !+!=! #M! #.!M! !+" *$!M":!.! !M!~! "M!7! #M! #7!Z! "M"$!M!.! !.! #
2520 '$!Z! #.!7!+!M! $.!,! !+!:! #N! #.!M!.!+!M! +D!M! #=!N! ":!O! #=!M! #Z!D! $M!I! %
2521 $,! ".! $.!M" %$!.! !?!~! "+!7!." !.!M!,! !M! *,!N!M!.$M!?! "D!,! #M!.! #N! +
2522 ,M!Z! &M! "I!,! "M! %I!M! !?!=!.! (Z!8!M! $:!M!.! !,!M! $D! #.!M!.! )
2523 +8!O! &.!8! "I!,! !~!M! &N!M! !M!D! '?!N!O!." $?!7! "?!~! #M!.! #I!D!.! (
2524 3M!,! "N!.! !D" &.!+!M!.! !M":!.":!M!7!M!D! 'M!.! "M!.! "M!,! $I! )
2525 3I! #M! "M!,! !:! &.!M" ".!,! !.!$!M!I! #.! !:! !.!M!?! "N!+! ".! /
2526 1M!,! #.!M!8!M!=!.! +~!N"O!Z"~! *+!M!.! "M! 2
2527 0.!M! &M!.! 8:! %.!M!Z! "M!=! *O!,! %
2528 0?!$! &N! )." .,! %."M! ":!M!.! 0
2529 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0
2531 return App
::Ack
::__pic
($x);
2535 my($compressed) = @_;
2536 $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2537 App
::Ack
::print( $compressed );
2543 my $help_arg = shift || 0;
2545 return show_help_types
() if $help_arg =~ /^types?/;
2547 App
::Ack
::print( <<"END_OF_HELP" );
2548 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2550 Search for PATTERN in each source file in the tree from the current
2551 directory on down. If any files or directories are specified, then
2552 only those files and directories are checked. ack may also search
2553 STDIN, but only if no file or directory arguments are specified,
2554 or if one of them is "-".
2556 Default switches may be specified in ACK_OPTIONS environment variable or
2557 an .ackrc file. If you want no dependency on the environment, turn it
2560 Example: ack -i select
2563 -i, --ignore-case Ignore case distinctions in PATTERN
2564 --[no]smart-case Ignore case distinctions in PATTERN,
2565 only if PATTERN contains no upper case.
2566 Ignored if -i is specified
2567 -v, --invert-match Invert match: select non-matching lines
2568 -w, --word-regexp Force PATTERN to match only whole words
2569 -Q, --literal Quote all metacharacters; PATTERN is literal
2572 --lines=NUM Only print line(s) NUM of each file
2573 -l, --files-with-matches Only print filenames containing matches
2574 -L, --files-without-matches Only print filenames with no matches
2575 --output=expr Output the evaluation of expr for each line
2576 (turns off text highlighting)
2577 -o Show only the part of a line matching PATTERN
2578 Same as --output='\$&'
2579 --passthru Print all lines, whether matching or not
2580 --match PATTERN Specify PATTERN explicitly.
2581 -m, --max-count=NUM Stop searching in each file after NUM matches
2582 -1 Stop searching after one match of any kind
2583 -H, --with-filename Print the filename for each match (default:
2584 on unless explicitly searching a single file)
2585 -h, --no-filename Suppress the prefixing filename on output
2586 -c, --count Show number of lines matching per file
2587 --[no]column Show the column number of the first match
2589 -A NUM, --after-context=NUM Print NUM lines of trailing context after
2591 -B NUM, --before-context=NUM Print NUM lines of leading context before
2593 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2595 --print0 Print null byte as separator between filenames,
2596 only works with -f, -g, -l, -L or -c.
2598 -s Suppress error messages about nonexistent or
2603 --pager=COMMAND Pipes all ack output through COMMAND. For
2604 example, --pager="less -R". Ignored if output
2606 --nopager Do not send output through a pager. Cancels
2607 any setting in ~/.ackrc, ACK_PAGER or
2609 --[no]heading Print a filename heading above each file's
2610 results. (default: on when used interactively)
2611 --[no]break Print a break between results from different
2612 files. (default: on when used interactively)
2613 --group Same as --heading --break
2614 --nogroup Same as --noheading --nobreak
2615 --[no]color Highlight the matching text (default: on unless
2616 output is redirected, or on Windows)
2617 --[no]colour Same as --[no]color
2618 --color-filename=COLOR
2620 --color-lineno=COLOR Set the color for filenames, matches, and line
2622 --flush Flush output immediately, even when ack is used
2623 non-interactively (when output goes to a pipe or
2628 -f Only print the files selected, without
2629 searching. The PATTERN must not be specified.
2630 -g Same as -f, but only select files matching
2632 --sort-files Sort the found files lexically.
2633 --show-types Show which types each file has.
2634 --files-from=FILE Read the list of files to search from FILE.
2635 -x Read the list of files to search from STDIN.
2637 File inclusion/exclusion:
2638 --[no]ignore-dir=name Add/remove directory from list of ignored dirs
2639 --[no]ignore-directory=name Synonym for ignore-dir
2640 --ignore-file=filter Add filter for ignoring files
2641 -r, -R, --recurse Recurse into subdirectories (default: on)
2642 -n, --no-recurse No descending into subdirectories
2643 --[no]follow Follow symlinks. Default is off.
2644 -k, --known-types Include only files of types that ack recognizes.
2646 --type=X Include only X files, where X is a recognized
2648 --type=noX Exclude X files.
2649 See "ack --help-types" for supported filetypes.
2651 File type specification:
2652 --type-set TYPE:FILTER:FILTERARGS
2653 Files with the given FILTERARGS applied to the
2654 given FILTER are recognized as being of type
2655 TYPE. This replaces an existing definition for
2657 --type-add TYPE:FILTER:FILTERARGS
2658 Files with the given FILTERARGS applied to the
2659 given FILTER are recognized as being type TYPE.
2660 --type-del TYPE Removes all filters associated with TYPE.
2664 --[no]env Ignore environment variables and global ackrc
2665 files. --env is legal but redundant.
2666 --ackrc=filename Specify an ackrc file to use
2667 --ignore-ack-defaults Ignore default definitions included with ack.
2668 --create-ackrc Outputs a default ackrc for your customization
2670 --help, -? This help
2671 --help-types Display all known types
2672 --dump Dump information on which options are loaded
2674 --[no]filter Force ack to treat standard input as a pipe
2675 (--filter) or tty (--nofilter)
2677 --version Display version & copyright
2678 --thpppt Bill the Cat
2679 --bar The warning admiral
2680 --cathy Chocolate! Chocolate! Chocolate!
2682 Exit status is 0 if match, 1 if no match.
2684 ack's home page is at http://beyondgrep.com/
2686 The full ack manual is available by running "ack --man".
2688 This is version $VERSION of ack. Run "ack --version" for full version info.
2696 sub show_help_types {
2697 App::Ack::print( <<'END_OF_HELP' );
2698 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2700 The following is the list of filetypes supported by ack. You can
2701 specify a file type with the --type=TYPE format, or the --TYPE
2702 format. For example, both --type=perl and --perl work.
2704 Note that some extensions may appear in multiple types. For example,
2705 .pod files are both Perl and Parrot.
2709 my @types = filetypes_supported();
2712 $maxlen = length if $maxlen < length;
2714 for my $type ( sort @types ) {
2715 next if $type =~ /^-/; # Stuff to not show
2716 my $ext_list = $mappings{$type};
2718 if ( ref $ext_list ) {
2719 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
2721 App::Ack::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2730 Pod::Usage::pod2usage({
2731 -input => $App::Ack::orig_program_name,
2740 sub get_version_statement {
2743 my $copyright = get_copyright();
2744 my $this_perl = $Config::Config{perlpath};
2746 my $ext = $Config::Config{_exe};
2747 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2749 my $ver = sprintf( '%vd', $^V );
2751 return <<"END_OF_VERSION
";
2753 Running under Perl $ver at $this_perl
2757 This program is free software. You may modify or distribute it
2758 under the terms of the Artistic License v2.0.
2763 sub print_version_statement {
2764 App::Ack::print( get_version_statement() );
2775 # print*() subs added in order to make it easy for a third party
2776 # module (such as App::Wack) to redefine the display methods
2777 # and show the results in a different way.
2778 sub print { print {$fh} @_; return; }
2779 sub print_first_filename { App::Ack::print( $_[0], "\n" ); return; }
2780 sub print_blank_line { App::Ack::print( "\n" ); return; }
2781 sub print_separator { App::Ack::print( "--\n" ); return; }
2782 sub print_filename { App::Ack::print( $_[0], $_[1] ); return; }
2783 sub print_line_no { App::Ack::print( $_[0], $_[1] ); return; }
2784 sub print_column_no { App::Ack::print( $_[0], $_[1] ); return; }
2786 my $filename = shift;
2787 my $nmatches = shift;
2790 my $show_filename = shift;
2792 if ($show_filename) {
2793 App::Ack::print( $filename );
2794 App::Ack::print( ':', $nmatches ) if $count;
2797 App::Ack::print( $nmatches ) if $count;
2799 App::Ack::print( $ors );
2805 my $filename = shift;
2807 my $show_filename = shift;
2809 if ($show_filename) {
2810 App::Ack::print( $filename, ':0', $ors );
2813 App::Ack::print( '0', $ors );
2820 my $command = shift;
2822 return if App::Ack::output_to_pipe();
2825 if ( not open( $pager, '|-', $command ) ) {
2826 App::Ack::die( qq{Unable to pipe to pager "$command": $!} );
2834 sub output_to_pipe {
2835 return $output_to_pipe;
2840 my $nmatches = shift;
2842 my $rc = $nmatches ? 0 : 1;
2848 1; # End of App::Ack
2849 package App::Ack::Resource;
2859 Carp::confess( 'Must be overloaded' );
2883 sub needs_line_scan {
2908 package App::Ack::Resources;
2915 sub _generate_error_handler {
2918 if ( $opt->{dont_report_bad_filenames} ) {
2921 # XXX restricting to specific error messages for now; I would
2922 # prefer a different way of doing this
2923 if ( $msg =~ /Permission denied/ ) {
2926 App::Ack::warn( $msg );
2932 App::Ack::warn( $msg );
2943 my $self = bless {}, $class;
2945 my $file_filter = undef;
2946 my $descend_filter = $opt->{descend_filter};
2949 $descend_filter = sub {
2955 File::Next::files( {
2956 file_filter => $opt->{file_filter},
2957 descend_filter => $descend_filter,
2958 error_handler => _generate_error_handler($opt),
2959 warning_handler => sub {},
2960 sort_files => $opt->{sort_files},
2961 follow_symlinks => $opt->{follow},
2974 File::Next::from_file( {
2975 error_handler => _generate_error_handler($opt),
2976 warning_handler => _generate_error_handler($opt),
2977 sort_files => $opt->{sort_files},
2978 }, $file ) or return undef;
2985 # This is for reading input lines from STDIN, not the list of files from STDIN
2990 my $self = bless {}, $class;
2992 my $has_been_called = 0;
2994 $self->{iter} = sub {
2995 if ( !$has_been_called ) {
2996 $has_been_called = 1;
3008 my $file = $self->{iter}->() or return;
3010 return App::Ack::Resource::Basic->new( $file );
3014 package App::Ack::Resource::Basic;
3023 our @ISA = 'App::Ack::Resource';
3030 my $filename = shift;
3033 filename => $filename,
3038 if ( $self->{filename} eq '-' ) {
3039 $self->{fh} = *STDIN;
3040 $self->{opened} = 1;
3048 return $_[0]->{filename};
3053 sub needs_line_scan {
3057 return 1 if $opt->{v};
3059 my $size = -s $self->{fh};
3063 elsif ( $size > 100_000 ) {
3068 my $rc = sysread( $self->{fh}, $buffer, $size );
3069 if ( !defined($rc) && $App::Ack::report_bad_filenames ) {
3070 App::Ack::warn( "$self->{filename
}: $!" );
3073 return 0 unless $rc && ( $rc == $size );
3075 my $regex = $opt->{regex};
3076 return $buffer =~ /$regex/m;
3083 # return if we haven't opened the file yet
3084 if ( !defined($self->{fh}) ) {
3088 if( !seek( $self->{fh}, 0, 0 ) && $App::Ack::report_bad_filenames ) {
3089 App::Ack::warn( "$self->{filename
}: $!" );
3099 # return if we haven't opened the file yet
3100 if ( !defined($self->{fh}) ) {
3104 if ( !close($self->{fh}) && $App::Ack::report_bad_filenames ) {
3105 App::Ack::warn( $self->name() . ": $!" );
3108 $self->{opened} = 0;
3117 return __PACKAGE__->new($self->name);
3123 my $fh = $self->open();
3125 if ( !exists $self->{firstliney} ) {
3127 my $rc = sysread( $fh, $buffer, 250 );
3128 unless($rc) { # XXX handle this better?
3131 $buffer =~ s/[\r\n].*//s;
3132 $self->{firstliney} = $buffer;
3138 return $self->{firstliney};
3144 return $self->{fh} if $self->{opened};
3146 if ( ! open $self->{fh}, '<', $self->{filename} ) {
3150 $self->{opened} = 1;
3156 package App::Ack::ConfigDefault;
3164 return split( /\n/, _options_block() );
3169 return grep { /./ && !/^#/ } options();
3173 sub _options_block {
3174 my $lines = <<'HERE';
3175 # This is the default ackrc for ack version ==VERSION==.
3177 # There are four different ways to match
3179 # is: Match the filename exactly
3181 # ext: Match the extension of the filename exactly
3183 # match: Match the filename against a Perl regular expression
3185 # firstlinematch: Match the first 250 characters of the first line
3186 # of text against a Perl regular expression. This is only for
3187 # the --type-add option.
3190 ### Directories to ignore
3193 # http://bazaar.canonical.com/
3194 --ignore-directory=is:.bzr
3197 # http://freecode.com/projects/codeville
3198 --ignore-directory=is:.cdv
3200 # Interface Builder (Xcode)
3201 # http://en.wikipedia.org/wiki/Interface_Builder
3202 --ignore-directory=is:~.dep
3203 --ignore-directory=is:~.dot
3204 --ignore-directory=is:~.nib
3205 --ignore-directory=is:~.plst
3208 # http://git-scm.com/
3209 --ignore-directory=is:.git
3212 # http://mercurial.selenic.com/
3213 --ignore-directory=is:.hg
3216 # http://directory.fsf.org/wiki/Quilt
3217 --ignore-directory=is:.pc
3220 # http://subversion.tigris.org/
3221 --ignore-directory=is:.svn
3224 # http://www.monotone.ca/
3225 --ignore-directory=is:_MTN
3228 # http://savannah.nongnu.org/projects/cvs
3229 --ignore-directory=is:CVS
3232 # http://www.gnu.org/software/rcs/
3233 --ignore-directory=is:RCS
3236 # http://en.wikipedia.org/wiki/Source_Code_Control_System
3237 --ignore-directory=is:SCCS
3241 --ignore-directory=is:_darcs
3244 --ignore-directory=is:_sgbak
3247 # http://www.gnu.org/software/autoconf/
3248 --ignore-directory=is:autom4te.cache
3250 # Perl module building
3251 --ignore-directory=is:blib
3252 --ignore-directory=is:_build
3254 # Perl Devel::Cover module's output directory
3255 # https://metacpan.org/release/Devel-Cover
3256 --ignore-directory=is:cover_db
3258 # Node modules created by npm
3259 --ignore-directory=is:node_modules
3262 # http://www.cmake.org/
3263 --ignore-directory=is:CMakeFiles
3265 # Eclipse workspace folder
3266 # http://eclipse.org/
3267 --ignore-directory=is:.metadata
3269 # Cabal (Haskell) sandboxes
3270 # http://www.haskell.org/cabal/users-guide/installing-packages.html
3271 --ignore-directory=is:.cabal-sandbox
3276 --ignore-file=ext:bak
3277 --ignore-file=match:/~$/
3280 --ignore-file=match:/^#.+#$/
3282 # vi/vim swap files http://vim.org/
3283 --ignore-file=match:/[._].*\.swp$/
3286 --ignore-file=match:/core\.\d+$/
3288 # minified Javascript
3289 --ignore-file=match:/[.-]min[.]js$/
3290 --ignore-file=match:/[.]js[.]min$/
3293 --ignore-file=match:/[.]min[.]css$/
3294 --ignore-file=match:/[.]css[.]min$/
3296 # JS and CSS source maps
3297 --ignore-file=match:/[.]js[.]map$/
3298 --ignore-file=match:/[.]css[.]map$/
3300 # PDFs, because they pass Perl's -T detection
3301 --ignore-file=ext:pdf
3303 # Common graphics, just as an optimization
3304 --ignore-file=ext:gif,jpg,jpeg,png
3307 ### Filetypes defined
3311 --type-add=perl:ext:pl,pm,pod,t,psgi
3312 --type-add=perl:firstlinematch:/^#!.*\bperl/
3315 --type-add=perltest:ext:t
3318 # http://www.gnu.org/s/make/
3319 --type-add=make:ext:mk
3320 --type-add=make:ext:mak
3321 --type-add=make:is:makefile
3322 --type-add=make:is:Makefile
3323 --type-add=make:is:Makefile.Debug
3324 --type-add=make:is:Makefile.Release
3327 # http://rake.rubyforge.org/
3328 --type-add=rake:is:Rakefile
3331 # http://www.cmake.org/
3332 --type-add=cmake:is:CMakeLists.txt
3333 --type-add=cmake:ext:cmake
3336 --type-add=actionscript:ext:as,mxml
3339 # http://www.adaic.org/
3340 --type-add=ada:ext:ada,adb,ads
3343 # http://msdn.microsoft.com/en-us/library/aa286483.aspx
3344 --type-add=asp:ext:asp
3347 # http://www.asp.net/
3348 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
3351 --type-add=asm:ext:asm,s
3354 --type-add=batch:ext:bat,cmd
3357 # http://en.wikipedia.org/wiki/ColdFusion
3358 --type-add=cfmx:ext:cfc,cfm,cfml
3361 # http://clojure.org/
3362 --type-add=clojure:ext:clj
3365 # .xs are Perl C files
3366 --type-add=cc:ext:c,h,xs
3372 # http://coffeescript.org/
3373 --type-add=coffeescript:ext:coffee
3376 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
3379 --type-add=csharp:ext:cs
3382 # http://www.w3.org/Style/CSS/
3383 --type-add=css:ext:css
3386 # http://www.dartlang.org/
3387 --type-add=dart:ext:dart
3390 # http://en.wikipedia.org/wiki/Embarcadero_Delphi
3391 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
3394 # http://elixir-lang.org/
3395 --type-add=elixir:ext:ex,exs
3398 # http://www.gnu.org/software/emacs
3399 --type-add=elisp:ext:el
3402 # http://www.erlang.org/
3403 --type-add=erlang:ext:erl,hrl
3406 # http://en.wikipedia.org/wiki/Fortran
3407 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
3410 # http://golang.org/
3411 --type-add=go:ext:go
3414 # http://groovy.codehaus.org/
3415 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
3418 # http://www.haskell.org/
3419 --type-add=haskell:ext:hs,lhs
3422 --type-add=html:ext:htm,html
3425 # http://jade-lang.com/
3426 --type-add=jade:ext:jade
3429 # http://www.oracle.com/technetwork/java/index.html
3430 --type-add=java:ext:java,properties
3433 --type-add=js:ext:js
3436 # http://www.oracle.com/technetwork/java/javaee/jsp/index.html
3437 --type-add=jsp:ext:jsp,jspx,jhtm,jhtml
3440 # http://www.json.org/
3441 --type-add=json:ext:json
3444 # http://www.lesscss.org/
3445 --type-add=less:ext:less
3448 # http://common-lisp.net/
3449 --type-add=lisp:ext:lisp,lsp
3452 # http://www.lua.org/
3453 --type-add=lua:ext:lua
3454 --type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
3457 --type-add=objc:ext:m,h
3460 --type-add=objcpp:ext:mm,h
3463 # http://caml.inria.fr/
3464 --type-add=ocaml:ext:ml,mli
3467 # http://en.wikipedia.org/wiki/MATLAB
3468 --type-add=matlab:ext:m
3471 # http://www.parrot.org/
3472 --type-add=parrot:ext:pir,pasm,pmc,ops,pod,pg,tg
3475 # http://www.php.net/
3476 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
3477 --type-add=php:firstlinematch:/^#!.*\bphp/
3481 --type-add=plone:ext:pt,cpt,metadata,cpy,py
3484 # http://www.python.org/
3485 --type-add=python:ext:py
3486 --type-add=python:firstlinematch:/^#!.*\bpython/
3489 # http://www.r-project.org/
3493 # http://docutils.sourceforge.net/rst.html
3494 --type-add=rst:ext:rst
3497 # http://www.ruby-lang.org/
3498 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
3499 --type-add=ruby:is:Rakefile
3500 --type-add=ruby:firstlinematch:/^#!.*\bruby/
3503 # http://www.rust-lang.org/
3504 --type-add=rust:ext:rs
3507 # http://sass-lang.com
3508 --type-add=sass:ext:sass,scss
3511 # http://www.scala-lang.org/
3512 --type-add=scala:ext:scala
3515 # http://groups.csail.mit.edu/mac/projects/scheme/
3516 --type-add=scheme:ext:scm,ss
3519 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
3520 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
3523 # http://www.smalltalk.org/
3524 --type-add=smalltalk:ext:st
3527 # http://www.smarty.net/
3528 --type-add=smarty:ext:tpl
3531 # http://www.iso.org/iso/catalogue_detail.htm?csnumber=45498
3532 --type-add=sql:ext:sql,ctl
3535 # http://learnboost.github.io/stylus/
3536 --type-add=stylus:ext:styl
3539 # http://www.tcl.tk/
3540 --type-add=tcl:ext:tcl,itcl,itk
3543 # http://www.latex-project.org/
3544 --type-add=tex:ext:tex,cls,sty
3546 # Template Toolkit (Perl)
3547 # http://template-toolkit.org/
3548 --type-add=tt:ext:tt,tt2,ttml
3551 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
3554 --type-add=verilog:ext:v,vh,sv
3557 # http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
3558 --type-add=vhdl:ext:vhd,vhdl
3561 # http://www.vim.org/
3562 --type-add=vim:ext:vim
3565 # http://www.w3.org/TR/REC-xml/
3566 --type-add=xml:ext:xml,dtd,xsl,xslt,ent
3567 --type-add=xml:firstlinematch:/<[?]xml/
3571 --type-add=yaml:ext:yaml,yml
3573 $lines =~ s/==VERSION==/$App::Ack::VERSION/sm;
3579 package App
::Ack
::ConfigFinder
;
3586 use File
::Spec
3.00;
3588 use if ($^O
eq 'MSWin32'), 'Win32';
3594 return bless {}, $class;
3598 sub _remove_redundancies
{
3602 foreach my $config (@configs) {
3603 my $key = $config->{path
};
3604 if ( not $App::Ack
::is_windows
) {
3605 # On Unix, uniquify on inode.
3606 my ($dev, $inode) = (stat $key)[0, 1];
3607 $key = "$dev:$inode" if defined $dev;
3609 undef $config if $seen{$key}++;
3611 return grep { defined } @configs;
3615 sub _check_for_ackrc
{
3616 return unless defined $_[0];
3618 my @files = grep { -f
}
3619 map { File
::Spec
->catfile(@_, $_) }
3622 die File
::Spec
->catdir(@_) . " contains both .ackrc and _ackrc.\n" .
3623 "Please remove one of those files.\n"
3626 return wantarray ?
@files : $files[0];
3627 } # end _check_for_ackrc
3631 sub find_config_files
{
3634 if ( $App::Ack
::is_windows
) {
3635 push @config_files, map { +{ path
=> File
::Spec
->catfile($_, 'ackrc') } } (
3636 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3637 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3641 push @config_files, { path
=> '/etc/ackrc' };
3645 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3646 push @config_files, { path
=> $ENV{'ACKRC'} };
3649 push @config_files, map { +{ path
=> $_ } } _check_for_ackrc
($ENV{'HOME'});
3652 # XXX This should go through some untainted cwd-fetching function, and not get untainted inline like this.
3653 my $cwd = Cwd
::getcwd
();
3656 my @dirs = File
::Spec
->splitdir( $cwd );
3658 my $ackrc = _check_for_ackrc
(@dirs);
3659 if(defined $ackrc) {
3660 push @config_files, { project
=> 1, path
=> $ackrc };
3666 # We only test for existence here, so if the file is deleted out from under us, this will fail later.
3667 return _remove_redundancies
( @config_files );
3675 return unless defined $file && -e
$file;
3679 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
3680 while ( my $line = <$fh> ) {
3685 next if $line eq '';
3686 next if $line =~ /^\s*#/;
3688 push( @lines, $line );
3690 close $fh or App
::Ack
::die( "Unable to close $file: $!" );
3696 package App
::Ack
::ConfigLoader
;
3702 use Getopt
::Long
2.35 ();
3703 use Text
::ParseWords
3.1 ();
3706 my @INVALID_COMBINATIONS;
3709 my @context = qw( -A -B -C --after-context --before-context --context );
3710 my @pretty = qw( --heading --group --break );
3711 my @filename = qw( -h -H --with-filename --no-filename );
3713 @INVALID_COMBINATIONS = (
3715 [qw(-l)] => [@context, @pretty, @filename, qw(-L -o --passthru --output --max-count --column -f -g --show-types)],
3716 [qw(-L)] => [@context, @pretty, @filename, qw(-l -o --passthru --output --max-count --column -f -g --show-types -c --count)],
3717 [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)],
3718 [qw(-o)] => [@context, qw(--output -c --count --column --column -f --show-types)],
3719 [qw(--passthru)] => [@context, qw(--output --column -m --max-count -1 -c --count -f -g)],
3720 [qw(--output)] => [@context, qw(-c --count -f -g)],
3721 [qw(--match)] => [qw(-f -g)],
3722 [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
3723 [qw(-h --no-filename)] => [qw(-H --with-filename -f -g --group --heading)],
3724 [qw(-H --with-filename)] => [qw(-h --no-filename -f -g)],
3725 [qw(-c --count)] => [@context, @pretty, qw(--column -f -g)],
3726 [qw(--column)] => [qw(-f -g)],
3727 [@context] => [qw(-f -g)],
3728 [qw(-f)] => [qw(-g), @pretty],
3729 [qw(-g)] => [qw(-f), @pretty],
3734 sub process_filter_spec
{
3737 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3738 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3740 return ( $type_name,
3741 App
::Ack
::Filter
->create_filter($ext_type, split(/,/, $arguments)) );
3743 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3744 my ( $type_name, $extensions ) = ( $1, $2 );
3746 my @extensions = split(/,/, $extensions);
3747 foreach my $extension ( @extensions ) {
3748 $extension =~ s/^[.]//;
3751 return ( $type_name, App
::Ack
::Filter
->create_filter('ext', @extensions) );
3754 Carp
::croak
"invalid filter specification '$spec'";
3759 sub uninvert_filter
{
3760 my ( $opt, @filters ) = @_;
3762 return unless defined $opt->{filters
} && @filters;
3764 # Loop through all the registered filters. If we hit one that
3765 # matches this extension and it's inverted, we need to delete it from
3767 for ( my $i = 0; $i < @
{ $opt->{filters
} }; $i++ ) {
3768 my $opt_filter = @
{ $opt->{filters
} }[$i];
3770 # XXX Do a real list comparison? This just checks string equivalence.
3771 if ( $opt_filter->is_inverted() && "$opt_filter->{filter}" eq "@filters" ) {
3772 splice @
{ $opt->{filters
} }, $i, 1;
3779 sub process_filetypes
{
3780 my ( $opt, $arg_sources ) = @_;
3782 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3783 Getopt
::Long
::Configure
(
3788 my %additional_specs;
3790 my $add_spec = sub {
3791 my ( undef, $spec ) = @_;
3793 my ( $name, $filter ) = process_filter_spec
($spec);
3795 push @
{ $App::Ack
::mappings
{$name} }, $filter;
3797 $additional_specs{$name . '!'} = sub {
3798 my ( undef, $value ) = @_;
3800 my @filters = @
{ $App::Ack
::mappings
{$name} };
3802 @filters = map { $_->invert() } @filters;
3805 uninvert_filter
( $opt, @filters );
3808 push @
{ $opt->{'filters'} }, @filters;
3812 my $set_spec = sub {
3813 my ( undef, $spec ) = @_;
3815 my ( $name, $filter ) = process_filter_spec
($spec);
3817 $App::Ack
::mappings
{$name} = [ $filter ];
3819 $additional_specs{$name . '!'} = sub {
3820 my ( undef, $value ) = @_;
3822 my @filters = @
{ $App::Ack
::mappings
{$name} };
3824 @filters = map { $_->invert() } @filters;
3827 push @
{ $opt->{'filters'} }, @filters;
3831 my $delete_spec = sub {
3832 my ( undef, $name ) = @_;
3834 delete $App::Ack
::mappings
{$name};
3835 delete $additional_specs{$name . '!'};
3838 my %type_arg_specs = (
3839 'type-add=s' => $add_spec,
3840 'type-set=s' => $set_spec,
3841 'type-del=s' => $delete_spec,
3844 foreach my $source (@
{$arg_sources}) {
3845 my ( $source_name, $args ) = @
{$source}{qw
/name contents/};
3848 # $args are modified in place, so no need to munge $arg_sources
3849 local @ARGV = @
{$args};
3850 Getopt
::Long
::GetOptions
(%type_arg_specs);
3854 ( undef, $source->{contents
} ) =
3855 Getopt
::Long
::GetOptionsFromString
($args, %type_arg_specs);
3859 $additional_specs{'k|known-types'} = sub {
3860 my ( undef, $value ) = @_;
3862 my @filters = map { @
{$_} } values(%App::Ack
::mappings
);
3864 push @
{ $opt->{'filters'} }, @filters;
3867 return \
%additional_specs;
3871 sub removed_option
{
3872 my ( $option, $explanation ) = @_;
3874 $explanation ||= '';
3876 warn "Option '$option' is not valid in ack 2\n$explanation";
3883 my ( $opt, $extra_specs ) = @_;
3885 my $dash_a_explanation = <<'EOT';
3886 This is because we now have -k/--known-types which makes it only select files
3887 of known types, rather than any text file (which is the behavior of ack 1.x).
3888 You may have options in a .ackrc, or in the ACKRC_OPTIONS environment variable.
3889 Try using the --dump flag.
3894 1 => sub { $opt->{1} = $opt->{m
} = 1 },
3895 'A|after-context=i' => \
$opt->{after_context
},
3896 'B|before-context=i'
3897 => \
$opt->{before_context
},
3898 'C|context:i' => sub { shift; my $val = shift; $opt->{before_context
} = $opt->{after_context
} = ($val || 2) },
3899 'a' => removed_option
('-a', $dash_a_explanation),
3900 'all' => removed_option
('--all', $dash_a_explanation),
3901 'break!' => \
$opt->{break},
3902 c
=> \
$opt->{count
},
3903 'color|colour!' => \
$opt->{color
},
3904 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
3905 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
3906 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
3907 'column!' => \
$opt->{column
},
3908 count
=> \
$opt->{count
},
3909 'create-ackrc' => sub { print "$_\n" for ( '--ignore-ack-defaults', App
::Ack
::ConfigDefault
::options
() ); exit; },
3911 my ( undef, $value ) = @_;
3914 $opt->{noenv_seen
} = 1;
3918 'files-from=s' => \
$opt->{files_from
},
3919 'filter!' => \
$App::Ack
::is_filter_mode
,
3920 flush
=> \
$opt->{flush
},
3921 'follow!' => \
$opt->{follow
},
3923 G
=> removed_option
('-G'),
3924 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
3925 'heading!' => \
$opt->{heading
},
3926 'h|no-filename' => \
$opt->{h
},
3927 'H|with-filename' => \
$opt->{H
},
3928 'i|ignore-case' => \
$opt->{i
},
3929 'ignore-directory|ignore-dir=s' => sub {
3930 my ( undef, $dir ) = @_;
3932 $dir = App
::Ack
::remove_dir_sep
( $dir );
3933 if ( $dir !~ /^(?:is|match):/ ) {
3934 $dir = 'is:' . $dir;
3936 push @
{ $opt->{idirs
} }, $dir;
3938 'ignore-file=s' => sub {
3939 my ( undef, $file ) = @_;
3940 push @
{ $opt->{ifiles
} }, $file;
3942 'lines=s' => sub { shift; my $val = shift; push @
{$opt->{lines
}}, $val },
3943 'l|files-with-matches'
3945 'L|files-without-matches'
3947 'm|max-count=i' => \
$opt->{m
},
3948 'match=s' => \
$opt->{regex
},
3949 'n|no-recurse' => \
$opt->{n
},
3950 o
=> sub { $opt->{output
} = '$&' },
3951 'output=s' => \
$opt->{output
},
3953 my ( undef, $value ) = @_;
3955 $opt->{pager
} = $value || $ENV{PAGER
};
3957 'noignore-directory|noignore-dir=s'
3959 my ( undef, $dir ) = @_;
3961 # XXX can you do --noignore-dir=match,...?
3962 $dir = App
::Ack
::remove_dir_sep
( $dir );
3963 if ( $dir !~ /^(?:is|match):/ ) {
3964 $dir = 'is:' . $dir;
3966 if ( $dir !~ /^(?:is|match):/ ) {
3967 Carp
::croak
("invalid noignore-directory argument: '$dir'");
3970 @
{ $opt->{idirs
} } = grep {
3972 } @
{ $opt->{idirs
} };
3974 push @
{ $opt->{no_ignore_dirs
} }, $dir;
3976 'nopager' => sub { $opt->{pager
} = undef },
3977 'passthru' => \
$opt->{passthru
},
3978 'print0' => \
$opt->{print0
},
3979 'Q|literal' => \
$opt->{Q
},
3980 'r|R|recurse' => sub { $opt->{n
} = 0 },
3981 's' => \
$opt->{dont_report_bad_filenames
},
3982 'show-types' => \
$opt->{show_types
},
3983 'smart-case!' => \
$opt->{smart_case
},
3984 'sort-files' => \
$opt->{sort_files
},
3986 my ( $getopt, $value ) = @_;
3989 if ( $value =~ s/^no// ) {
3993 my $callback = $extra_specs->{ $value . '!' };
3996 $callback->( $getopt, $cb_value );
3999 Carp
::croak
( "Unknown type '$value'" );
4002 'u' => removed_option
('-u'),
4003 'unrestricted' => removed_option
('--unrestricted'),
4004 'v|invert-match' => \
$opt->{v
},
4005 'w|word-regexp' => \
$opt->{w
},
4006 'x' => sub { $opt->{files_from
} = '-' },
4008 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
4009 'help|?:s' => sub { shift; App
::Ack
::show_help
(@_); exit; },
4010 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
4011 'man' => sub { App
::Ack
::show_man
(); exit; },
4012 $extra_specs ?
%{$extra_specs} : (),
4018 my ( $opt, $extra_specs, $arg_sources ) = @_;
4020 # Start with default options, minus some annoying ones.
4021 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4022 Getopt
::Long
::Configure
(
4028 my $is_help_types_active;
4030 foreach my $source (@
{$arg_sources}) {
4031 my ( $source_name, $args ) = @
{$source}{qw
/name contents/};
4033 if ( $source_name eq 'ARGV' ) {
4034 $argv_source = $args;
4039 if ( $argv_source ) { # This *should* always be true, but you never know...
4040 my @copy = @
{$argv_source};
4041 local @ARGV = @copy;
4043 Getopt
::Long
::Configure
('pass_through');
4045 Getopt
::Long
::GetOptions
(
4046 'help-types' => \
$is_help_types_active,
4049 Getopt
::Long
::Configure
('no_pass_through');
4052 my $arg_specs = get_arg_spec
($opt, $extra_specs);
4054 foreach my $source (@
{$arg_sources}) {
4055 my ( $source_name, $args ) = @
{$source}{qw
/name contents/};
4057 my $args_for_source = $arg_specs;
4059 if ( $source->{project
} ) {
4061 die "Options --output, --pager and --match are forbidden in project .ackrc files.\n";
4064 $args_for_source = { %$args_for_source,
4065 'output=s' => $illegal,
4066 'pager:s' => $illegal,
4067 'match=s' => $illegal,
4073 local @ARGV = @
{$args};
4074 $ret = Getopt
::Long
::GetOptions
( %{$args_for_source} );
4078 ( $ret, $source->{contents
} ) =
4079 Getopt
::Long
::GetOptionsFromString
( $args, %{$args_for_source} );
4082 if ( !$is_help_types_active ) {
4083 my $where = $source_name eq 'ARGV' ?
'on command line' : "in $source_name";
4084 App
::Ack
::die( "Invalid option $where" );
4087 if ( $opt->{noenv_seen
} ) {
4088 App
::Ack
::die( "--noenv found in $source_name" );
4092 # XXX We need to check on a -- in the middle of a non-ARGV source
4098 sub should_dump_options
{
4099 my ( $sources ) = @_;
4101 foreach my $source (@
{$sources}) {
4102 my ( $name, $options ) = @
{$source}{qw
/name contents/};
4104 if($name eq 'ARGV') {
4106 local @ARGV = @
{$options};
4107 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
4108 Getopt
::Long
::GetOptions
(
4111 @
{$options} = @ARGV;
4119 sub explode_sources
{
4120 my ( $sources ) = @_;
4124 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
4127 my $arg_spec = get_arg_spec
(\
%opt);
4129 my $add_type = sub {
4130 my ( undef, $arg ) = @_;
4133 if ( $arg =~ /(\w+)=/) {
4134 $arg_spec->{$1} = sub {};
4137 ( $arg ) = split /:/, $arg;
4138 $arg_spec->{$arg} = sub {};
4142 my $del_type = sub {
4143 my ( undef, $arg ) = @_;
4145 delete $arg_spec->{$arg};
4148 foreach my $source (@
{$sources}) {
4149 my ( $name, $options ) = @
{$source}{qw
/name contents/};
4150 if ( ref($options) ne 'ARRAY' ) {
4151 $source->{contents
} = $options =
4152 [ Text
::ParseWords
::shellwords
($options) ];
4155 for my $j ( 0 .. @
{$options}-1 ) {
4156 next unless $options->[$j] =~ /^-/;
4157 my @chunk = ( $options->[$j] );
4158 push @chunk, $options->[$j] while ++$j < @
{$options} && $options->[$j] !~ /^-/;
4162 local @ARGV = @chunk;
4163 Getopt
::Long
::GetOptions
(
4164 'type-add=s' => $add_type,
4165 'type-set=s' => $add_type,
4166 'type-del=s' => $del_type,
4168 Getopt
::Long
::GetOptions
( %{$arg_spec} );
4170 push @new_sources, {
4177 return \
@new_sources;
4184 my $first_a = $a->[0];
4185 my $first_b = $b->[0];
4187 $first_a =~ s/^--?//;
4188 $first_b =~ s/^--?//;
4190 return $first_a cmp $first_b;
4195 my ( $sources ) = @_;
4197 $sources = explode_sources
($sources);
4202 foreach my $source (@
{$sources}) {
4203 my ( $name, $contents ) = @
{$source}{qw
/name contents/};
4204 if ( not $opts_by_source{$name} ) {
4205 $opts_by_source{$name} = [];
4206 push @source_names, $name;
4208 push @
{$opts_by_source{$name}}, $contents;
4211 foreach my $name (@source_names) {
4212 my $contents = $opts_by_source{$name};
4215 print '=' x
length($name), "\n";
4216 print ' ', join(' ', @
{$_}), "\n" foreach sort { compare_opts
($a, $b) } @
{$contents};
4223 sub remove_default_options_if_needed
{
4224 my ( $sources ) = @_;
4228 foreach my $index ( 0 .. $#{$sources} ) {
4229 if ( $sources->[$index]{'name'} eq 'Defaults' ) {
4230 $default_index = $index;
4235 return $sources unless defined $default_index;
4237 my $should_remove = 0;
4239 # Start with default options, minus some annoying ones.
4240 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4241 Getopt
::Long
::Configure
(
4247 foreach my $index ( $default_index + 1 .. $#{$sources} ) {
4248 my ( $name, $args ) = @
{$sources->[$index]}{qw
/name contents/};
4251 local @ARGV = @
{$args};
4252 Getopt
::Long
::GetOptions
(
4253 'ignore-ack-defaults' => \
$should_remove,
4258 ( undef, $sources->[$index]{contents
} ) = Getopt
::Long
::GetOptionsFromString
($args,
4259 'ignore-ack-defaults' => \
$should_remove,
4264 Getopt
::Long
::Configure
('default');
4265 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4267 return $sources unless $should_remove;
4269 my @copy = @
{$sources};
4270 splice @copy, $default_index, 1;
4275 sub check_for_mutually_exclusive_options
{
4276 my ( $arg_sources ) = @_;
4278 my %mutually_exclusive_with;
4279 my @copy = @
{$arg_sources};
4281 for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
4282 my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
4284 foreach my $l_opt ( @
{$lhs} ) {
4285 foreach my $r_opt ( @
{$rhs} ) {
4286 push @
{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
4287 push @
{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
4295 my $source = shift @copy;
4296 my ( $source_name, $args ) = @
{$source}{qw
/name contents/};
4297 $args = ref($args) ?
[ @
{$args} ] : [ Text
::ParseWords
::shellwords
($args) ];
4299 foreach my $opt ( @
{$args} ) {
4300 next unless $opt =~ /^[-+]/;
4301 last if $opt eq '--';
4303 if( $opt =~ /^(.*)=/ ) {
4306 elsif ( $opt =~ /^(-[^-]).+/ ) {
4310 $set_opts{ $opt } = 1;
4312 my $mutex_opts = $mutually_exclusive_with{ $opt };
4314 next unless $mutex_opts;
4316 foreach my $mutex_opt ( @
{$mutex_opts} ) {
4317 if($set_opts{ $mutex_opt }) {
4318 die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
4327 my $arg_sources = \
@_;
4330 pager
=> $ENV{ACK_PAGER_COLOR
} || $ENV{ACK_PAGER
},
4333 check_for_mutually_exclusive_options
($arg_sources);
4335 $arg_sources = remove_default_options_if_needed
($arg_sources);
4337 if ( should_dump_options
($arg_sources) ) {
4338 dump_options
($arg_sources);
4342 my $type_specs = process_filetypes
(\
%opt, $arg_sources);
4343 process_other
(\
%opt, $type_specs, $arg_sources);
4344 while ( @
{$arg_sources} ) {
4345 my $source = shift @
{$arg_sources};
4346 my ( $source_name, $args ) = @
{$source}{qw
/name contents/};
4348 # All of our sources should be transformed into an array ref
4350 if ( $source_name eq 'ARGV' ) {
4354 Carp
::croak
"source '$source_name' has extra arguments!";
4358 Carp
::croak
'The impossible has occurred!';
4361 my $filters = ($opt{filters
} ||= []);
4363 # Throw the default filter in if no others are selected.
4364 if ( not grep { !$_->is_inverted() } @
{$filters} ) {
4365 push @
{$filters}, App
::Ack
::Filter
::Default
->new();
4371 sub retrieve_arg_sources
{
4377 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4378 Getopt
::Long
::Configure
('pass_through');
4379 Getopt
::Long
::Configure
('no_auto_abbrev');
4381 Getopt
::Long
::GetOptions
(
4383 'ackrc=s' => \
$ackrc,
4386 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4391 my $finder = App
::Ack
::ConfigFinder
->new;
4392 @files = $finder->find_config_files;
4395 # We explicitly use open so we get a nice error message.
4396 # XXX This is a potential race condition!.
4397 if(open my $fh, '<', $ackrc) {
4401 die "Unable to load ackrc '$ackrc': $!"
4403 push( @files, { path
=> $ackrc } );
4406 push @arg_sources, {
4408 contents
=> [ App
::Ack
::ConfigDefault
::options_clean
() ],
4411 foreach my $file ( @files) {
4412 my @lines = App
::Ack
::ConfigFinder
::read_rcfile
($file->{path
});
4415 push @arg_sources, {
4416 name
=> $file->{path
},
4417 contents
=> \
@lines,
4418 project
=> $file->{project
},
4423 if ( $ENV{ACK_OPTIONS
} && !$noenv ) {
4424 push @arg_sources, {
4425 name
=> 'ACK_OPTIONS',
4426 contents
=> $ENV{ACK_OPTIONS
},
4430 push @arg_sources, {
4432 contents
=> [ @ARGV ],
4435 return @arg_sources;
4438 1; # End of App::Ack::ConfigLoader
4439 package App
::Ack
::Filter
;
4444 '""' => 'to_string';
4452 my ( undef, $type, @args ) = @_;
4454 if ( my $package = $filter_types{$type} ) {
4455 return $package->new(@args);
4457 Carp
::croak
"Unknown filter type '$type'";
4461 sub register_filter
{
4462 my ( undef, $type, $package ) = @_;
4464 $filter_types{$type} = $package;
4473 return App
::Ack
::Filter
::Inverse
->new( $self );
4485 return '(unimplemented to_string)';
4496 package App
::Ack
::Filter
::Extension
;
4501 our @ISA = 'App::Ack::Filter';
4506 my ( $class, @extensions ) = @_;
4508 my $exts = join('|', map { "\Q$_\E"} @extensions);
4509 my $re = qr/[.](?:$exts)$/i;
4512 extensions
=> \
@extensions,
4514 groupname
=> 'ExtensionGroup',
4519 return App
::Ack
::Filter
::ExtensionGroup
->new();
4523 my ( $self, $resource ) = @_;
4525 my $re = $self->{'regex'};
4527 return $resource->name =~ /$re/;
4533 my $re = $self->{'regex'};
4535 return ref($self) . " - $re";
4541 my $exts = $self->{'extensions'};
4543 return join(' ', map { ".$_" } @
{$exts});
4547 App
::Ack
::Filter
->register_filter(ext
=> __PACKAGE__
);
4551 package App
::Ack
::Filter
::FirstLineMatch
;
4556 our @ISA = 'App::Ack::Filter';
4560 my ( $class, $re ) = @_;
4562 $re =~ s{^/|/$}{}g; # XXX validate?
4570 # This test reads the first 250 characters of a file, then just uses the
4571 # first line found in that. This prevents reading something like an entire
4572 # .min.js file (which might be only one "line" long) into memory.
4575 my ( $self, $resource ) = @_;
4577 my $re = $self->{'regex'};
4579 my $line = $resource->firstliney;
4581 return $line =~ /$re/;
4587 my $re = $self->{'regex'};
4589 return ref($self) . " - $re";
4595 (my $re = $self->{regex
}) =~ s{\([^:]*:(.*)\)$}{$1};
4597 return "first line matches /$re/";
4601 App
::Ack
::Filter
->register_filter(firstlinematch
=> __PACKAGE__
);
4605 package App
::Ack
::Filter
::Is
;
4610 our @ISA = 'App::Ack::Filter';
4613 use File
::Spec
3.00 ();
4616 my ( $class, $filename ) = @_;
4619 filename
=> $filename,
4620 groupname
=> 'IsGroup',
4625 return App
::Ack
::Filter
::IsGroup
->new();
4629 my ( $self, $resource ) = @_;
4631 my $filename = $self->{'filename'};
4632 my $base = (File
::Spec
->splitpath($resource->name))[2];
4634 return $base eq $filename;
4640 my $filename = $self->{'filename'};
4642 return ref($self) . " - $filename";
4648 my $filename = $self->{'filename'};
4654 App
::Ack
::Filter
->register_filter(is
=> __PACKAGE__
);
4658 package App
::Ack
::Filter
::Match
;
4663 our @ISA = 'App::Ack::Filter';
4666 use File
::Spec
3.00;
4669 my ( $class, $re ) = @_;
4671 $re =~ s{^/|/$}{}g; # XXX validate?
4680 my ( $self, $resource ) = @_;
4682 my $re = $self->{'regex'};
4683 my $base = (File
::Spec
->splitpath($resource->name))[2];
4685 return $base =~ /$re/;
4691 my $re = $self->{'regex'};
4693 print ref($self) . " - $re";
4701 my $re = $self->{'regex'};
4703 return "filename matches $re";
4707 App
::Ack
::Filter
->register_filter(match
=> __PACKAGE__
);
4711 package App
::Ack
::Filter
::Default
;
4716 our @ISA = 'App::Ack::Filter';
4722 return bless {}, $class;
4726 my ( $self, $resource ) = @_;
4728 return -T
$resource->name;
4732 package App
::Ack
::Filter
::Inverse
;
4737 our @ISA = 'App::Ack::Filter';
4741 my ( $class, $filter ) = @_;
4749 my ( $self, $resource ) = @_;
4751 my $filter = $self->{'filter'};
4752 return !$filter->filter( $resource );
4758 return $self->{'filter'};
4768 my $filter = $self->{'filter'};
4774 package App
::Ack
::Filter
::Collection
;
4779 our @ISA = 'App::Ack::Filter';
4792 my ( $self, $resource ) = @_;
4794 for my $group (values %{$self->{'groups'}}) {
4795 if ($group->filter($resource)) {
4800 for my $filter (@
{$self->{'ungrouped'}}) {
4801 if ($filter->filter($resource)) {
4810 my ( $self, $filter ) = @_;
4812 if (exists $filter->{'groupname'}) {
4813 my $group = ($self->{groups
}->{$filter->{groupname
}} ||= $filter->create_group());
4814 $group->add($filter);
4817 push @
{$self->{'ungrouped'}}, $filter;
4826 return ref($self) . " - $self";
4832 my $ungrouped = $self->{'ungrouped'};
4834 return join(', ', map { "($_)" } @
{$ungrouped});
4838 package App
::Ack
::Filter
::IsGroup
;
4843 our @ISA = 'App::Ack::Filter';
4846 use File
::Spec
3.00 ();
4857 my ( $self, $filter ) = @_;
4859 $self->{data
}->{ $filter->{filename
} } = 1;
4865 my ( $self, $resource ) = @_;
4867 my $data = $self->{'data'};
4868 my $base = (File
::Spec
->splitpath($resource->name))[2];
4870 return exists $data->{$base};
4876 return ref($self) . " - $self";
4882 return join(' ', keys %{$self->{data
}});
4886 package App
::Ack
::Filter
::ExtensionGroup
;
4891 our @ISA = 'App::Ack::Filter';
4903 my ( $self, $filter ) = @_;
4905 foreach my $ext (@
{$filter->{extensions
}}) {
4906 $self->{data
}->{lc $ext} = 1;
4913 my ( $self, $resource ) = @_;
4915 if ($resource->name =~ /[.]([^.]*)$/) {
4916 return exists $self->{'data'}->{lc $1};
4925 return ref($self) . " - $self";
4931 return join(' ', map { ".$_" } sort keys %{$self->{data
}});
4941 our $VERSION = '1.12';
4947 our $name; # name of the current file
4948 our $dir; # dir of the current file
4950 our %files_defaults;
4955 file_filter
=> undef,
4956 descend_filter
=> undef,
4957 error_handler
=> sub { CORE
::die @_ },
4958 warning_handler
=> sub { CORE
::warn @_ },
4959 sort_files
=> undef,
4960 follow_symlinks
=> 1,
4963 %skip_dirs = map {($_,1)} (File
::Spec
->curdir, File
::Spec
->updir);
4968 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
4970 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
4971 my $filter = $parms->{file_filter
};
4975 my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 );
4976 if ( -f
$fullpath || -p
$fullpath || $fullpath =~ m{^/dev/fd} ) {
4979 local $File::Next
::dir
= $dirname;
4980 local $File::Next
::name
= $fullpath;
4981 next if not $filter->();
4983 return wantarray ?
($dirname,$file,$fullpath) : $fullpath;
4986 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
5000 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5002 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5003 my $err = $parms->{error_handler
};
5004 my $warn = $parms->{error_handler
};
5006 my $filename = $queue[1];
5008 if ( !defined($filename) ) {
5009 $err->( 'Must pass a filename to from_file()' );
5014 if ( $filename eq '-' ) {
5018 if ( !open( $fh, '<', $filename ) ) {
5019 $err->( "Unable to open $filename: $!" );
5023 my $filter = $parms->{file_filter
};
5026 local $/ = $parms->{nul_separated} ? "\x00" : $/;
5027 while ( my $fullpath = <$fh> ) {
5029 next unless $fullpath =~ /./;
5030 if ( not ( -f
$fullpath || -p _
) ) {
5031 $warn->( "$fullpath: No such file" );
5035 my ($volume,$dirname,$file) = File
::Spec
->splitpath( $fullpath );
5038 local $File::Next
::dir
= $dirname;
5039 local $File::Next
::name
= $fullpath;
5040 next if not $filter->();
5042 return wantarray ?
($dirname,$file,$fullpath) : $fullpath;
5050 sub _bad_invocation
{
5051 my $good = (caller(1))[3];
5053 $bad =~ s/(.+)::/$1->/;
5054 return "$good must not be invoked as $bad";
5057 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
5058 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
5063 my @parts = split( /\//, $path );
5065 return $path if @parts < 2;
5067 return File
::Spec
->catfile( @parts );
5073 my $defaults = shift;
5074 my $passed_parms = ref $_[0] eq 'HASH' ?
{%{+shift}} : {}; # copy parm hash
5076 my %passed_parms = %{$passed_parms};
5079 for my $key ( keys %{$defaults} ) {
5081 exists $passed_parms{$key}
5082 ?
delete $passed_parms{$key}
5083 : $defaults->{$key};
5086 # Any leftover keys are bogus
5087 for my $badkey ( keys %passed_parms ) {
5088 my $sub = (caller(1))[3];
5089 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
5092 # If it's not a code ref, assume standard sort
5093 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
5094 $parms->{sort_files
} = \
&sort_standard
;
5099 my $start = reslash
( $_ );
5101 push @queue, ($start,undef,$start);
5104 push @queue, (undef,$start,$start);
5108 return ($parms,@queue);
5112 sub _candidate_files
{
5114 my $dirname = shift;
5117 if ( !opendir $dh, $dirname ) {
5118 $parms->{error_handler
}->( "$dirname: $!" );
5123 my $descend_filter = $parms->{descend_filter
};
5124 my $follow_symlinks = $parms->{follow_symlinks
};
5125 my $sort_sub = $parms->{sort_files
};
5127 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
5130 # Only do directory checking if we have a descend_filter
5131 my $fullpath = File
::Spec
->catdir( $dirname, $file );
5132 if ( !$follow_symlinks ) {
5133 next if -l
$fullpath;
5137 if ( $descend_filter ) {
5138 if ( $has_stat ?
(-d _
) : (-d
$fullpath) ) {
5139 local $File::Next
::dir
= $fullpath;
5141 next if not $descend_filter->();
5145 push( @newfiles, [ $dirname, $file, $fullpath ] );
5148 push( @newfiles, $dirname, $file, $fullpath );
5154 return map { @
{$_} } sort $sort_sub @newfiles;
5161 1; # End of File::Next