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/beyondgrep/ack2
8 # and submit patches against the individual files
16 our $VERSION = '2.22'; # Check https://beyondgrep.com/ for updates
19 use Getopt
::Long
2.38 ();
25 # XXX Don't make this so brute force
26 # See also: https://github.com/beyondgrep/ack2/issues/89
28 our $opt_after_context;
29 our $opt_before_context;
34 our $opt_show_filename;
48 # Flag if we need any context tracking.
49 our $is_tracking_context;
51 # These are all our globals.
54 $App::Ack
::orig_program_name
= $0;
55 $0 = join(' ', 'ack', $0);
56 if ( $App::Ack
::VERSION
ne $main::VERSION
) {
57 App
::Ack
::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
60 # Do preliminary arg checking;
61 my $env_is_usable = 1;
62 for my $arg ( @ARGV ) {
63 last if ( $arg eq '--' );
65 # Get the --thpppt, --bar, --cathy checking out of the way.
66 $arg =~ /^--th[pt]+t+$/ and App
::Ack
::thpppt
($arg);
67 $arg eq '--bar' and App
::Ack
::ackbar
();
68 $arg eq '--cathy' and App
::Ack
::cathy
();
70 # See if we want to ignore the environment. (Don't tell Al Gore.)
71 $arg eq '--env' and $env_is_usable = 1;
72 $arg eq '--noenv' and $env_is_usable = 0;
75 if ( !$env_is_usable ) {
76 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
81 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
82 Getopt
::Long
::Configure
('pass_through', 'no_auto_abbrev');
83 Getopt
::Long
::GetOptions
(
84 'help' => sub { App
::Ack
::show_help
(); exit; },
85 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
86 'man' => sub { App
::Ack
::show_man
(); exit; },
88 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
91 App
::Ack
::show_help
();
98 sub _compile_descend_filter
{
102 my $dont_ignore_dirs = 0;
104 for my $filter (@{$opt->{idirs
} || []}) {
105 if ($filter->is_inverted()) {
113 # If we have one or more --noignore-dir directives, we can't ignore
114 # entire subdirectory hierarchies, so we return an "accept all"
115 # filter and scrutinize the files more in _compile_file_filter.
116 return if $dont_ignore_dirs;
117 return unless $idirs;
119 $idirs = $opt->{idirs
};
122 my $resource = App
::Ack
::Resource-
>new($File::Next
::dir
);
123 return !grep { $_->filter($resource) } @{$idirs};
127 sub _compile_file_filter
{
128 my ( $opt, $start ) = @_;
130 my $ifiles_filters = $opt->{ifiles
};
132 my $filters = $opt->{'filters'} || [];
133 my $direct_filters = App
::Ack
::Filter
::Collection-
>new();
134 my $inverse_filters = App
::Ack
::Filter
::Collection-
>new();
136 foreach my $filter (@{$filters}) {
137 if ($filter->is_inverted()) {
138 # We want to check if files match the uninverted filters
139 $inverse_filters->add($filter->invert());
142 $direct_filters->add($filter);
146 my %is_member_of_starting_set = map { (get_file_id
($_) => 1) } @{$start};
148 my @ignore_dir_filter = @{$opt->{idirs
} || []};
149 my @is_inverted = map { $_->is_inverted() } @ignore_dir_filter;
150 # This depends on InverseFilter->invert returning the original filter (for optimization).
151 @ignore_dir_filter = map { $_->is_inverted() ? $_->invert() : $_ } @ignore_dir_filter;
152 my $dont_ignore_dir_filter = grep { $_ } @is_inverted;
153 my $previous_dir = '';
154 my $previous_dir_ignore_result;
158 if ( $File::Next
::name
=~ /$opt_regex/ && $opt_v ) {
161 if ( $File::Next
::name
!~ /$opt_regex/ && !$opt_v ) {
165 # ack always selects files that are specified on the command
166 # line, regardless of filetype. If you want to ack a JPEG,
167 # and say "ack foo whatever.jpg" it will do it for you.
168 return 1 if $is_member_of_starting_set{ get_file_id
($File::Next
::name
) };
170 if ( $dont_ignore_dir_filter ) {
171 if ( $previous_dir eq $File::Next
::dir
) {
172 if ( $previous_dir_ignore_result ) {
177 my @dirs = File
::Spec-
>splitdir($File::Next
::dir
);
181 for ( my $i = 0; $i < @dirs; $i++) {
182 my $dir_rsrc = App
::Ack
::Resource-
>new(File
::Spec-
>catfile(@dirs[0 .. $i]));
185 for my $filter (@ignore_dir_filter) {
186 if ( $filter->filter($dir_rsrc) ) {
187 $is_ignoring = !$is_inverted[$j];
193 $previous_dir = $File::Next
::dir
;
194 $previous_dir_ignore_result = $is_ignoring;
196 if ( $is_ignoring ) {
202 # Ignore named pipes found in directory searching. Named
203 # pipes created by subprocesses get specified on the command
204 # line, so the rule of "always select whatever is on the
205 # command line" wins.
206 return 0 if -p
$File::Next
::name
;
208 # We can't handle unreadable filenames; report them.
210 use filetest
'access';
212 if ( not -R
$File::Next
::name
) {
213 if ( $App::Ack
::report_bad_filenames
) {
214 App
::Ack
::warn( "${File::Next::name}: cannot open file for reading" );
220 my $resource = App
::Ack
::Resource-
>new($File::Next
::name
);
222 if ( $ifiles_filters && $ifiles_filters->filter($resource) ) {
226 my $match_found = $direct_filters->filter($resource);
228 # Don't bother invoking inverse filters unless we consider the current resource a match
229 if ( $match_found && $inverse_filters->filter( $resource ) ) {
237 my $resource = shift;
240 my @types = filetypes
( $resource );
241 my $types = join( ',', @types );
242 my $arrow = @types ? ' => ' : ' =>';
243 App
::Ack
::print( $resource->name, $arrow, join( ',', @types ), $ors );
248 # Set default colors, load Term::ANSIColor
250 eval 'use Term::ANSIColor 1.10 ()';
251 eval 'use Win32::Console::ANSI' if $App::Ack
::is_windows
;
253 $ENV{ACK_COLOR_MATCH
} ||= 'black on_yellow';
254 $ENV{ACK_COLOR_FILENAME
} ||= 'bold green';
255 $ENV{ACK_COLOR_LINENO
} ||= 'bold yellow';
261 my ( $resource ) = @_;
265 foreach my $k (keys %App::Ack
::mappings
) {
266 my $filters = $App::Ack
::mappings
{$k};
268 foreach my $filter (@{$filters}) {
269 # Clone the resource.
270 my $clone = $resource->clone;
271 if ( $filter->filter($clone) ) {
278 # http://search.cpan.org/dist/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm
279 @matches = sort @matches;
283 # Returns a (fairly) unique identifier for a file.
284 # Use this function to compare two files to see if they're
285 # equal (ie. the same file, but with a different path/links/etc).
287 my ( $filename ) = @_;
289 if ( $App::Ack
::is_windows
) {
290 return File
::Next
::reslash
( $filename );
293 # XXX Is this the best method? It always hits the FS.
294 if( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
295 return join(':', $dev, $inode);
298 # XXX This could be better.
304 # Returns a regex object based on a string and command-line options.
305 # Dies when the regex $str is undefined (i.e. not given on command line).
311 defined $str or App
::Ack
::die( 'No regular expression found.' );
313 $str = quotemeta( $str ) if $opt->{Q
};
315 my $pristine_str = $str;
318 $str = "\\b$str" if $pristine_str =~ /^\w/;
319 $str = "$str\\b" if $pristine_str =~ /\w$/;
322 my $regex_is_lc = $str eq lc $str;
323 if ( $opt->{i
} || ($opt->{smart_case
} && $regex_is_lc) ) {
327 my $re = eval { qr/$str/m };
329 die "Invalid regex '$str':\n $@";
336 my $match_column_number;
340 # Number of context lines
341 my $n_before_ctx_lines;
342 my $n_after_ctx_lines;
344 # Array to keep track of lines that might be required for a "before" context
345 my @before_context_buf;
346 # Position to insert next line in @before_context_buf
347 my $before_context_pos;
349 # Number of "after" context lines still pending
350 my $after_context_pending;
352 # Number of latest line that got printed
358 my $has_printed_something;
361 $has_printed_something = 0;
364 # Set up context tracking variables.
365 sub set_up_line_context
{
366 $n_before_ctx_lines = $opt_output ? 0 : ($opt_before_context || 0);
367 $n_after_ctx_lines = $opt_output ? 0 : ($opt_after_context || 0);
369 @before_context_buf = (undef) x
$n_before_ctx_lines;
370 $before_context_pos = 0;
372 $is_tracking_context = $n_before_ctx_lines || $n_after_ctx_lines;
379 # Adjust context tracking variables when entering a new file.
380 sub set_up_line_context_for_file
{
381 $printed_line_no = 0;
382 $after_context_pending = 0;
383 if ( $opt_heading && !$opt_lines ) {
392 This subroutine jumps through a number of optimization hoops to
393 try to be fast in the more common use cases of ack. For one thing,
394 in non-context tracking searches (not using -A, -B, or -C),
395 conditions that normally would be checked inside the loop happen
396 outside, resulting in three nearly identical loops for -v, --passthru,
397 and normal searching. Any changes that happen to one should propagate
398 to the others if they make sense. The non-context branches also inline
399 does_match for performance reasons; any relevant changes that happen here
400 must also happen there.
406 sub print_matches_in_resource
{
407 my ( $resource ) = @_;
409 my $max_count = $opt_m || -1;
411 my $filename = $resource->name;
412 my $ors = $opt_print0 ? "\0" : "\n";
414 my $has_printed_for_this_resource = 0;
418 my $fh = $resource->open();
420 if ( $App::Ack
::report_bad_filenames
) {
421 App
::Ack
::warn( "$filename: $!" );
426 my $display_filename = $filename;
427 if ( $opt_show_filename && $opt_heading && $opt_color ) {
428 $display_filename = Term
::ANSIColor
::colored
($display_filename, $ENV{ACK_COLOR_FILENAME
});
431 # Check for context before the main loop, so we don't pay for it if we don't need it.
432 if ( $is_tracking_context ) {
433 $after_context_pending = 0;
435 if ( does_match
( $_ ) && $max_count ) {
436 if ( !$has_printed_for_this_resource ) {
437 if ( $opt_break && $has_printed_something ) {
438 App
::Ack
::print_blank_line
();
440 if ( $opt_show_filename && $opt_heading ) {
441 App
::Ack
::print_filename
( $display_filename, $ors );
444 print_line_with_context
( $filename, $_, $. );
445 $has_printed_for_this_resource = 1;
449 elsif ( $opt_passthru ) {
450 chomp; # XXX Proper newline handling?
451 # XXX Inline this call?
452 if ( $opt_break && !$has_printed_for_this_resource && $has_printed_something ) {
453 App
::Ack
::print_blank_line
();
455 print_line_with_options
( $filename, $_, $., ':' );
456 $has_printed_for_this_resource = 1;
459 chomp; # XXX Proper newline handling?
460 print_line_if_context
( $filename, $_, $., '-' );
463 last if ($max_count == 0) && ($after_context_pending == 0);
467 if ( $opt_passthru ) {
471 $match_column_number = undef;
472 if ( $opt_v ? !/$opt_regex/o : /$opt_regex/o ) {
474 $match_column_number = $-[0] + 1;
476 if ( !$has_printed_for_this_resource ) {
477 if ( $opt_break && $has_printed_something ) {
478 App
::Ack
::print_blank_line
();
480 if ( $opt_show_filename && $opt_heading ) {
481 App
::Ack
::print_filename
( $display_filename, $ors );
484 print_line_with_context
( $filename, $_, $. );
485 $has_printed_for_this_resource = 1;
490 chomp; # XXX proper newline handling?
491 if ( $opt_break && !$has_printed_for_this_resource && $has_printed_something ) {
492 App
::Ack
::print_blank_line
();
494 print_line_with_options
( $filename, $_, $., ':' );
495 $has_printed_for_this_resource = 1;
497 last unless $max_count != 0;
503 $match_column_number = undef;
505 if ( !/$opt_regex/o ) {
506 if ( !$has_printed_for_this_resource ) {
507 if ( $opt_break && $has_printed_something ) {
508 App
::Ack
::print_blank_line
();
510 if ( $opt_show_filename && $opt_heading ) {
511 App
::Ack
::print_filename
( $display_filename, $ors );
514 print_line_with_context
( $filename, $_, $. );
515 $has_printed_for_this_resource = 1;
519 last unless $max_count != 0;
526 $match_column_number = undef;
527 if ( /$opt_regex/o ) {
528 $match_column_number = $-[0] + 1;
529 if ( !$has_printed_for_this_resource ) {
530 if ( $opt_break && $has_printed_something ) {
531 App
::Ack
::print_blank_line
();
533 if ( $opt_show_filename && $opt_heading ) {
534 App
::Ack
::print_filename
( $display_filename, $ors );
538 print_line_with_options
( $filename, $_, $., ':' );
539 $has_printed_for_this_resource = 1;
543 last unless $max_count != 0;
554 sub print_line_with_options
{
555 my ( $filename, $line, $line_no, $separator ) = @_;
557 $has_printed_something = 1;
558 $printed_line_no = $line_no;
560 my $ors = $opt_print0 ? "\0" : "\n";
565 $filename = Term
::ANSIColor
::colored
($filename,
566 $ENV{ACK_COLOR_FILENAME
});
567 $line_no = Term
::ANSIColor
::colored
($line_no,
568 $ENV{ACK_COLOR_LINENO
});
571 if($opt_show_filename) {
573 push @line_parts, $line_no;
576 push @line_parts, $filename, $line_no;
580 push @line_parts, get_match_column
();
584 while ( $line =~ /$opt_regex/og ) {
585 # XXX We need to stop using eval() for --output. See https://github.com/beyondgrep/ack2/issues/421
586 my $output = eval $opt_output;
587 App
::Ack
::print( join( $separator, @line_parts, $output ), $ors );
592 # This match is redundant, but we need to perfom it in order to get if capture groups are set.
593 $line =~ /$opt_regex/o;
595 if ( @+ > 1 ) { # If we have captures...
596 while ( $line =~ /$opt_regex/og ) {
597 my $offset = 0; # Additional offset for when we add stuff.
598 my $previous_match_end = 0;
600 last if $-[0] == $+[0];
602 for ( my $i = 1; $i < @+; $i++ ) {
603 my ( $match_start, $match_end ) = ( $-[$i], $+[$i] );
605 next unless defined($match_start);
606 next if $match_start < $previous_match_end;
608 my $substring = substr( $line,
609 $offset + $match_start, $match_end - $match_start );
610 my $substitution = Term
::ANSIColor
::colored
( $substring,
611 $ENV{ACK_COLOR_MATCH
} );
613 substr( $line, $offset + $match_start,
614 $match_end - $match_start, $substitution );
616 $previous_match_end = $match_end; # Offsets do not need to be applied.
617 $offset += length( $substitution ) - length( $substring );
620 pos($line) = $+[0] + $offset;
624 my $matched = 0; # If matched, need to escape afterwards.
626 while ( $line =~ /$opt_regex/og ) {
629 my ( $match_start, $match_end ) = ($-[0], $+[0]);
630 next unless defined($match_start);
631 last if $match_start == $match_end;
633 my $substring = substr( $line, $match_start,
634 $match_end - $match_start );
635 my $substitution = Term
::ANSIColor
::colored
( $substring,
636 $ENV{ACK_COLOR_MATCH
} );
638 substr( $line, $match_start, $match_end - $match_start,
641 pos($line) = $match_end +
642 (length( $substitution ) - length( $substring ));
644 # XXX Why do we do this?
645 $line .= "\033[0m\033[K" if $matched;
649 push @line_parts, $line;
650 App
::Ack
::print( join( $separator, @line_parts ), $ors );
657 my ( $resource, $cb ) = @_;
661 my $fh = $resource->open();
663 if ( $App::Ack
::report_bad_filenames
) {
664 App
::Ack
::warn( $resource->name . ': ' . $! );
669 # Check for context before the main loop, so we don't pay for it if we don't need it.
670 if ( $is_tracking_context ) {
671 $after_context_pending = 0;
690 sub print_line_with_context
{
691 my ( $filename, $matching_line, $line_no ) = @_;
693 my $ors = $opt_print0 ? "\0" : "\n";
694 my $is_tracking_context = $opt_after_context || $opt_before_context;
696 $matching_line =~ s/[\r\n]+$//g;
698 # Check if we need to print context lines first.
699 if ( $is_tracking_context ) {
700 my $before_unprinted = $line_no - $printed_line_no - 1;
701 if ( !$is_first_match && ( !$printed_line_no || $before_unprinted > $n_before_ctx_lines ) ) {
702 App
::Ack
::print('--', $ors);
705 # We want at most $n_before_ctx_lines of context.
706 if ( $before_unprinted > $n_before_ctx_lines ) {
707 $before_unprinted = $n_before_ctx_lines;
710 while ( $before_unprinted > 0 ) {
711 my $line = $before_context_buf[($before_context_pos - $before_unprinted + $n_before_ctx_lines) % $n_before_ctx_lines];
715 # Disable $opt->{column} since there are no matches in the context lines.
716 local $opt_column = 0;
718 print_line_with_options
( $filename, $line, $line_no-$before_unprinted, '-' );
723 print_line_with_options
( $filename, $matching_line, $line_no, ':' );
725 # We want to get the next $n_after_ctx_lines printed.
726 $after_context_pending = $n_after_ctx_lines;
733 # Print the line only if it's part of a context we need to display.
734 sub print_line_if_context
{
735 my ( $filename, $line, $line_no, $separator ) = @_;
737 if ( $after_context_pending ) {
738 # Disable $opt_column since there are no matches in the context lines.
739 local $opt_column = 0;
740 print_line_with_options
( $filename, $line, $line_no, $separator );
741 --$after_context_pending;
743 elsif ( $n_before_ctx_lines ) {
744 # Save line for "before" context.
745 $before_context_buf[$before_context_pos] = $_;
746 $before_context_pos = ($before_context_pos+1) % $n_before_ctx_lines;
754 # does_match() MUST have an $opt_regex set.
758 This subroutine is inlined a few places in print_matches_in_resource
759 for performance reasons, so any changes here must be copied there as
769 $match_column_number = undef;
772 return ( $line !~ /$opt_regex/o );
775 if ( $line =~ /$opt_regex/o ) {
776 # @- = @LAST_MATCH_START
777 # @+ = @LAST_MATCH_END
778 $match_column_number = $-[0] + 1;
787 sub get_match_column
{
788 return $match_column_number;
791 sub resource_has_match
{
792 my ( $resource ) = @_;
795 my $fh = $resource->open();
797 if ( $App::Ack
::report_bad_filenames
) {
798 App
::Ack
::warn( $resource->name . ': ' . $! );
803 if (/$opt_regex/o xor $opt_v) {
814 sub count_matches_in_resource
{
815 my ( $resource ) = @_;
818 my $fh = $resource->open();
820 if ( $App::Ack
::report_bad_filenames
) {
821 App
::Ack
::warn( $resource->name . ': ' . $! );
826 ++$nmatches if (/$opt_regex/o xor $opt_v);
835 my @arg_sources = App
::Ack
::ConfigLoader
::retrieve_arg_sources
();
837 my $opt = App
::Ack
::ConfigLoader
::process_args
( @arg_sources );
839 $opt_after_context = $opt->{after_context
};
840 $opt_before_context = $opt->{before_context
};
841 $opt_output = $opt->{output
};
842 $opt_print0 = $opt->{print0
};
843 $opt_color = $opt->{color
};
844 $opt_heading = $opt->{heading
};
845 $opt_show_filename = $opt->{show_filename
};
846 $opt_regex = $opt->{regex
};
847 $opt_break = $opt->{break};
848 $opt_count = $opt->{count
};
853 $opt_lines = $opt->{lines
};
856 $opt_passthru = $opt->{passthru
};
857 $opt_column = $opt->{column
};
859 $App::Ack
::report_bad_filenames
= !$opt->{dont_report_bad_filenames
};
861 if ( $opt->{flush
} ) {
865 if ( !defined($opt_color) && !$opt_g ) {
866 my $windows_color = 1;
867 if ( $App::Ack
::is_windows
) {
868 $windows_color = eval { require Win32
::Console
::ANSI
; };
870 $opt_color = !App
::Ack
::output_to_pipe
() && $windows_color;
872 if ( not defined $opt_heading and not defined $opt_break ) {
873 $opt_heading = $opt_break = $opt->{break} = !App
::Ack
::output_to_pipe
();
876 if ( defined($opt->{H
}) || defined($opt->{h
}) ) {
877 $opt_show_filename = $opt->{show_filename
} = $opt->{H
} && !$opt->{h
};
880 if ( my $output = $opt_output ) {
881 $output =~ s{\\}{\\\\}g;
882 $output =~ s{"}{\\"}g;
883 $opt_output = qq{"$output"};
887 if ( $App::Ack
::is_filter_mode
&& !$opt->{files_from
} ) { # probably -x
888 $resources = App
::Ack
::Resources-
>from_stdin( $opt );
889 $opt_regex = shift @ARGV if not defined $opt_regex;
890 $opt_regex = $opt->{regex
} = build_regex
( $opt_regex, $opt );
893 if ( $opt_f || $opt_lines ) {
895 App
::Ack
::warn( "regex ($opt_regex) specified with -f or --lines" );
896 App
::Ack
::exit_from_ack
( 0 ); # XXX the 0 is misleading
900 $opt_regex = shift @ARGV if not defined $opt_regex;
901 $opt_regex = $opt->{regex
} = build_regex
( $opt_regex, $opt );
903 if ( $opt_regex && $opt_regex =~ /\n/ ) {
904 App
::Ack
::exit_from_ack
( 0 );
907 if ( not defined $opt->{files_from
} ) {
910 if ( !exists($opt->{show_filename
}) ) {
911 unless(@start == 1 && !(-d
$start[0])) {
912 $opt_show_filename = $opt->{show_filename
} = 1;
916 if ( defined $opt->{files_from
} ) {
917 $resources = App
::Ack
::Resources-
>from_file( $opt, $opt->{files_from
} );
918 exit 1 unless $resources;
921 @start = ('.') unless @start;
922 foreach my $target (@start) {
923 if ( !-e
$target && $App::Ack
::report_bad_filenames
) {
924 App
::Ack
::warn( "$target: No such file or directory" );
928 $opt->{file_filter
} = _compile_file_filter
($opt, \
@start);
929 $opt->{descend_filter
} = _compile_descend_filter
($opt);
931 $resources = App
::Ack
::Resources-
>from_argv( $opt, \
@start );
934 App
::Ack
::set_up_pager
( $opt->{pager
} ) if defined $opt->{pager
};
936 my $ors = $opt_print0 ? "\0" : "\n";
937 my $only_first = $opt->{1};
942 set_up_line_context
();
945 while ( my $resource = $resources->next ) {
946 if ($is_tracking_context) {
947 set_up_line_context_for_file
();
951 if ( $opt->{show_types
} ) {
952 show_types
( $resource, $ors );
955 App
::Ack
::print( $resource->name, $ors );
958 last RESOURCES
if defined($opt_m) && $nmatches >= $opt_m;
961 if ( $opt->{show_types
} ) {
962 show_types
( $resource, $ors );
965 local $opt_show_filename = 0; # XXX Why is this local?
967 print_line_with_options
( '', $resource->name, 0, $ors );
970 last RESOURCES
if defined($opt_m) && $nmatches >= $opt_m;
972 elsif ( $opt_lines ) {
974 foreach my $line ( @{ $opt_lines } ) {
975 my @lines = split /,/, $line;
981 @line_numbers{@lines} = (1) x
@lines;
984 my $filename = $resource->name;
986 local $opt_color = 0;
988 iterate
( $resource, sub {
991 if ( $line_numbers{$.} ) {
992 print_line_with_context
( $filename, $_, $. );
994 elsif ( $opt_passthru ) {
995 print_line_with_options
( $filename, $_, $., ':' );
997 elsif ( $is_tracking_context ) {
998 print_line_if_context
( $filename, $_, $., '-' );
1003 elsif ( $opt_count ) {
1004 my $matches_for_this_file = count_matches_in_resource
( $resource );
1006 if ( not $opt_show_filename ) {
1007 $total_count += $matches_for_this_file;
1011 if ( !$opt_l || $matches_for_this_file > 0) {
1012 if ( $opt_show_filename ) {
1013 App
::Ack
::print( $resource->name, ':', $matches_for_this_file, $ors );
1016 App
::Ack
::print( $matches_for_this_file, $ors );
1020 elsif ( $opt_l || $opt_L ) {
1021 my $is_match = resource_has_match
( $resource );
1023 if ( $opt_L ? !$is_match : $is_match ) {
1024 App
::Ack
::print( $resource->name, $ors );
1027 last RESOURCES
if $only_first;
1028 last RESOURCES
if defined($opt_m) && $nmatches >= $opt_m;
1032 $nmatches += print_matches_in_resource
( $resource, $opt );
1033 if ( $nmatches && $only_first ) {
1039 if ( $opt_count && !$opt_show_filename ) {
1040 App
::Ack
::print( $total_count, "\n" );
1043 close $App::Ack
::fh
;
1044 App
::Ack
::exit_from_ack
( $nmatches );
1053 ack - grep-like text finder
1057 ack [options] PATTERN [FILE...]
1058 ack -f [options] [DIRECTORY...]
1062 ack is designed as an alternative to F<grep> for programmers.
1064 ack searches the named input files or directories for lines containing a
1065 match to the given PATTERN. By default, ack prints the matching lines.
1066 If no FILE or DIRECTORY is given, the current directory will be searched.
1068 PATTERN is a Perl regular expression. Perl regular expressions
1069 are commonly found in other programming languages, but for the particulars
1070 of their behavior, please consult
1071 L<http://perldoc.perl.org/perlreref.html|perlreref>. If you don't know
1072 how to use regular expression but are interested in learning, you may
1073 consult L<http://perldoc.perl.org/perlretut.html|perlretut>. If you do not
1074 need or want ack to use regular expressions, please see the
1075 C<-Q>/C<--literal> option.
1077 Ack can also list files that would be searched, without actually
1078 searching them, to let you take advantage of ack's file-type filtering
1081 =head1 FILE SELECTION
1083 If files are not specified for searching, either on the command
1084 line or piped in with the C<-x> option, I<ack> delves into
1085 subdirectories selecting files for searching.
1087 I<ack> is intelligent about the files it searches. It knows about
1088 certain file types, based on both the extension on the file and,
1089 in some cases, the contents of the file. These selections can be
1090 made with the B<--type> option.
1092 With no file selection, I<ack> searches through regular files that
1093 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
1094 options, either present in F<ackrc> files or on the command line.
1096 The default options for I<ack> ignore certain files and directories. These
1101 =item * Backup files: Files matching F<#*#> or ending with F<~>.
1103 =item * Coredumps: Files matching F<core.\d+>
1105 =item * Version control directories like F<.svn> and F<.git>.
1109 Run I<ack> with the C<--dump> option to see what settings are set.
1111 However, I<ack> always searches the files given on the command line,
1112 no matter what type. If you tell I<ack> to search in a coredump,
1113 it will search in a coredump.
1115 =head1 DIRECTORY SELECTION
1117 I<ack> descends through the directory tree of the starting directories
1118 specified. If no directories are specified, the current working directory is
1119 used. However, it will ignore the shadow directories used by
1120 many version control systems, and the build directories used by the
1121 Perl MakeMaker system. You may add or remove a directory from this
1122 list with the B<--[no]ignore-dir> option. The option may be repeated
1123 to add/remove multiple directories from the ignore list.
1125 For a complete list of directories that do not get searched, run
1128 =head1 WHEN TO USE GREP
1130 I<ack> trumps I<grep> as an everyday tool 99% of the time, but don't
1131 throw I<grep> away, because there are times you'll still need it.
1133 E.g., searching through huge files looking for regexes that can be
1134 expressed with I<grep> syntax should be quicker with I<grep>.
1136 If your script or parent program uses I<grep> C<--quiet> or C<--silent>
1137 or needs exit 2 on IO error, use I<grep>.
1145 Specifies an ackrc file to load after all others; see L</"ACKRC LOCATION SEMANTICS">.
1147 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
1149 Print I<NUM> lines of trailing context after matching lines.
1151 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
1153 Print I<NUM> lines of leading context before matching lines.
1155 =item B<--[no]break>
1157 Print a break between results from different files. On by default
1158 when used interactively.
1160 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
1162 Print I<NUM> lines (default 2) of context around matching lines.
1163 You can specify zero lines of context to override another context
1164 specified in an ackrc.
1166 =item B<-c>, B<--count>
1168 Suppress normal output; instead print a count of matching lines for
1169 each input file. If B<-l> is in effect, it will only show the
1170 number of lines for each file that has lines matching. Without
1171 B<-l>, some line counts may be zeroes.
1173 If combined with B<-h> (B<--no-filename>) ack outputs only one total
1176 =item B<--[no]color>, B<--[no]colour>
1178 B<--color> highlights the matching text. B<--nocolor> suppresses
1179 the color. This is on by default unless the output is redirected.
1181 On Windows, this option is off by default unless the
1182 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
1183 environment variable is used.
1185 =item B<--color-filename=I<color>>
1187 Sets the color to be used for filenames.
1189 =item B<--color-match=I<color>>
1191 Sets the color to be used for matches.
1193 =item B<--color-lineno=I<color>>
1195 Sets the color to be used for line numbers.
1197 =item B<--[no]column>
1199 Show the column number of the first match. This is helpful for
1200 editors that can place your cursor at a given position.
1202 =item B<--create-ackrc>
1204 Dumps the default ack options to standard output. This is useful for
1205 when you want to customize the defaults.
1209 Writes the list of options loaded and where they came from to standard
1210 output. Handy for debugging.
1214 B<--noenv> disables all environment processing. No F<.ackrc> is
1215 read and all environment variables are ignored. By default, F<ack>
1216 considers F<.ackrc> and settings in the environment.
1220 B<--flush> flushes output immediately. This is off by default
1221 unless ack is running interactively (when output goes to a pipe or
1226 Only print the files that would be searched, without actually doing
1227 any searching. PATTERN must not be specified, or it will be taken
1228 as a path to search.
1230 =item B<--files-from=I<FILE>>
1232 The list of files to be searched is specified in I<FILE>. The list of
1233 files are separated by newlines. If I<FILE> is C<->, the list is loaded
1234 from standard input.
1236 =item B<--[no]filter>
1238 Forces ack to act as if it were receiving input via a pipe.
1240 =item B<--[no]follow>
1242 Follow or don't follow symlinks, other than whatever starting files
1243 or directories were specified on the command line.
1245 This is off by default.
1247 =item B<-g I<PATTERN>>
1249 Print searchable files where the relative path + filename matches
1256 is exactly the same as
1260 This means that just as ack will not search, for example, F<.jpg>
1261 files, C<-g> will not list F<.jpg> files either. ack is not intended
1262 to be a general-purpose file finder.
1264 Note also that if you have C<-i> in your .ackrc that the filenames
1265 to be matched will be case-insensitive as well.
1267 This option can be combined with B<--color> to make it easier to
1270 =item B<--[no]group>
1272 B<--group> groups matches by file name. This is the default
1273 when used interactively.
1275 B<--nogroup> prints one result per line, like grep. This is the
1276 default when output is redirected.
1278 =item B<-H>, B<--with-filename>
1280 Print the filename for each match. This is the default unless searching
1281 a single explicitly specified file.
1283 =item B<-h>, B<--no-filename>
1285 Suppress the prefixing of filenames on output when multiple files are
1288 =item B<--[no]heading>
1290 Print a filename heading above each file's results. This is the default
1291 when used interactively.
1293 =item B<--help>, B<-?>
1295 Print a short help statement.
1297 =item B<--help-types>, B<--help=types>
1299 Print all known types.
1301 =item B<-i>, B<--ignore-case>
1303 Ignore case distinctions in PATTERN
1305 =item B<--ignore-ack-defaults>
1307 Tells ack to completely ignore the default definitions provided with ack.
1308 This is useful in combination with B<--create-ackrc> if you I<really> want
1311 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
1313 Ignore directory (as CVS, .svn, etc are ignored). May be used
1314 multiple times to ignore multiple directories. For example, mason
1315 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
1316 option allows users to search directories which would normally be
1317 ignored (perhaps to research the contents of F<.svn/props> directories).
1319 The I<DIRNAME> must always be a simple directory name. Nested
1320 directories like F<foo/bar> are NOT supported. You would need to
1321 specify B<--ignore-dir=foo> and then no files from any foo directory
1322 are taken into account by ack unless given explicitly on the command
1325 =item B<--ignore-file=I<FILTERTYPE:FILTERARGS>>
1327 Ignore files matching I<FILTERTYPE:FILTERARGS>. The filters are specified
1328 identically to file type filters as seen in L</"Defining your own types">.
1330 =item B<-k>, B<--known-types>
1332 Limit selected files to those with types that ack knows about. This is
1333 equivalent to the default behavior found in ack 1.
1335 =item B<--lines=I<NUM>>
1337 Only print line I<NUM> of each file. Multiple lines can be given with multiple
1338 B<--lines> options or as a comma separated list (B<--lines=3,5,7>). B<--lines=4-7>
1339 also works. The lines are always output in ascending order, no matter the
1340 order given on the command line.
1342 =item B<-l>, B<--files-with-matches>
1344 Only print the filenames of matching files, instead of the matching text.
1346 =item B<-L>, B<--files-without-matches>
1348 Only print the filenames of files that do I<NOT> match.
1350 =item B<--match I<PATTERN>>
1352 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
1353 regex as your first argument, e.g. when executing multiple searches over the
1356 # search for foo and bar in given files
1357 ack file1 t/file* --match foo
1358 ack file1 t/file* --match bar
1360 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
1362 Stop reading a file after I<NUM> matches.
1366 Print this manual page.
1368 =item B<-n>, B<--no-recurse>
1370 No descending into subdirectories.
1374 Show only the part of each line matching PATTERN (turns off text
1377 =item B<--output=I<expr>>
1379 Output the evaluation of I<expr> for each line (turns off text
1381 If PATTERN matches more than once then a line is output for each non-overlapping match.
1382 For more information please see the section L</"Examples of F<--output>">.
1384 =item B<--pager=I<program>>, B<--nopager>
1386 B<--pager> directs ack's output through I<program>. This can also be specified
1387 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
1389 Using --pager does not suppress grouping and coloring like piping
1390 output on the command-line does.
1392 B<--nopager> cancels any setting in ~/.ackrc, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
1393 No output will be sent through a pager.
1397 Prints all lines, whether or not they match the expression. Highlighting
1398 will still work, though, so it can be used to highlight matches while
1399 still seeing the entire file, as in:
1401 # Watch a log file, and highlight a certain IP address
1402 $ tail -f ~/access.log | ack --passthru 123.45.67.89
1406 Only works in conjunction with -f, -g, -l or -c (filename output). The filenames
1407 are output separated with a null byte instead of the usual newline. This is
1408 helpful when dealing with filenames that contain whitespace, e.g.
1410 # remove all files of type html
1411 ack -f --html --print0 | xargs -0 rm -f
1413 =item B<-Q>, B<--literal>
1415 Quote all metacharacters in PATTERN, it is treated as a literal.
1417 =item B<-r>, B<-R>, B<--recurse>
1419 Recurse into sub-directories. This is the default and just here for
1420 compatibility with grep. You can also use it for turning B<--no-recurse> off.
1424 Suppress error messages about nonexistent or unreadable files. This is taken
1427 =item B<--[no]smart-case>, B<--no-smart-case>
1429 Ignore case in the search strings if PATTERN contains no uppercase
1430 characters. This is similar to C<smartcase> in vim. This option is
1431 off by default, and ignored if C<-i> is specified.
1433 B<-i> always overrides this option.
1435 =item B<--sort-files>
1437 Sorts the found files lexicographically. Use this if you want your file
1438 listings to be deterministic between runs of I<ack>.
1440 =item B<--show-types>
1442 Outputs the filetypes that ack associates with each file.
1444 Works with B<-f> and B<-g> options.
1446 =item B<--type=[no]TYPE>
1448 Specify the types of files to include or exclude from a search.
1449 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
1450 also be specified as B<--perl>, and B<--type=noperl> can be done
1453 If a file is of both type "foo" and "bar", specifying --foo and
1454 --nobar will exclude the file, because an exclusion takes precedence
1457 Type specifications can be repeated and are ORed together.
1459 See I<ack --help=types> for a list of valid types.
1461 =item B<--type-add I<TYPE>:I<FILTER>:I<FILTERARGS>>
1463 Files with the given FILTERARGS applied to the given FILTER
1464 are recognized as being of (the existing) type TYPE.
1465 See also L</"Defining your own types">.
1468 =item B<--type-set I<TYPE>:I<FILTER>:I<FILTERARGS>>
1470 Files with the given FILTERARGS applied to the given FILTER are recognized as
1471 being of type TYPE. This replaces an existing definition for type TYPE. See
1472 also L</"Defining your own types">.
1474 =item B<--type-del I<TYPE>>
1476 The filters associated with TYPE are removed from Ack, and are no longer considered
1479 =item B<-v>, B<--invert-match>
1481 Invert match: select non-matching lines
1485 Display version and copyright information.
1487 =item B<-w>, B<--word-regexp>
1489 =item B<-w>, B<--word-regexp>
1491 Turn on "words mode". This sometimes matches a whole word, but the
1492 semantics is quite subtle. If the passed regexp begins with a word
1493 character, then a word boundary is required before the match. If the
1494 passed regexp ends with a word character, or with a word character
1495 followed by newline, then a word boundary is required after the match.
1497 Thus, for example, B<-w> with the regular expression C<ox> will not
1498 match the strings C<box> or C<oxen>. However, if the regular
1499 expression is C<(ox|ass)> then it will match those strings. Because
1500 the regular expression's first character is C<(>, the B<-w> flag has
1501 no effect at the start, and because the last character is C<)>, it has
1502 no effect at the end.
1504 Force PATTERN to match only whole words. The PATTERN is wrapped with
1505 C<\b> metacharacters.
1509 An abbreviation for B<--files-from=->; the list of files to search are read
1510 from standard input, with one line per file.
1514 Stops after reporting first match of any kind. This is different
1515 from B<--max-count=1> or B<-m1>, where only one match per file is
1516 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
1521 Display the all-important Bill The Cat logo. Note that the exact
1522 spelling of B<--thpppppt> is not important. It's checked against
1523 a regular expression.
1527 Check with the admiral for traps.
1531 Chocolate, Chocolate, Chocolate!
1535 =head1 THE .ackrc FILE
1537 The F<.ackrc> file contains command-line options that are prepended
1538 to the command line before processing. Multiple options may live
1539 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
1540 might look like this:
1542 # Always sort the files
1545 # Always color, even if piping to another program
1548 # Use "less -r" as my pager
1551 Note that arguments with spaces in them do not need to be quoted,
1552 as they are not interpreted by the shell. Basically, each I<line>
1553 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
1555 F<ack> looks in several locations for F<.ackrc> files; the searching
1556 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
1557 files are not considered if B<--noenv> is specified on the command line.
1559 =head1 Defining your own types
1561 ack allows you to define your own types in addition to the predefined
1562 types. This is done with command line options that are best put into
1563 an F<.ackrc> file - then you do not have to define your types over and
1564 over again. In the following examples the options will always be shown
1565 on one command line so that they can be easily copy & pasted.
1567 File types can be specified both with the the I<--type=xxx> option,
1568 or the file type as an option itself. For example, if you create
1569 a filetype of "cobol", you can specify I<--type=cobol> or simply
1570 I<--cobol>. File types must be at least two characters long. This
1571 is why the C language is I<--cc> and the R language is I<--rr>.
1573 I<ack --perl foo> searches for foo in all perl files. I<ack --help=types>
1574 tells you, that perl files are files ending
1575 in .pl, .pm, .pod or .t. So what if you would like to include .xs
1576 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
1577 does this for you. B<--type-add> appends
1578 additional extensions to an existing type.
1580 If you want to define a new type, or completely redefine an existing
1581 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
1582 the type I<eiffel> to include files with
1583 the extensions .e or .eiffel. So to search for all eiffel files
1584 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
1585 As usual, you can also write B<--type=eiffel>
1586 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
1587 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
1588 and I<.xs> files no longer belong to the type I<cc>.
1590 When defining your own types in the F<.ackrc> file you have to use
1593 --type-set=eiffel:ext:e,eiffel
1595 or writing on separate lines
1600 The following does B<NOT> work in the F<.ackrc> file:
1602 --type-set eiffel:ext:e,eiffel
1604 In order to see all currently defined types, use I<--help-types>, e.g.
1605 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
1607 In addition to filtering based on extension (like ack 1.x allowed), ack 2
1608 offers additional filter types. The generic syntax is
1609 I<--type-set TYPE:FILTER:FILTERARGS>; I<FILTERARGS> depends on the value
1614 =item is:I<FILENAME>
1616 I<is> filters match the target filename exactly. It takes exactly one
1617 argument, which is the name of the file to match.
1621 --type-set make:is:Makefile
1623 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
1625 I<ext> filters match the extension of the target file against a list
1626 of extensions. No leading dot is needed for the extensions.
1630 --type-set perl:ext:pl,pm,t
1632 =item match:I<PATTERN>
1634 I<match> filters match the target filename against a regular expression.
1635 The regular expression is made case insensitive for the search.
1639 --type-set make:match:/(gnu)?makefile/
1641 =item firstlinematch:I<PATTERN>
1643 I<firstlinematch> matches the first line of the target file against a
1644 regular expression. Like I<match>, the regular expression is made
1649 --type-add perl:firstlinematch:/perl/
1653 More filter types may be made available in the future.
1655 =head1 ENVIRONMENT VARIABLES
1657 For commonly-used ack options, environment variables can make life
1658 much easier. These variables are ignored if B<--noenv> is specified
1659 on the command line.
1665 Specifies the location of the user's F<.ackrc> file. If this file doesn't
1666 exist, F<ack> looks in the default location.
1670 This variable specifies default options to be placed in front of
1671 any explicit options on the command line.
1673 =item ACK_COLOR_FILENAME
1675 Specifies the color of the filename when it's printed in B<--group>
1676 mode. By default, it's "bold green".
1678 The recognized attributes are clear, reset, dark, bold, underline,
1679 underscore, blink, reverse, concealed black, red, green, yellow,
1680 blue, magenta, on_black, on_red, on_green, on_yellow, on_blue,
1681 on_magenta, on_cyan, and on_white. Case is not significant.
1682 Underline and underscore are equivalent, as are clear and reset.
1683 The color alone sets the foreground color, and on_color sets the
1686 This option can also be set with B<--color-filename>.
1688 =item ACK_COLOR_MATCH
1690 Specifies the color of the matching text when printed in B<--color>
1691 mode. By default, it's "black on_yellow".
1693 This option can also be set with B<--color-match>.
1695 See B<ACK_COLOR_FILENAME> for the color specifications.
1697 =item ACK_COLOR_LINENO
1699 Specifies the color of the line number when printed in B<--color>
1700 mode. By default, it's "bold yellow".
1702 This option can also be set with B<--color-lineno>.
1704 See B<ACK_COLOR_FILENAME> for the color specifications.
1708 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
1709 ack will send its output.
1711 Using C<ACK_PAGER> does not suppress grouping and coloring like
1712 piping output on the command-line does, except that on Windows
1713 ack will assume that C<ACK_PAGER> does not support color.
1715 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
1717 =item ACK_PAGER_COLOR
1719 Specifies a pager program that understands ANSI color sequences.
1720 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
1721 like piping output on the command-line does.
1723 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
1727 =head1 AVAILABLE COLORS
1729 F<ack> uses the colors available in Perl's L<Term::ANSIColor> module, which
1730 provides the following listed values. Note that case does not matter when using
1733 =head2 Foreground colors
1735 black red green yellow blue magenta cyan white
1737 bright_black bright_red bright_green bright_yellow
1738 bright_blue bright_magenta bright_cyan bright_white
1740 =head2 Background colors
1742 on_black on_red on_green on_yellow
1743 on_blue on_magenta on_cyan on_white
1745 on_bright_black on_bright_red on_bright_green on_bright_yellow
1746 on_bright_blue on_bright_magenta on_bright_cyan on_bright_white
1748 =head1 ACK & OTHER TOOLS
1750 =head2 Simple vim integration
1752 F<ack> integrates easily with the Vim text editor. Set this in your
1753 F<.vimrc> to use F<ack> instead of F<grep>:
1757 That example uses C<-k> to search through only files of the types ack
1758 knows about, but you may use other default flags. Now you can search
1759 with F<ack> and easily step through the results in Vim:
1761 :grep Dumper perllib
1763 =head2 Editor integration
1765 Many users have integrated ack into their preferred text editors.
1766 For details and links, see L<https://beyondgrep.com/more-tools/>.
1768 =head2 Shell and Return Code
1770 For greater compatibility with I<grep>, I<ack> in normal use returns
1771 shell return or exit code of 0 only if something is found and 1 if
1774 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
1776 The I<grep> code 2 for errors is not used.
1778 If C<-f> or C<-g> are specified, then 0 is returned if at least one
1779 file is found. If no files are found, then 1 is returned.
1783 =head1 DEBUGGING ACK PROBLEMS
1785 If ack gives you output you're not expecting, start with a few simple steps.
1787 =head2 Use B<--noenv>
1789 Your environment variables and F<.ackrc> may be doing things you're
1790 not expecting, or forgotten you specified. Use B<--noenv> to ignore
1791 your environment and F<.ackrc>.
1793 =head2 Use B<-f> to see what files have been selected
1795 Ack's B<-f> was originally added as a debugging tool. If ack is
1796 not finding matches you think it should find, run F<ack -f> to see
1797 what files have been selected. You can also add the C<--show-types>
1798 options to show the type of each file selected.
1800 =head2 Use B<--dump>
1802 This lists the ackrc files that are loaded and the options loaded
1804 So for example you can find a list of directories that do not get searched or where filetypes are defined.
1808 =head2 Use the F<.ackrc> file.
1810 The F<.ackrc> is the place to put all your options you use most of
1811 the time but don't want to remember. Put all your --type-add and
1812 --type-set definitions in it. If you like --smart-case, set it
1813 there, too. I also set --sort-files there.
1815 =head2 Use F<-f> for working with big codesets
1817 Ack does more than search files. C<ack -f --perl> will create a
1818 list of all the Perl files in a tree, ideal for sending into F<xargs>.
1821 # Change all "this" to "that" in all Perl files in a tree.
1822 ack -f --perl | xargs perl -p -i -e's/this/that/g'
1826 perl -p -i -e's/this/that/g' $(ack -f --perl)
1828 =head2 Use F<-Q> when in doubt about metacharacters
1830 If you're searching for something with a regular expression
1831 metacharacter, most often a period in a filename or IP address, add
1832 the -Q to avoid false positives without all the backslashing. See
1833 the following example for more...
1835 =head2 Use ack to watch log files
1837 Here's one I used the other day to find trouble spots for a website
1838 visitor. The user had a problem loading F<troublesome.gif>, so I
1839 took the access log and scanned it with ack twice.
1841 ack -Q aa.bb.cc.dd /path/to/access.log | ack -Q -B5 troublesome.gif
1843 The first ack finds only the lines in the Apache log for the given
1844 IP. The second finds the match on my troublesome GIF, and shows
1845 the previous five lines from the log in each case.
1847 =head2 Examples of F<--output>
1849 Following variables are useful in the expansion string:
1855 The whole string matched by PATTERN.
1857 =item C<$1>, C<$2>, ...
1859 The contents of the 1st, 2nd ... bracketed group in PATTERN.
1863 The string before the match.
1867 The string after the match.
1871 For more details and other variables see
1872 L<http://perldoc.perl.org/perlvar.html#Variables-related-to-regular-expressions|perlvar>.
1874 This example shows how to add text around a particular pattern
1875 (in this case adding _ around word with "e")
1877 ack2.pl "\w*e\w*" quick.txt --output="$`_$&_$'"
1878 _The_ quick brown fox jumps over the lazy dog
1879 The quick brown fox jumps _over_ the lazy dog
1880 The quick brown fox jumps over _the_ lazy dog
1882 This shows how to pick out particular parts of a match using ( ) within regular expression.
1884 ack '=head(\d+)\s+(.*)' --output=' $1 : $2'
1885 input file contains "=head1 NAME"
1890 There are ack mailing lists and a Slack channel for ack. See
1891 L<https://beyondgrep.com/community/> for details.
1895 =head2 Why isn't ack finding a match in (some file)?
1897 First, take a look and see if ack is even looking at the file. ack is
1898 intelligent in what files it will search and which ones it won't, but
1899 sometimes that can be surprising.
1901 Use the C<-f> switch, with no regex, to see a list of files that ack
1902 will search for you. If your file doesn't show up in the list of files
1903 that C<ack -f> shows, then ack never looks in it.
1905 NOTE: If you're using an old ack before 2.0, it's probably because it's of
1906 a type that ack doesn't recognize. In ack 1.x, the searching behavior is
1907 driven by filetype. B<If ack 1.x doesn't know what kind of file it is,
1908 ack ignores the file.> You can use the C<--show-types> switch to show
1909 which type ack thinks each file is.
1911 =head2 Wouldn't it be great if F<ack> did search & replace?
1913 No, ack will always be read-only. Perl has a perfectly good way
1914 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
1917 You can certainly use ack to select your files to update. For
1918 example, to change all "foo" to "bar" in all PHP files, you can do
1919 this from the Unix shell:
1921 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
1923 =head2 Can I make ack recognize F<.xyz> files?
1925 Yes! Please see L</"Defining your own types">. If you think
1926 that F<ack> should recognize a type by default, please see
1929 =head2 There's already a program/package called ack.
1933 =head2 Why is it called ack if it's called ack-grep?
1935 The name of the program is "ack". Some packagers have called it
1936 "ack-grep" when creating packages because there's already a package
1937 out there called "ack" that has nothing to do with this ack.
1939 I suggest you make a symlink named F<ack> that points to F<ack-grep>
1940 because one of the crucial benefits of ack is having a name that's
1941 so short and simple to type.
1943 To do that, run this with F<sudo> or as root:
1945 ln -s /usr/bin/ack-grep /usr/bin/ack
1947 Alternatively, you could use a shell alias:
1955 =head2 What does F<ack> mean?
1957 Nothing. I wanted a name that was easy to type and that you could
1958 pronounce as a single syllable.
1960 =head2 Can I do multi-line regexes?
1962 No, ack does not support regexes that match multiple lines. Doing
1963 so would require reading in the entire file at a time.
1965 If you want to see lines near your match, use the C<--A>, C<--B>
1966 and C<--C> switches for displaying context.
1968 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
1970 ack treats command line options beginning with C<+> or C<-> as options; if you
1971 would like to search for these, you may prefix your search term with C<--> or
1972 use the C<--match> option. (However, don't forget that C<+> is a regular
1973 expression metacharacter!)
1975 =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex?
1977 The Perl language limits the repetition quantifier to 32K. You
1978 can search for C<.{32767}> but not C<.{32768}>.
1980 =head2 Ack does "X" and shouldn't, should it?
1982 We try to remain as close to grep's behavior as possible, so when in doubt,
1983 see what grep does! If there's a mismatch in functionality there, please
1984 bring it up on the ack-users mailing list.
1986 =head1 ACKRC LOCATION SEMANTICS
1988 Ack can load its configuration from many sources. The following list
1989 specifies the sources Ack looks for configuration files; each one
1990 that is found is loaded in the order specified here, and
1991 each one overrides options set in any of the sources preceding
1992 it. (For example, if I set --sort-files in my user ackrc, and
1993 --nosort-files on the command line, the command line takes
2000 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
2001 using C<--ignore-ack-defaults>.
2003 =item * Global ackrc
2005 Options are then loaded from the global ackrc. This is located at
2006 C</etc/ackrc> on Unix-like systems.
2008 Under Windows XP and earlier, the global ackrc is at
2009 C<C:\Documents and Settings\All Users\Application Data\ackrc>
2011 Under Windows Vista/7, the global ackrc is at
2012 C<C:\ProgramData\ackrc>
2014 The C<--noenv> option prevents all ackrc files from being loaded.
2018 Options are then loaded from the user's ackrc. This is located at
2019 C<$HOME/.ackrc> on Unix-like systems.
2021 Under Windows XP and earlier, the user's ackrc is at
2022 C<C:\Documents and Settings\$USER\Application Data\ackrc>.
2024 Under Windows Vista/7, the user's ackrc is at
2025 C<C:\Users\$USER\AppData\Roaming\ackrc>.
2027 If you want to load a different user-level ackrc, it may be specified
2028 with the C<$ACKRC> environment variable.
2030 The C<--noenv> option prevents all ackrc files from being loaded.
2032 =item * Project ackrc
2034 Options are then loaded from the project ackrc. The project ackrc is
2035 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
2036 in the current directory, then the parent directory, then the grandparent
2037 directory, etc. This can be omitted using C<--noenv>.
2041 The C<--ackrc> option may be included on the command line to specify an
2042 ackrc file that can override all others. It is consulted even if C<--noenv>
2047 Options are then loaded from the environment variable C<ACK_OPTIONS>. This can
2048 be omitted using C<--noenv>.
2050 =item * Command line
2052 Options are then loaded from the command line.
2056 =head1 DIFFERENCES BETWEEN ACK 1.X AND ACK 2.X
2058 A lot of changes were made for ack 2; here is a list of them.
2060 =head2 GENERAL CHANGES
2066 When no selectors are specified, ack 1.x only searches through files that
2067 it can map to a file type. ack 2.x, by contrast, will search through
2068 every regular, non-binary file that is not explicitly ignored via
2069 B<--ignore-file> or B<--ignore-dir>. This is similar to the behavior of the
2070 B<-a/--all> option in ack 1.x.
2074 A more flexible filter system has been added, so that more powerful file types
2075 may be created by the user. For details, please consult
2076 L</"Defining your own types">.
2080 ack now loads multiple ackrc files; see L</"ACKRC LOCATION SEMANTICS"> for
2085 ack's default filter definitions aren't special; you may tell ack to
2086 completely disregard them if you don't like them.
2090 =head2 REMOVED OPTIONS
2096 Because of the change in default search behavior, the B<-a/--all> and
2097 B<-u/--unrestricted> options have been removed. In addition, the
2098 B<-k/--known-types> option was added to cause ack to behave with
2099 the default search behavior of ack 1.x.
2103 The B<-G> option has been removed. Two regular expressions on the
2104 command line was considered too confusing; to simulate B<-G>'s functionality,
2105 you may use the new B<-x> option to pipe filenames from one invocation of
2110 The B<--binary> option has been removed.
2114 The B<--skipped> option has been removed.
2118 The B<--text> option has been removed.
2122 The B<--invert-file-match> option has been removed. Instead, you may
2123 use B<-v> with B<-g>.
2127 =head2 CHANGED OPTIONS
2133 The options that modify the regular expression's behavior (B<-i>, B<-w>,
2134 B<-Q>, and B<-v>) may now be used with B<-g>.
2138 =head2 ADDED OPTIONS
2144 B<--files-from> was added so that a user may submit a list of filenames as
2145 a list of files to search.
2149 B<-x> was added to tell ack to accept a list of filenames via standard input;
2150 this list is the list of filenames that will be used for the search.
2154 B<-s> was added to tell ack to suppress error messages about non-existent or
2159 B<--ignore-directory> and B<--noignore-directory> were added as aliases for
2160 B<--ignore-dir> and B<--noignore-dir> respectively.
2164 B<--ignore-file> was added so that users may specify patterns of files to
2165 ignore (ex. /.*~$/).
2169 B<--dump> was added to allow users to easily find out which options are
2174 B<--create-ackrc> was added so that users may create custom ackrc files based
2175 on the default settings loaded by ack, and so that users may easily view those
2180 B<--type-del> was added to selectively remove file type definitions.
2184 B<--ignore-ack-defaults> was added so that users may ignore ack's default
2185 options in favor of their own.
2189 B<--bar> was added so ack users may consult Admiral Ackbar.
2195 Andy Lester, C<< <andy at petdance.com> >>
2199 Please report any bugs or feature requests to the issues list at
2200 Github: L<https://github.com/beyondgrep/ack2/issues>
2204 All enhancement requests MUST first be posted to the ack-users
2205 mailing list at L<http://groups.google.com/group/ack-users>. I
2206 will not consider a request without it first getting seen by other
2207 ack users. This includes requests for new filetypes.
2209 There is a list of enhancements I want to make to F<ack> in the ack
2210 issues list at Github: L<https://github.com/beyondgrep/ack2/issues>
2212 Patches are always welcome, but patches with tests get the most
2217 Support for and information about F<ack> can be found at:
2221 =item * The ack homepage
2223 L<https://beyondgrep.com/>
2225 =item * The ack-users mailing list
2227 L<http://groups.google.com/group/ack-users>
2229 =item * The ack issues list at Github
2231 L<https://github.com/beyondgrep/ack2/issues>
2233 =item * AnnoCPAN: Annotated CPAN documentation
2235 L<http://annocpan.org/dist/ack>
2237 =item * CPAN Ratings
2239 L<http://cpanratings.perl.org/d/ack>
2243 L<http://search.cpan.org/dist/ack>
2247 L<http://metacpan.org/release/ack>
2249 =item * Git source repository
2251 L<https://github.com/beyondgrep/ack2>
2255 =head1 ACKNOWLEDGEMENTS
2257 How appropriate to have I<ack>nowledgements!
2259 Thanks to everyone who has contributed to ack in any way, including
2272 SE<eacute>bastien FeugE<egrave>re,
2279 RaE<uacute>l GundE<iacute>n,
2285 RaE<aacute>l GundE<aacute>n,
2321 Eric Van Dewoestine,
2330 Christopher J. Madsen,
2342 GE<aacute>bor SzabE<oacute>,
2345 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
2349 Mark Leighton Fisher,
2355 Nilson Santos F. Jr,
2360 Ask BjE<oslash>rn Hansen,
2364 Slaven ReziE<0x107>,
2374 =head1 COPYRIGHT & LICENSE
2376 Copyright 2005-2017 Andy Lester.
2378 This program is free software; you can redistribute it and/or modify
2379 it under the terms of the Artistic License v2.0.
2381 See http://www.perlfoundation.org/artistic_license_2_0 or the LICENSE.md
2382 file that comes with the ack distribution.
2395 $COPYRIGHT = 'Copyright 2005-2017 Andy Lester.';
2410 our $is_filter_mode;
2411 our $output_to_pipe;
2417 use File
::Spec
1.00015 ();
2420 # These have to be checked before any filehandle diddling.
2421 $output_to_pipe = not -t
*STDOUT
;
2422 $is_filter_mode = -p STDIN
;
2424 $is_cygwin = ($^O eq 'cygwin' || $^O eq 'msys');
2425 $is_windows = ($^O eq 'MSWin32');
2426 $dir_sep_chars = $is_windows ? quotemeta( '\\/' ) : quotemeta( File
::Spec-
>catfile( '', '' ) );
2431 sub remove_dir_sep
{
2433 $path =~ s/[$dir_sep_chars]$//;
2441 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2446 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2450 require File
::Basename
;
2451 return File
::Basename
::basename
( $0 );
2456 sub filetypes_supported
{
2457 return keys %mappings;
2461 my $y = q{_ /|,\\'!.x',=(www)=, U };
2462 $y =~ tr/,x!w/\nOo_/;
2464 App
::Ack
::print( "$y ack $_[0]!\n" );
2472 3~!I#7#I"7#I!?!+!="+"="+!:!
2473 2?#I!7!I!?#I!7!I"+"=%+"=#
2474 1?"+!?*+!=#~"=!+#?"="+!
2475 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2476 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2478 ,,!?%I"?(+$=$~!=#:"~$:!~!
2479 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2480 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2481 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2482 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2483 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2484 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2485 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2486 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2487 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2488 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2489 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2490 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2491 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2492 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2493 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2494 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2495 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2496 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2497 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2498 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2499 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2500 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2501 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2502 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2503 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2504 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2505 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2506 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2507 7+:!,!~#,"=!7'I!?#I"7/+!7+
2508 77I!+!7!?!7!I"71+!7,
2511 return _pic_decode
($x);
2517 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2518 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2519 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2525 4.! $\! /M!~!.!8! +.!M# 4
2526 0,!.! (\! .~!M!N! ,+!I!.!M!.! 3
2527 /?!O!.!M!:! '\! .O!.! +~!Z!=!N!.! 4
2528 ..! !D!Z!.!Z!.! '\! 9=!M".! 6
2529 /.! !.!~!M".! '\! 8~! 9
2531 4.! &:!M! !N"M# !M"N!M! #D!M&=! =
2532 :M!7!M#:! !~!M!7!,!$!M!:! #.! !O!N!.!M!:!M# ;
2533 8Z!M"~!N!$!D!.!N!?! !I!N!.! (?!M! !M!,!D!M".! 9
2534 (?!Z!M!N!:! )=!M!O!8!.!M!+!M! !M!,! !O!M! +,!M!.!M!~!Z!N!M!:! &:!~! 0
2535 &8!7!.!~!M"D!M!,! &M!?!=!8! !M!,!O! !M!+! !+!O!.!M! $M#~! !.!8!M!Z!.!M! !O!M"Z! %:!~!M!Z!M!Z!.! +
2536 &:!M!7!,! *M!.!Z!M! !8"M!.!M!~! !.!M!.!=! #~!8!.!M! !7!M! "N!Z#I! !D!M!,!M!.! $."M!,! !M!.! *
2537 2$!O! "N! !.!M!I! !7" "M! "+!O! !~!M! !d!O!.!7!I!M!.! !.!O!=!M!.! !M",!M!.! %.!$!O!D! +
2538 1~!O! "M!+! !8!$! "M! "?!O! %Z!8!D!M!?!8!I!O!7!M! #M!.!M! "M",!M! 4
2539 07!~! ".!8! !.!M! "I!+! !.!M! &Z!D!.!7!=!M! !:!.!M! #:!8"+! !.!+!8! !8! 3
2540 /~!M! #N! !~!M!$! !.!M! !.!M" &~!M! "~!M!O! "D! $M! !8! "M!,!M!+!D!.! 1
2541 #.! #?!M!N!.! #~!O! $M!.!7!$! "?" !?!~!M! '7!8!?!M!.!+!M"O! $?"$!D! !.!O! !$!7!I!.! 0
2542 $,!M!:!O!?! ".! !?!=! $=!:!O! !M! "M! !M! !+!$! (.! +.!M! !M!.! !8! !+"Z!~! $:!M!$! !.! '
2543 #.!8!.!I!$! $7!I! %M" !=!M! !~!M!D! "7!I! .I!O! %?!=!,!D! !,!M! !D!~!8!~! %D!M! (
2544 #.!M"?! $=!O! %=!N! "8!.! !Z!M! #M!~! (M!:! #.!M" &O! !M!.! !?!,! !8!.!N!~! $8!N!M!,!.! %
2545 *$!O! &M!,! "O! !.!M!.! #M! (~!M( &O!.! !7! "M! !.!M!.!M!,! #.!M! !M! &
2546 )=!8!.! $.!M!O!.! "$!.!I!N! !I!M# (7!M(I! %D"Z!M! "=!I! "M! !M!:! #~!D! '
2547 )D! &8!N!:! ".!O! !M!="M! "M! (7!M) %." !M!D!."M!.! !$!=! !M!,! +
2548 (M! &+!.!M! #Z!7!O!M!.!~!8! +,!M#D!?!M#D! #.!Z!M#,!Z!?! !~!N! "N!.! !M! +
2549 'D!:! %$!D! !?! #M!Z! !8!.! !M"?!7!?!7! '+!I!D! !?!O!:!M!:! ":!M!:! !M!7".!M! "8!+! !:!D! !.!M! *
2550 %.!O!:! $.!O!+! !D!.! #M! "M!.!+!N!I!Z! "7!M!N!M!N!?!I!7!Z!=!M'D"~! #M!.!8!$! !:! !.!M! "N!?! !,!O! )
2551 !.!?!M!:!M!I! %8!,! "M!.! #M! "N! !M!.! !M!.! !+!~! !.!M!.! ':!M! $M! $M!Z!$! !M!.! "D! "M! "?!M! (
2552 !7!8! !+!I! ".! "$!=! ":!$! "+! !M!.! !O! !M!I!M".! !=!~! ",!O! '=!M! $$!,! #N!:! ":!8!.! !D!~! !,!M!.! !:!M!.! &
2553 !:!,!.! &Z" #D! !.!8!."M!.! !8!?!Z!M!.!M! #Z!~! !?!M!Z!.! %~!O!.!8!$!N!8!O!I!:!~! !+! #M!.! !.!M!.! !+!M! ".!~!M!+! $
2554 !.! 'D!I! #?!M!.!M!,! !.!Z! !.!8! #M&O!I!?! (~!I!M"." !M!Z!.! !M!N!.! "+!$!.! "M!.! !M!?!.! "8!M! $
2555 (O!8! $M! !M!.! ".!:! !+!=! #M! #.!M! !+" *$!M":!.! !M!~! "M!7! #M! #7!Z! "M"$!M!.! !.! #
2556 '$!Z! #.!7!+!M! $.!,! !+!:! #N! #.!M!.!+!M! +D!M! #=!N! ":!O! #=!M! #Z!D! $M!I! %
2557 $,! ".! $.!M" %$!.! !?!~! "+!7!." !.!M!,! !M! *,!N!M!.$M!?! "D!,! #M!.! #N! +
2558 ,M!Z! &M! "I!,! "M! %I!M! !?!=!.! (Z!8!M! $:!M!.! !,!M! $D! #.!M!.! )
2559 +8!O! &.!8! "I!,! !~!M! &N!M! !M!D! '?!N!O!." $?!7! "?!~! #M!.! #I!D!.! (
2560 3M!,! "N!.! !D" &.!+!M!.! !M":!.":!M!7!M!D! 'M!.! "M!.! "M!,! $I! )
2561 3I! #M! "M!,! !:! &.!M" ".!,! !.!$!M!I! #.! !:! !.!M!?! "N!+! ".! /
2562 1M!,! #.!M!8!M!=!.! +~!N"O!Z"~! *+!M!.! "M! 2
2563 0.!M! &M!.! 8:! %.!M!Z! "M!=! *O!,! %
2564 0?!$! &N! )." .,! %."M! ":!M!.! 0
2565 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0
2567 return _pic_decode
($x);
2571 my($compressed) = @_;
2572 $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2573 App
::Ack
::print( $compressed );
2579 my $help_arg = shift || 0;
2581 return show_help_types
() if $help_arg =~ /^types?/;
2583 App
::Ack
::print( <<"END_OF_HELP" );
2584 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2586 Search for PATTERN in each source file in the tree from the current
2587 directory on down. If any files or directories are specified, then
2588 only those files and directories are checked. ack may also search
2589 STDIN, but only if no file or directory arguments are specified,
2590 or if one of them is "-".
2592 Default switches may be specified in ACK_OPTIONS environment variable or
2593 an .ackrc file. If you want no dependency on the environment, turn it
2596 Example: ack -i select
2599 -i, --ignore-case Ignore case distinctions in PATTERN
2600 --[no]smart-case Ignore case distinctions in PATTERN,
2601 only if PATTERN contains no upper case.
2602 Ignored if -i is specified
2603 -v, --invert-match Invert match: select non-matching lines
2604 -w, --word-regexp Force PATTERN to match only whole words
2605 -Q, --literal Quote all metacharacters; PATTERN is literal
2608 --lines=NUM Only print line(s) NUM of each file
2609 -l, --files-with-matches Only print filenames containing matches
2610 -L, --files-without-matches Only print filenames with no matches
2611 --output=expr Output the evaluation of expr for each line
2612 (turns off text highlighting)
2613 -o Show only the part of a line matching PATTERN
2614 Same as --output='\$&'
2615 --passthru Print all lines, whether matching or not
2616 --match PATTERN Specify PATTERN explicitly.
2617 -m, --max-count=NUM Stop searching in each file after NUM matches
2618 -1 Stop searching after one match of any kind
2619 -H, --with-filename Print the filename for each match (default:
2620 on unless explicitly searching a single file)
2621 -h, --no-filename Suppress the prefixing filename on output
2622 -c, --count Show number of lines matching per file
2623 --[no]column Show the column number of the first match
2625 -A NUM, --after-context=NUM Print NUM lines of trailing context after
2627 -B NUM, --before-context=NUM Print NUM lines of leading context before
2629 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2631 --print0 Print null byte as separator between filenames,
2632 only works with -f, -g, -l, -L or -c.
2634 -s Suppress error messages about nonexistent or
2639 --pager=COMMAND Pipes all ack output through COMMAND. For
2640 example, --pager="less -R". Ignored if output
2642 --nopager Do not send output through a pager. Cancels
2643 any setting in ~/.ackrc, ACK_PAGER or
2645 --[no]heading Print a filename heading above each file's
2646 results. (default: on when used interactively)
2647 --[no]break Print a break between results from different
2648 files. (default: on when used interactively)
2649 --group Same as --heading --break
2650 --nogroup Same as --noheading --nobreak
2651 --[no]color Highlight the matching text (default: on unless
2652 output is redirected, or on Windows)
2653 --[no]colour Same as --[no]color
2654 --color-filename=COLOR
2656 --color-lineno=COLOR Set the color for filenames, matches, and line
2658 --flush Flush output immediately, even when ack is used
2659 non-interactively (when output goes to a pipe or
2664 -f Only print the files selected, without
2665 searching. The PATTERN must not be specified.
2666 -g Same as -f, but only select files matching
2668 --sort-files Sort the found files lexically.
2669 --show-types Show which types each file has.
2670 --files-from=FILE Read the list of files to search from FILE.
2671 -x Read the list of files to search from STDIN.
2673 File inclusion/exclusion:
2674 --[no]ignore-dir=name Add/remove directory from list of ignored dirs
2675 --[no]ignore-directory=name Synonym for ignore-dir
2676 --ignore-file=filter Add filter for ignoring files
2677 -r, -R, --recurse Recurse into subdirectories (default: on)
2678 -n, --no-recurse No descending into subdirectories
2679 --[no]follow Follow symlinks. Default is off.
2680 -k, --known-types Include only files of types that ack recognizes.
2682 --type=X Include only X files, where X is a recognized
2684 --type=noX Exclude X files.
2685 See "ack --help-types" for supported filetypes.
2687 File type specification:
2688 --type-set TYPE:FILTER:FILTERARGS
2689 Files with the given FILTERARGS applied to the
2690 given FILTER are recognized as being of type
2691 TYPE. This replaces an existing definition for
2693 --type-add TYPE:FILTER:FILTERARGS
2694 Files with the given FILTERARGS applied to the
2695 given FILTER are recognized as being type TYPE.
2696 --type-del TYPE Removes all filters associated with TYPE.
2700 --[no]env Ignore environment variables and global ackrc
2701 files. --env is legal but redundant.
2702 --ackrc=filename Specify an ackrc file to use
2703 --ignore-ack-defaults Ignore default definitions included with ack.
2704 --create-ackrc Outputs a default ackrc for your customization
2706 --help, -? This help
2707 --help-types Display all known types
2708 --dump Dump information on which options are loaded
2710 --[no]filter Force ack to treat standard input as a pipe
2711 (--filter) or tty (--nofilter)
2713 --version Display version & copyright
2714 --thpppt Bill the Cat
2715 --bar The warning admiral
2716 --cathy Chocolate! Chocolate! Chocolate!
2718 Exit status is 0 if match, 1 if no match.
2720 ack's home page is at https://beyondgrep.com/
2722 The full ack manual is available by running "ack --man".
2724 This is version $VERSION of ack. Run "ack --version" for full version info.
2732 sub show_help_types
{
2733 App
::Ack
::print( <<'END_OF_HELP' );
2734 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2736 The following is the list of filetypes supported by ack. You can
2737 specify a file type with the --type=TYPE format, or the --TYPE
2738 format. For example, both --type=perl and --perl work.
2740 Note that some extensions may appear in multiple types. For example,
2741 .pod files are both Perl and Parrot.
2745 my @types = filetypes_supported
();
2748 $maxlen = length if $maxlen < length;
2750 for my $type ( sort @types ) {
2751 next if $type =~ /^-/; # Stuff to not show
2752 my $ext_list = $mappings{$type};
2754 if ( ref $ext_list ) {
2755 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
2757 App
::Ack
::print( sprintf( " --[no]%-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2766 Pod
::Usage
::pod2usage
({
2767 -input
=> $App::Ack
::orig_program_name
,
2776 sub get_version_statement
{
2779 my $copyright = get_copyright
();
2780 my $this_perl = $Config::Config
{perlpath
};
2782 my $ext = $Config::Config
{_exe
};
2783 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2785 my $ver = sprintf( '%vd', $^V );
2787 return <<"END_OF_VERSION";
2789 Running under Perl $ver at $this_perl
2793 This program is free software. You may modify or distribute it
2794 under the terms of the Artistic License v2.0.
2799 sub print_version_statement
{
2800 App
::Ack
::print( get_version_statement
() );
2811 sub print { print {$fh} @_; return; }
2812 sub print_blank_line
{ App
::Ack
::print( "\n" ); return; }
2813 sub print_filename
{ App
::Ack
::print( $_[0], $_[1] ); return; }
2816 my $command = shift;
2818 return if App
::Ack
::output_to_pipe
();
2821 if ( not open( $pager, '|-', $command ) ) {
2822 App
::Ack
::die( qq{Unable to pipe to pager "$command": $!} );
2830 sub output_to_pipe
{
2831 return $output_to_pipe;
2836 my $nmatches = shift;
2838 my $rc = $nmatches ? 0 : 1;
2844 1; # End of App::Ack
2845 package App
::Ack
::Resource
;
2856 my $filename = shift;
2859 filename
=> $filename,
2864 if ( $self->{filename
} eq '-' ) {
2865 $self->{fh
} = *STDIN
;
2866 $self->{opened
} = 1;
2875 return $_[0]->{filename
};
2883 # XXX Definedness? Pre-populate the slot with an undef?
2884 unless ( exists $self->{basename
} ) {
2885 $self->{basename
} = (File
::Spec-
>splitpath($self->name))[2];
2888 return $self->{basename
};
2896 if ( !$self->{opened
} ) {
2897 if ( open $self->{fh
}, '<', $self->{filename
} ) {
2898 $self->{opened
} = 1;
2901 $self->{fh
} = undef;
2910 sub needs_line_scan
{
2914 return 1 if $opt->{v
};
2916 my $size = -s
$self->{fh
};
2920 elsif ( $size > 100_000 ) {
2925 my $rc = sysread( $self->{fh
}, $buffer, $size );
2926 if ( !defined($rc) && $App::Ack
::report_bad_filenames
) {
2927 App
::Ack
::warn( "$self->{filename}: $!" );
2930 return 0 unless $rc && ( $rc == $size );
2932 return $buffer =~ /$opt->{regex}/m;
2940 # Return if we haven't opened the file yet.
2941 if ( !defined($self->{fh
}) ) {
2945 if ( !seek( $self->{fh
}, 0, 0 ) && $App::Ack
::report_bad_filenames
) {
2946 App
::Ack
::warn( "$self->{filename}: $!" );
2957 # Return if we haven't opened the file yet.
2958 if ( !defined($self->{fh
}) ) {
2962 if ( !close($self->{fh
}) && $App::Ack
::report_bad_filenames
) {
2963 App
::Ack
::warn( $self->name() . ": $!" );
2966 $self->{opened
} = 0;
2976 return __PACKAGE__-
>new($self->name);
2984 if ( !exists $self->{firstliney
} ) {
2985 my $fh = $self->open();
2987 if ( $App::Ack
::report_bad_filenames
) {
2988 App
::Ack
::warn( $self->name . ': ' . $! );
2994 my $rc = sysread( $fh, $buffer, 250 );
2995 unless($rc) { # XXX handle this better?
2998 $buffer =~ s/[\r\n].*//s;
2999 $self->{firstliney
} = $buffer;
3005 return $self->{firstliney
};
3009 package App
::Ack
::Resources
;
3013 use Errno
qw(EACCES);
3018 sub _generate_error_handler
{
3021 if ( $opt->{dont_report_bad_filenames
} ) {
3024 if ( $! == EACCES
) {
3027 App
::Ack
::warn( $msg );
3033 App
::Ack
::warn( $msg );
3044 my $self = bless {}, $class;
3046 my $file_filter = undef;
3047 my $descend_filter = $opt->{descend_filter
};
3050 $descend_filter = sub {
3056 File
::Next
::files
( {
3057 file_filter
=> $opt->{file_filter
},
3058 descend_filter
=> $descend_filter,
3059 error_handler
=> _generate_error_handler
($opt),
3060 warning_handler
=> sub {},
3061 sort_files
=> $opt->{sort_files
},
3062 follow_symlinks
=> $opt->{follow
},
3075 File
::Next
::from_file
( {
3076 error_handler
=> _generate_error_handler
($opt),
3077 warning_handler
=> _generate_error_handler
($opt),
3078 sort_files
=> $opt->{sort_files
},
3079 }, $file ) or return undef;
3086 # This is for reading input lines from STDIN, not the list of files from STDIN
3091 my $self = bless {}, $class;
3093 my $has_been_called = 0;
3095 $self->{iter
} = sub {
3096 if ( !$has_been_called ) {
3097 $has_been_called = 1;
3109 my $file = $self->{iter
}->() or return;
3111 return App
::Ack
::Resource-
>new( $file );
3115 package App
::Ack
::ConfigDefault
;
3124 return split( /\n/, _options_block
() );
3129 return grep { /./ && !/^#/ } options
();
3133 sub _options_block
{
3134 my $lines = <<'HERE';
3135 # This is the default ackrc for ack version ==VERSION==.
3137 # There are four different ways to match
3139 # is: Match the filename exactly
3141 # ext: Match the extension of the filename exactly
3143 # match: Match the filename against a Perl regular expression
3145 # firstlinematch: Match the first 250 characters of the first line
3146 # of text against a Perl regular expression. This is only for
3147 # the --type-add option.
3150 ### Directories to ignore
3153 # http://bazaar.canonical.com/
3154 --ignore-directory=is:.bzr
3157 # http://freecode.com/projects/codeville
3158 --ignore-directory=is:.cdv
3160 # Interface Builder (Xcode)
3161 # http://en.wikipedia.org/wiki/Interface_Builder
3162 --ignore-directory=is:~.dep
3163 --ignore-directory=is:~.dot
3164 --ignore-directory=is:~.nib
3165 --ignore-directory=is:~.plst
3168 # http://git-scm.com/
3169 --ignore-directory=is:.git
3170 # When using submodules, .git is a file.
3171 --ignore-file=is:.git
3174 # http://mercurial.selenic.com/
3175 --ignore-directory=is:.hg
3178 # http://directory.fsf.org/wiki/Quilt
3179 --ignore-directory=is:.pc
3182 # http://subversion.tigris.org/
3183 --ignore-directory=is:.svn
3186 # http://www.monotone.ca/
3187 --ignore-directory=is:_MTN
3190 # http://savannah.nongnu.org/projects/cvs
3191 --ignore-directory=is:CVS
3194 # http://www.gnu.org/software/rcs/
3195 --ignore-directory=is:RCS
3198 # http://en.wikipedia.org/wiki/Source_Code_Control_System
3199 --ignore-directory=is:SCCS
3203 --ignore-directory=is:_darcs
3206 --ignore-directory=is:_sgbak
3209 # http://www.gnu.org/software/autoconf/
3210 --ignore-directory=is:autom4te.cache
3212 # Perl module building
3213 --ignore-directory=is:blib
3214 --ignore-directory=is:_build
3216 # Perl Devel::Cover module's output directory
3217 # https://metacpan.org/release/Devel-Cover
3218 --ignore-directory=is:cover_db
3220 # Node modules created by npm
3221 --ignore-directory=is:node_modules
3224 # http://www.cmake.org/
3225 --ignore-directory=is:CMakeFiles
3227 # Eclipse workspace folder
3228 # http://eclipse.org/
3229 --ignore-directory=is:.metadata
3231 # Cabal (Haskell) sandboxes
3232 # http://www.haskell.org/cabal/users-guide/installing-packages.html
3233 --ignore-directory=is:.cabal-sandbox
3238 --ignore-file=ext:bak
3239 --ignore-file=match:/~$/
3242 --ignore-file=match:/^#.+#$/
3244 # vi/vim swap files http://vim.org/
3245 --ignore-file=match:/[._].*\.swp$/
3248 --ignore-file=match:/core\.\d+$/
3250 # minified Javascript
3251 --ignore-file=match:/[.-]min[.]js$/
3252 --ignore-file=match:/[.]js[.]min$/
3255 --ignore-file=match:/[.]min[.]css$/
3256 --ignore-file=match:/[.]css[.]min$/
3258 # JS and CSS source maps
3259 --ignore-file=match:/[.]js[.]map$/
3260 --ignore-file=match:/[.]css[.]map$/
3262 # PDFs, because they pass Perl's -T detection
3263 --ignore-file=ext:pdf
3265 # Common graphics, just as an optimization
3266 --ignore-file=ext:gif,jpg,jpeg,png
3269 ### Filetypes defined
3273 --type-add=perl:ext:pl,pm,pod,t,psgi
3274 --type-add=perl:firstlinematch:/^#!.*\bperl/
3277 --type-add=perltest:ext:t
3280 # http://www.gnu.org/s/make/
3281 --type-add=make:ext:mk
3282 --type-add=make:ext:mak
3283 --type-add=make:is:makefile
3284 --type-add=make:is:Makefile
3285 --type-add=make:is:Makefile.Debug
3286 --type-add=make:is:Makefile.Release
3289 # http://rake.rubyforge.org/
3290 --type-add=rake:is:Rakefile
3293 # http://www.cmake.org/
3294 --type-add=cmake:is:CMakeLists.txt
3295 --type-add=cmake:ext:cmake
3298 --type-add=actionscript:ext:as,mxml
3301 # http://www.adaic.org/
3302 --type-add=ada:ext:ada,adb,ads
3305 # http://msdn.microsoft.com/en-us/library/aa286483.aspx
3306 --type-add=asp:ext:asp
3309 # http://www.asp.net/
3310 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
3313 --type-add=asm:ext:asm,s
3316 --type-add=batch:ext:bat,cmd
3319 # http://en.wikipedia.org/wiki/ColdFusion
3320 --type-add=cfmx:ext:cfc,cfm,cfml
3323 # http://clojure.org/
3324 --type-add=clojure:ext:clj,cljs,edn,cljc
3327 # .xs are Perl C files
3328 --type-add=cc:ext:c,h,xs
3334 # http://coffeescript.org/
3335 --type-add=coffeescript:ext:coffee
3338 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
3341 --type-add=hpp:ext:hpp,hh,h,hxx
3344 --type-add=csharp:ext:cs
3347 # http://www.w3.org/Style/CSS/
3348 --type-add=css:ext:css
3351 # http://www.dartlang.org/
3352 --type-add=dart:ext:dart
3355 # http://en.wikipedia.org/wiki/Embarcadero_Delphi
3356 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
3359 # http://elixir-lang.org/
3360 --type-add=elixir:ext:ex,exs
3363 # http://www.gnu.org/software/emacs
3364 --type-add=elisp:ext:el
3367 # http://www.erlang.org/
3368 --type-add=erlang:ext:erl,hrl
3371 # http://en.wikipedia.org/wiki/Fortran
3372 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
3375 # http://golang.org/
3376 --type-add=go:ext:go
3379 # http://groovy.codehaus.org/
3380 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
3383 # http://groovy.codehaus.org/GSP
3384 --type-add=gsp:ext:gsp
3387 # http://www.haskell.org/
3388 --type-add=haskell:ext:hs,lhs
3391 --type-add=html:ext:htm,html,xhtml
3394 # http://jade-lang.com/
3395 --type-add=jade:ext:jade
3398 # http://www.oracle.com/technetwork/java/index.html
3399 --type-add=java:ext:java,properties
3402 --type-add=js:ext:js
3405 # http://www.oracle.com/technetwork/java/javaee/jsp/index.html
3406 --type-add=jsp:ext:jsp,jspx,jspf,jhtm,jhtml
3409 # http://www.json.org/
3410 --type-add=json:ext:json
3413 # https://kotlinlang.org/
3414 --type-add=kotlin:ext:kt,kts
3417 # http://www.lesscss.org/
3418 --type-add=less:ext:less
3421 # http://common-lisp.net/
3422 --type-add=lisp:ext:lisp,lsp
3425 # http://www.lua.org/
3426 --type-add=lua:ext:lua
3427 --type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
3430 --type-add=objc:ext:m,h
3433 --type-add=objcpp:ext:mm,h
3436 # http://caml.inria.fr/
3437 --type-add=ocaml:ext:ml,mli,mll,mly
3440 # http://en.wikipedia.org/wiki/MATLAB
3441 --type-add=matlab:ext:m
3444 # http://www.parrot.org/
3445 --type-add=parrot:ext:pir,pasm,pmc,ops,pod,pg,tg
3448 # http://www.php.net/
3449 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
3450 --type-add=php:firstlinematch:/^#!.*\bphp/
3454 --type-add=plone:ext:pt,cpt,metadata,cpy,py
3457 # http://www.python.org/
3458 --type-add=python:ext:py
3459 --type-add=python:firstlinematch:/^#!.*\bpython/
3462 # http://www.r-project.org/
3466 # http://docutils.sourceforge.net/rst.html
3467 --type-add=rst:ext:rst
3470 # http://www.ruby-lang.org/
3471 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
3472 --type-add=ruby:is:Rakefile
3473 --type-add=ruby:firstlinematch:/^#!.*\bruby/
3476 # http://www.rust-lang.org/
3477 --type-add=rust:ext:rs
3480 # http://sass-lang.com
3481 --type-add=sass:ext:sass,scss
3484 # http://www.scala-lang.org/
3485 --type-add=scala:ext:scala
3488 # http://groups.csail.mit.edu/mac/projects/scheme/
3489 --type-add=scheme:ext:scm,ss
3492 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
3493 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
3496 # http://www.smalltalk.org/
3497 --type-add=smalltalk:ext:st
3500 # http://www.smarty.net/
3501 --type-add=smarty:ext:tpl
3504 # http://www.iso.org/iso/catalogue_detail.htm?csnumber=45498
3505 --type-add=sql:ext:sql,ctl
3508 # http://learnboost.github.io/stylus/
3509 --type-add=stylus:ext:styl
3512 # https://developer.apple.com/swift/
3513 --type-add=swift:ext:swift
3514 --type-add=swift:firstlinematch:/^#!.*\bswift/
3517 # http://www.tcl.tk/
3518 --type-add=tcl:ext:tcl,itcl,itk
3521 # http://www.latex-project.org/
3522 --type-add=tex:ext:tex,cls,sty
3524 # Template Toolkit (Perl)
3525 # http://template-toolkit.org/
3526 --type-add=tt:ext:tt,tt2,ttml
3529 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
3532 --type-add=verilog:ext:v,vh,sv
3535 # http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
3536 --type-add=vhdl:ext:vhd,vhdl
3539 # http://www.vim.org/
3540 --type-add=vim:ext:vim
3543 # http://www.w3.org/TR/REC-xml/
3544 --type-add=xml:ext:xml,dtd,xsd,xsl,xslt,ent,wsdl
3545 --type-add=xml:firstlinematch:/<[?]xml/
3549 --type-add=yaml:ext:yaml,yml
3551 $lines =~ s/==VERSION==/$App::Ack::VERSION/sm;
3557 package App
::Ack
::ConfigFinder
;
3564 use File
::Spec
3.00;
3566 use if ($^O eq 'MSWin32'), 'Win32';
3572 return bless {}, $class;
3576 sub _remove_redundancies
{
3580 foreach my $config (@configs) {
3581 my $key = $config->{path
};
3582 if ( not $App::Ack
::is_windows
) {
3583 # On Unix, uniquify on inode.
3584 my ($dev, $inode) = (stat $key)[0, 1];
3585 $key = "$dev:$inode" if defined $dev;
3587 undef $config if $seen{$key}++;
3589 return grep { defined } @configs;
3593 sub _check_for_ackrc
{
3594 return unless defined $_[0];
3596 my @files = grep { -f
}
3597 map { File
::Spec-
>catfile(@_, $_) }
3600 die File
::Spec-
>catdir(@_) . " contains both .ackrc and _ackrc.\n" .
3601 "Please remove one of those files.\n"
3604 return wantarray ? @files : $files[0];
3605 } # end _check_for_ackrc
3609 sub find_config_files
{
3612 if ( $App::Ack
::is_windows
) {
3613 push @config_files, map { +{ path
=> File
::Spec-
>catfile($_, 'ackrc') } } (
3614 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3615 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3619 push @config_files, { path
=> '/etc/ackrc' };
3623 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3624 push @config_files, { path
=> $ENV{'ACKRC'} };
3627 push @config_files, map { +{ path
=> $_ } } _check_for_ackrc
($ENV{'HOME'});
3630 my $cwd = Cwd
::getcwd
();
3631 return () unless defined $cwd;
3633 # XXX This should go through some untainted cwd-fetching function, and not get untainted brute-force like this.
3636 my @dirs = File
::Spec-
>splitdir( $cwd );
3638 my $ackrc = _check_for_ackrc
(@dirs);
3639 if(defined $ackrc) {
3640 push @config_files, { project
=> 1, path
=> $ackrc };
3646 # We only test for existence here, so if the file is deleted out from under us, this will fail later.
3647 return _remove_redundancies
( @config_files );
3655 return unless defined $file && -e
$file;
3659 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
3660 while ( my $line = <$fh> ) {
3665 next if $line eq '';
3666 next if $line =~ /^\s*#/;
3668 push( @lines, $line );
3670 close $fh or App
::Ack
::die( "Unable to close $file: $!" );
3676 package App
::Ack
::ConfigLoader
;
3682 use Getopt
::Long
2.38 ();
3683 use Text
::ParseWords
3.1 ();
3686 my @INVALID_COMBINATIONS;
3689 my @context = qw( -A -B -C --after-context --before-context --context );
3690 my @pretty = qw( --heading --group --break );
3691 my @filename = qw( -h -H --with-filename --no-filename );
3693 @INVALID_COMBINATIONS = (
3695 [qw(-l)] => [@context, @pretty, @filename, qw(-L -o --passthru --output --max-count --column -f -g --show-types)],
3696 [qw(-L)] => [@context, @pretty, @filename, qw(-l -o --passthru --output --max-count --column -f -g --show-types -c --count)],
3697 [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)],
3698 [qw(-o)] => [@context, qw(--output -c --count --column --column -f --show-types)],
3699 [qw(--passthru)] => [@context, qw(--output --column -m --max-count -1 -c --count -f -g)],
3700 [qw(--output)] => [@context, qw(-c --count -f -g)],
3701 [qw(--match)] => [qw(-f -g)],
3702 [qw(-m --max-count)] => [qw(-1 -f -g -c --count)],
3703 [qw(-h --no-filename)] => [qw(-H --with-filename -f -g --group --heading)],
3704 [qw(-H --with-filename)] => [qw(-h --no-filename -f -g)],
3705 [qw(-c --count)] => [@context, @pretty, qw(--column -f -g)],
3706 [qw(--column)] => [qw(-f -g)],
3707 [@context] => [qw(-f -g)],
3708 [qw(-f)] => [qw(-g), @pretty],
3709 [qw(-g)] => [qw(-f), @pretty],
3713 sub _generate_ignore_dir
{
3714 my ( $option_name, $opt ) = @_;
3716 my $is_inverted = $option_name =~ /^--no/;
3719 my ( undef, $dir ) = @_;
3721 $dir = App
::Ack
::remove_dir_sep
( $dir );
3722 if ( $dir !~ /:/ ) {
3723 $dir = 'is:' . $dir;
3726 my ( $filter_type, $args ) = split /:/, $dir, 2;
3728 if ( $filter_type eq 'firstlinematch' ) {
3729 Carp
::croak
( qq{Invalid filter specification "$filter_type" for option '$option_name'} );
3732 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args));
3735 my $previous_inversion_matches = $opt->{idirs
} && !($is_inverted xor $opt->{idirs
}[-1]->is_inverted());
3737 if ( $previous_inversion_matches ) {
3738 $collection = $opt->{idirs
}[-1];
3740 if ( $is_inverted ) {
3741 # XXX this relies on invert of an inverted filter
3742 # to return the original
3743 $collection = $collection->invert()
3747 $collection = App
::Ack
::Filter
::Collection-
>new();
3749 if ( $is_inverted ) {
3750 push @{ $opt->{idirs
} }, $collection->invert();
3753 push @{ $opt->{idirs
} }, $collection;
3757 $collection->add($filter);
3759 if ( $filter_type eq 'is' ) {
3760 $collection->add(App
::Ack
::Filter
::IsPath-
>new($args));
3765 sub process_filter_spec
{
3768 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3769 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3771 return ( $type_name,
3772 App
::Ack
::Filter-
>create_filter($ext_type, split(/,/, $arguments)) );
3774 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3775 my ( $type_name, $extensions ) = ( $1, $2 );
3777 my @extensions = split(/,/, $extensions);
3778 foreach my $extension ( @extensions ) {
3779 $extension =~ s/^[.]//;
3782 return ( $type_name, App
::Ack
::Filter-
>create_filter('ext', @extensions) );
3785 Carp
::croak
"invalid filter specification '$spec'";
3790 sub uninvert_filter
{
3791 my ( $opt, @filters ) = @_;
3793 return unless defined $opt->{filters
} && @filters;
3795 # Loop through all the registered filters. If we hit one that
3796 # matches this extension and it's inverted, we need to delete it from
3798 for ( my $i = 0; $i < @{ $opt->{filters
} }; $i++ ) {
3799 my $opt_filter = @{ $opt->{filters
} }[$i];
3801 # XXX Do a real list comparison? This just checks string equivalence.
3802 if ( $opt_filter->is_inverted() && "$opt_filter->{filter}" eq "@filters" ) {
3803 splice @{ $opt->{filters
} }, $i, 1;
3812 sub process_filetypes
{
3813 my ( $opt, $arg_sources ) = @_;
3815 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version'); # start with default options, minus some annoying ones
3816 Getopt
::Long
::Configure
(
3821 my %additional_specs;
3823 my $add_spec = sub {
3824 my ( undef, $spec ) = @_;
3826 my ( $name, $filter ) = process_filter_spec
($spec);
3828 push @{ $App::Ack
::mappings
{$name} }, $filter;
3830 $additional_specs{$name . '!'} = sub {
3831 my ( undef, $value ) = @_;
3833 my @filters = @{ $App::Ack
::mappings
{$name} };
3835 @filters = map { $_->invert() } @filters;
3838 uninvert_filter
( $opt, @filters );
3841 push @{ $opt->{'filters'} }, @filters;
3845 my $set_spec = sub {
3846 my ( undef, $spec ) = @_;
3848 my ( $name, $filter ) = process_filter_spec
($spec);
3850 $App::Ack
::mappings
{$name} = [ $filter ];
3852 $additional_specs{$name . '!'} = sub {
3853 my ( undef, $value ) = @_;
3855 my @filters = @{ $App::Ack
::mappings
{$name} };
3857 @filters = map { $_->invert() } @filters;
3860 push @{ $opt->{'filters'} }, @filters;
3864 my $delete_spec = sub {
3865 my ( undef, $name ) = @_;
3867 delete $App::Ack
::mappings
{$name};
3868 delete $additional_specs{$name . '!'};
3871 my %type_arg_specs = (
3872 'type-add=s' => $add_spec,
3873 'type-set=s' => $set_spec,
3874 'type-del=s' => $delete_spec,
3877 foreach my $source (@{$arg_sources}) {
3878 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
3881 # $args are modified in place, so no need to munge $arg_sources
3882 local @ARGV = @{$args};
3883 Getopt
::Long
::GetOptions
(%type_arg_specs);
3887 ( undef, $source->{contents
} ) =
3888 Getopt
::Long
::GetOptionsFromString
($args, %type_arg_specs);
3892 $additional_specs{'k|known-types'} = sub {
3893 my ( undef, $value ) = @_;
3895 my @filters = map { @{$_} } values(%App::Ack
::mappings
);
3897 push @{ $opt->{'filters'} }, @filters;
3900 return \
%additional_specs;
3904 sub removed_option
{
3905 my ( $option, $explanation ) = @_;
3907 $explanation ||= '';
3909 warn "Option '$option' is not valid in ack 2.\n$explanation";
3916 my ( $opt, $extra_specs ) = @_;
3918 my $dash_a_explanation = <<'EOT';
3919 You don't need -a, ack 1.x users. This is because ack 2.x has
3920 -k/--known-types which makes it only select files of known types, rather
3921 than any text file (which is the behavior of ack 1.x).
3923 If you're surprised to see this message because you didn't put -a on the
3924 command line, you may have options in an .ackrc, or in the ACKRC_OPTIONS
3925 environment variable. Try using the --dump flag to help find it.
3929 sub _context_value
{
3932 # Contexts default to 2.
3933 return (!defined($val) || ($val < 0)) ? 2 : $val;
3937 1 => sub { $opt->{1} = $opt->{m
} = 1 },
3938 'A|after-context:-1' => sub { shift; $opt->{after_context
} = _context_value
(shift) },
3939 'B|before-context:-1' => sub { shift; $opt->{before_context
} = _context_value
(shift) },
3940 'C|context:-1' => sub { shift; $opt->{before_context
} = $opt->{after_context
} = _context_value
(shift) },
3941 'a' => removed_option
('-a', $dash_a_explanation),
3942 'all' => removed_option
('--all', $dash_a_explanation),
3943 'break!' => \
$opt->{break},
3944 c
=> \
$opt->{count
},
3945 'color|colour!' => \
$opt->{color
},
3946 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
3947 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
3948 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
3949 'column!' => \
$opt->{column
},
3950 count
=> \
$opt->{count
},
3951 'create-ackrc' => sub { print "$_\n" for ( '--ignore-ack-defaults', App
::Ack
::ConfigDefault
::options
() ); exit; },
3953 my ( undef, $value ) = @_;
3956 $opt->{noenv_seen
} = 1;
3960 'files-from=s' => \
$opt->{files_from
},
3961 'filter!' => \
$App::Ack
::is_filter_mode
,
3962 flush
=> \
$opt->{flush
},
3963 'follow!' => \
$opt->{follow
},
3965 G
=> removed_option
('-G'),
3966 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
3967 'heading!' => \
$opt->{heading
},
3968 'h|no-filename' => \
$opt->{h
},
3969 'H|with-filename' => \
$opt->{H
},
3970 'i|ignore-case' => \
$opt->{i
},
3971 'ignore-directory|ignore-dir=s' => _generate_ignore_dir
('--ignore-dir', $opt),
3972 'ignore-file=s' => sub {
3973 my ( undef, $file ) = @_;
3975 my ( $filter_type, $args ) = split /:/, $file, 2;
3977 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args));
3979 if ( !$opt->{ifiles
} ) {
3980 $opt->{ifiles
} = App
::Ack
::Filter
::Collection-
>new();
3982 $opt->{ifiles
}->add($filter);
3984 'lines=s' => sub { shift; my $val = shift; push @{$opt->{lines
}}, $val },
3985 'l|files-with-matches'
3987 'L|files-without-matches'
3989 'm|max-count=i' => \
$opt->{m
},
3990 'match=s' => \
$opt->{regex
},
3991 'n|no-recurse' => \
$opt->{n
},
3992 o
=> sub { $opt->{output
} = '$&' },
3993 'output=s' => \
$opt->{output
},
3995 my ( undef, $value ) = @_;
3997 $opt->{pager
} = $value || $ENV{PAGER
};
3999 'noignore-directory|noignore-dir=s' => _generate_ignore_dir
('--noignore-dir', $opt),
4000 'nopager' => sub { $opt->{pager
} = undef },
4001 'passthru' => \
$opt->{passthru
},
4002 'print0' => \
$opt->{print0
},
4003 'Q|literal' => \
$opt->{Q
},
4004 'r|R|recurse' => sub { $opt->{n
} = 0 },
4005 's' => \
$opt->{dont_report_bad_filenames
},
4006 'show-types' => \
$opt->{show_types
},
4007 'smart-case!' => \
$opt->{smart_case
},
4008 'sort-files' => \
$opt->{sort_files
},
4010 my ( $getopt, $value ) = @_;
4013 if ( $value =~ s/^no// ) {
4017 my $callback = $extra_specs->{ $value . '!' };
4020 $callback->( $getopt, $cb_value );
4023 Carp
::croak
( "Unknown type '$value'" );
4026 'u' => removed_option
('-u'),
4027 'unrestricted' => removed_option
('--unrestricted'),
4028 'v|invert-match' => \
$opt->{v
},
4029 'w|word-regexp' => \
$opt->{w
},
4030 'x' => sub { $opt->{files_from
} = '-' },
4032 'version' => sub { App
::Ack
::print_version_statement
(); exit; },
4033 'help|?:s' => sub { shift; App
::Ack
::show_help
(@_); exit; },
4034 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
4035 'man' => sub { App
::Ack
::show_man
(); exit; },
4036 $extra_specs ? %{$extra_specs} : (),
4042 my ( $opt, $extra_specs, $arg_sources ) = @_;
4044 # Start with default options, minus some annoying ones.
4045 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4046 Getopt
::Long
::Configure
(
4052 my $is_help_types_active;
4054 foreach my $source (@{$arg_sources}) {
4055 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4057 if ( $source_name eq 'ARGV' ) {
4058 $argv_source = $args;
4063 if ( $argv_source ) { # This *should* always be true, but you never know...
4064 my @copy = @{$argv_source};
4065 local @ARGV = @copy;
4067 Getopt
::Long
::Configure
('pass_through');
4069 Getopt
::Long
::GetOptions
(
4070 'help-types' => \
$is_help_types_active,
4073 Getopt
::Long
::Configure
('no_pass_through');
4076 my $arg_specs = get_arg_spec
($opt, $extra_specs);
4078 foreach my $source (@{$arg_sources}) {
4079 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4081 my $args_for_source = $arg_specs;
4083 if ( $source->{project
} ) {
4085 die "Options --output, --pager and --match are forbidden in project .ackrc files.\n";
4088 $args_for_source = {
4089 %{$args_for_source},
4090 'output=s' => $illegal,
4091 'pager:s' => $illegal,
4092 'match=s' => $illegal,
4098 local @ARGV = @{$args};
4099 $ret = Getopt
::Long
::GetOptions
( %{$args_for_source} );
4103 ( $ret, $source->{contents
} ) =
4104 Getopt
::Long
::GetOptionsFromString
( $args, %{$args_for_source} );
4107 if ( !$is_help_types_active ) {
4108 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
4109 App
::Ack
::die( "Invalid option $where" );
4112 if ( $opt->{noenv_seen
} ) {
4113 App
::Ack
::die( "--noenv found in $source_name" );
4117 # XXX We need to check on a -- in the middle of a non-ARGV source
4123 sub should_dump_options
{
4124 my ( $sources ) = @_;
4126 foreach my $source (@{$sources}) {
4127 my ( $name, $options ) = @{$source}{qw
/name contents/};
4129 if($name eq 'ARGV') {
4131 local @ARGV = @{$options};
4132 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
4133 Getopt
::Long
::GetOptions
(
4136 @{$options} = @ARGV;
4144 sub explode_sources
{
4145 my ( $sources ) = @_;
4149 Getopt
::Long
::Configure
('default', 'pass_through', 'no_auto_help', 'no_auto_version');
4152 my $arg_spec = get_arg_spec
(\
%opt);
4154 my $add_type = sub {
4155 my ( undef, $arg ) = @_;
4158 if ( $arg =~ /(\w+)=/) {
4159 $arg_spec->{$1} = sub {};
4162 ( $arg ) = split /:/, $arg;
4163 $arg_spec->{$arg} = sub {};
4167 my $del_type = sub {
4168 my ( undef, $arg ) = @_;
4170 delete $arg_spec->{$arg};
4173 foreach my $source (@{$sources}) {
4174 my ( $name, $options ) = @{$source}{qw
/name contents/};
4175 if ( ref($options) ne 'ARRAY' ) {
4176 $source->{contents
} = $options =
4177 [ Text
::ParseWords
::shellwords
($options) ];
4180 for my $j ( 0 .. @{$options}-1 ) {
4181 next unless $options->[$j] =~ /^-/;
4182 my @chunk = ( $options->[$j] );
4183 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
4187 local @ARGV = @chunk;
4188 Getopt
::Long
::GetOptions
(
4189 'type-add=s' => $add_type,
4190 'type-set=s' => $add_type,
4191 'type-del=s' => $del_type,
4193 Getopt
::Long
::GetOptions
( %{$arg_spec} );
4195 push @new_sources, {
4202 return \
@new_sources;
4209 my $first_a = $a->[0];
4210 my $first_b = $b->[0];
4212 $first_a =~ s/^--?//;
4213 $first_b =~ s/^--?//;
4215 return $first_a cmp $first_b;
4220 my ( $sources ) = @_;
4222 $sources = explode_sources
($sources);
4227 foreach my $source (@{$sources}) {
4228 my ( $name, $contents ) = @{$source}{qw
/name contents/};
4229 if ( not $opts_by_source{$name} ) {
4230 $opts_by_source{$name} = [];
4231 push @source_names, $name;
4233 push @{$opts_by_source{$name}}, $contents;
4236 foreach my $name (@source_names) {
4237 my $contents = $opts_by_source{$name};
4240 print '=' x
length($name), "\n";
4241 print ' ', join(' ', @{$_}), "\n" foreach sort { compare_opts
($a, $b) } @{$contents};
4248 sub remove_default_options_if_needed
{
4249 my ( $sources ) = @_;
4253 foreach my $index ( 0 .. $#{$sources} ) {
4254 if ( $sources->[$index]{'name'} eq 'Defaults' ) {
4255 $default_index = $index;
4260 return $sources unless defined $default_index;
4262 my $should_remove = 0;
4264 # Start with default options, minus some annoying ones.
4265 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4266 Getopt
::Long
::Configure
(
4272 foreach my $index ( $default_index + 1 .. $#{$sources} ) {
4273 my ( $name, $args ) = @{$sources->[$index]}{qw
/name contents/};
4276 local @ARGV = @{$args};
4277 Getopt
::Long
::GetOptions
(
4278 'ignore-ack-defaults' => \
$should_remove,
4283 ( undef, $sources->[$index]{contents
} ) = Getopt
::Long
::GetOptionsFromString
($args,
4284 'ignore-ack-defaults' => \
$should_remove,
4289 Getopt
::Long
::Configure
('default');
4290 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4292 return $sources unless $should_remove;
4294 my @copy = @{$sources};
4295 splice @copy, $default_index, 1;
4300 sub check_for_mutually_exclusive_options
{
4301 my ( $arg_sources ) = @_;
4303 my %mutually_exclusive_with;
4304 my @copy = @{$arg_sources};
4306 for(my $i = 0; $i < @INVALID_COMBINATIONS; $i += 2) {
4307 my ( $lhs, $rhs ) = @INVALID_COMBINATIONS[ $i, $i + 1 ];
4309 foreach my $l_opt ( @{$lhs} ) {
4310 foreach my $r_opt ( @{$rhs} ) {
4311 push @{ $mutually_exclusive_with{ $l_opt } }, $r_opt;
4312 push @{ $mutually_exclusive_with{ $r_opt } }, $l_opt;
4320 my $source = shift @copy;
4321 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4322 $args = ref($args) ? [ @{$args} ] : [ Text
::ParseWords
::shellwords
($args) ];
4324 foreach my $opt ( @{$args} ) {
4325 next unless $opt =~ /^[-+]/;
4326 last if $opt eq '--';
4328 if( $opt =~ /^(.*)=/ ) {
4331 elsif ( $opt =~ /^(-[^-]).+/ ) {
4335 $set_opts{ $opt } = 1;
4337 my $mutex_opts = $mutually_exclusive_with{ $opt };
4339 next unless $mutex_opts;
4341 foreach my $mutex_opt ( @{$mutex_opts} ) {
4342 if($set_opts{ $mutex_opt }) {
4343 die "Options '$mutex_opt' and '$opt' are mutually exclusive\n";
4354 my $arg_sources = \
@_;
4357 pager
=> $ENV{ACK_PAGER_COLOR
} || $ENV{ACK_PAGER
},
4360 check_for_mutually_exclusive_options
($arg_sources);
4362 $arg_sources = remove_default_options_if_needed
($arg_sources);
4364 if ( should_dump_options
($arg_sources) ) {
4365 dump_options
($arg_sources);
4369 my $type_specs = process_filetypes
(\
%opt, $arg_sources);
4370 process_other
(\
%opt, $type_specs, $arg_sources);
4371 while ( @{$arg_sources} ) {
4372 my $source = shift @{$arg_sources};
4373 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4375 # All of our sources should be transformed into an array ref
4377 if ( $source_name eq 'ARGV' ) {
4381 Carp
::croak
"source '$source_name' has extra arguments!";
4385 Carp
::croak
'The impossible has occurred!';
4388 my $filters = ($opt{filters
} ||= []);
4390 # Throw the default filter in if no others are selected.
4391 if ( not grep { !$_->is_inverted() } @{$filters} ) {
4392 push @{$filters}, App
::Ack
::Filter
::Default-
>new();
4398 sub retrieve_arg_sources
{
4404 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4405 Getopt
::Long
::Configure
('pass_through');
4406 Getopt
::Long
::Configure
('no_auto_abbrev');
4408 Getopt
::Long
::GetOptions
(
4410 'ackrc=s' => \
$ackrc,
4413 Getopt
::Long
::Configure
('default', 'no_auto_help', 'no_auto_version');
4418 my $finder = App
::Ack
::ConfigFinder-
>new;
4419 @files = $finder->find_config_files;
4422 # We explicitly use open so we get a nice error message.
4423 # XXX This is a potential race condition!.
4424 if(open my $fh, '<', $ackrc) {
4428 die "Unable to load ackrc '$ackrc': $!"
4430 push( @files, { path
=> $ackrc } );
4433 push @arg_sources, {
4435 contents
=> [ App
::Ack
::ConfigDefault
::options_clean
() ],
4438 foreach my $file ( @files) {
4439 my @lines = App
::Ack
::ConfigFinder
::read_rcfile
($file->{path
});
4442 push @arg_sources, {
4443 name
=> $file->{path
},
4444 contents
=> \
@lines,
4445 project
=> $file->{project
},
4450 if ( $ENV{ACK_OPTIONS
} && !$noenv ) {
4451 push @arg_sources, {
4452 name
=> 'ACK_OPTIONS',
4453 contents
=> $ENV{ACK_OPTIONS
},
4457 push @arg_sources, {
4459 contents
=> [ @ARGV ],
4462 return @arg_sources;
4465 1; # End of App::Ack::ConfigLoader
4466 package App
::Ack
::Filter
;
4478 my ( undef, $type, @args ) = @_;
4480 if ( my $package = $filter_types{$type} ) {
4481 return $package->new(@args);
4483 Carp
::croak
"Unknown filter type '$type'";
4487 sub register_filter
{
4488 my ( undef, $type, $package ) = @_;
4490 $filter_types{$type} = $package;
4499 return App
::Ack
::Filter
::Inverse-
>new( $self );
4511 return '(unimplemented to_string)';
4522 package App
::Ack
::Filter
::Extension
;
4528 our @ISA = 'App::Ack::Filter';
4533 my ( $class, @extensions ) = @_;
4535 my $exts = join('|', map { "\Q$_\E"} @extensions);
4536 my $re = qr/[.](?:$exts)$/i;
4539 extensions
=> \
@extensions,
4541 groupname
=> 'ExtensionGroup',
4546 return App
::Ack
::Filter
::ExtensionGroup-
>new();
4550 my ( $self, $resource ) = @_;
4552 my $re = $self->{'regex'};
4554 return $resource->name =~ /$re/;
4560 my $re = $self->{'regex'};
4562 return ref($self) . " - $re";
4568 my $exts = $self->{'extensions'};
4570 return join(' ', map { ".$_" } @{$exts});
4574 App
::Ack
::Filter-
>register_filter(ext
=> __PACKAGE__
);
4578 package App
::Ack
::Filter
::FirstLineMatch
;
4585 our @ISA = 'App::Ack::Filter';
4589 my ( $class, $re ) = @_;
4591 $re =~ s{^/|/$}{}g; # XXX validate?
4599 # This test reads the first 250 characters of a file, then just uses the
4600 # first line found in that. This prevents reading something like an entire
4601 # .min.js file (which might be only one "line" long) into memory.
4604 my ( $self, $resource ) = @_;
4606 my $re = $self->{'regex'};
4608 my $line = $resource->firstliney;
4610 return $line =~ /$re/;
4616 my $re = $self->{'regex'};
4618 return ref($self) . " - $re";
4624 (my $re = $self->{regex
}) =~ s{\([^:]*:(.*)\)$}{$1};
4626 return "first line matches /$re/";
4630 App
::Ack
::Filter-
>register_filter(firstlinematch
=> __PACKAGE__
);
4634 package App
::Ack
::Filter
::Is
;
4640 our @ISA = 'App::Ack::Filter';
4643 use File
::Spec
3.00 ();
4646 my ( $class, $filename ) = @_;
4649 filename
=> $filename,
4650 groupname
=> 'IsGroup',
4655 return App
::Ack
::Filter
::IsGroup-
>new();
4659 my ( $self, $resource ) = @_;
4661 my $filename = $self->{'filename'};
4662 my $base = (File
::Spec-
>splitpath($resource->name))[2];
4664 return $base eq $filename;
4670 my $filename = $self->{'filename'};
4672 return ref($self) . " - $filename";
4678 my $filename = $self->{'filename'};
4684 App
::Ack
::Filter-
>register_filter(is => __PACKAGE__
);
4688 package App
::Ack
::Filter
::Match
;
4693 our @ISA = 'App::Ack::Filter';
4696 use File
::Spec
3.00;
4700 my ( $class, $re ) = @_;
4702 $re =~ s{^/|/$}{}g; # XXX validate?
4707 groupname
=> 'MatchGroup',
4712 return App
::Ack
::Filter
::MatchGroup-
>new;
4716 my ( $self, $resource ) = @_;
4718 my $re = $self->{'regex'};
4720 return $resource->basename =~ /$re/;
4726 my $re = $self->{'regex'};
4728 print ref($self) . " - $re";
4736 my $re = $self->{'regex'};
4738 return "filename matches $re";
4742 App
::Ack
::Filter-
>register_filter(match
=> __PACKAGE__
);
4746 package App
::Ack
::Filter
::Default
;
4752 our @ISA = 'App::Ack::Filter';
4758 return bless {}, $class;
4762 my ( $self, $resource ) = @_;
4764 return -T
$resource->name;
4768 package App
::Ack
::Filter
::Inverse
;
4775 our @ISA = 'App::Ack::Filter';
4779 my ( $class, $filter ) = @_;
4787 my ( $self, $resource ) = @_;
4789 my $filter = $self->{'filter'};
4790 return !$filter->filter( $resource );
4796 return $self->{'filter'};
4806 my $filter = $self->{'filter'};
4812 package App
::Ack
::Filter
::Collection
;
4818 our @ISA = 'App::Ack::Filter';
4831 my ( $self, $resource ) = @_;
4833 for my $group (values %{$self->{'groups'}}) {
4834 if ($group->filter($resource)) {
4839 for my $filter (@{$self->{'ungrouped'}}) {
4840 if ($filter->filter($resource)) {
4849 my ( $self, $filter ) = @_;
4851 if (exists $filter->{'groupname'}) {
4852 my $group = ($self->{groups
}->{$filter->{groupname
}} ||= $filter->create_group());
4853 $group->add($filter);
4856 push @{$self->{'ungrouped'}}, $filter;
4865 return ref($self) . " - $self";
4871 my $ungrouped = $self->{'ungrouped'};
4873 return join(', ', map { "($_)" } @{$ungrouped});
4877 package App
::Ack
::Filter
::IsGroup
;
4883 our @ISA = 'App::Ack::Filter';
4886 use File
::Spec
3.00 ();
4897 my ( $self, $filter ) = @_;
4899 $self->{data
}->{ $filter->{filename
} } = 1;
4905 my ( $self, $resource ) = @_;
4907 my $data = $self->{'data'};
4908 my $base = $resource->basename;
4910 return exists $data->{$base};
4916 return ref($self) . " - $self";
4922 return join(' ', keys %{$self->{data
}});
4926 package App
::Ack
::Filter
::ExtensionGroup
;
4932 our @ISA = 'App::Ack::Filter';
4944 my ( $self, $filter ) = @_;
4946 foreach my $ext (@{$filter->{extensions
}}) {
4947 $self->{data
}->{lc $ext} = 1;
4954 my ( $self, $resource ) = @_;
4956 if ($resource->name =~ /[.]([^.]*)$/) {
4957 return exists $self->{'data'}->{lc $1};
4966 return ref($self) . " - $self";
4972 return join(' ', map { ".$_" } sort keys %{$self->{data
}});
4976 package App
::Ack
::Filter
::MatchGroup
;
4982 our @ISA = 'App::Ack::Filter';
4995 my ( $self, $filter ) = @_;
4997 push @{ $self->{matches
} }, $filter->{regex
};
4999 my $re = join('|', map { "(?:$_)" } @{ $self->{matches
} });
5000 $self->{big_re
} = qr/$re/;
5006 my ( $self, $resource ) = @_;
5008 my $re = $self->{big_re
};
5010 return $resource->basename =~ /$re/;
5016 # XXX Needs an explicit return.
5022 # XXX Needs an explicit return.
5026 package App
::Ack
::Filter
::IsPath
;
5032 our @ISA = 'App::Ack::Filter';
5037 my ( $class, $filename ) = @_;
5040 filename
=> $filename,
5041 groupname
=> 'IsPathGroup',
5046 return App
::Ack
::Filter
::IsPathGroup-
>new();
5050 my ( $self, $resource ) = @_;
5052 return $resource->name eq $self->{'filename'};
5058 my $filename = $self->{'filename'};
5060 return ref($self) . " - $filename";
5066 my $filename = $self->{'filename'};
5072 package App
::Ack
::Filter
::IsPathGroup
;
5080 our @ISA = 'App::Ack::Filter';
5092 my ( $self, $filter ) = @_;
5094 $self->{data
}->{ $filter->{filename
} } = 1;
5100 my ( $self, $resource ) = @_;
5102 my $data = $self->{'data'};
5104 return exists $data->{$resource->name};
5110 return ref($self) . " - $self";
5116 return join(' ', keys %{$self->{data
}});
5126 our $VERSION = '1.16';
5132 our $name; # name of the current file
5133 our $dir; # dir of the current file
5135 our %files_defaults;
5140 file_filter
=> undef,
5141 descend_filter
=> undef,
5142 error_handler
=> sub { CORE
::die $_[0] },
5143 warning_handler
=> sub { CORE
::warn @_ },
5144 sort_files
=> undef,
5145 follow_symlinks
=> 1,
5148 %skip_dirs = map {($_,1)} (File
::Spec-
>curdir, File
::Spec-
>updir);
5153 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5155 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5158 my $filter = $parms->{file_filter
};
5160 my ($dirname,$file,$fullpath) = splice( @queue, 0, 3 );
5161 if ( -f
$fullpath || -p _
|| $fullpath =~ m{^/dev/fd} ) {
5164 local $File::Next
::dir
= $dirname;
5165 local $File::Next
::name
= $fullpath;
5166 next if not $filter->();
5168 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5171 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
5185 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5187 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5188 my $err = $parms->{error_handler
};
5189 my $warn = $parms->{warning_handler
};
5191 my $filename = $queue[1];
5193 if ( !defined($filename) ) {
5194 $err->( 'Must pass a filename to from_file()' );
5199 if ( $filename eq '-' ) {
5203 if ( !open( $fh, '<', $filename ) ) {
5204 $err->( "Unable to open $filename: $!", $! + 0 );
5210 my $filter = $parms->{file_filter
};
5211 local $/ = $parms->{nul_separated
} ? "\x00" : $/;
5212 while ( my $fullpath = <$fh> ) {
5214 next unless $fullpath =~ /./;
5215 if ( not ( -f
$fullpath || -p _
) ) {
5216 $warn->( "$fullpath: No such file" );
5220 my ($volume,$dirname,$file) = File
::Spec-
>splitpath( $fullpath );
5223 local $File::Next
::dir
= $dirname;
5224 local $File::Next
::name
= $fullpath;
5225 next if not $filter->();
5227 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5235 sub _bad_invocation
{
5236 my $good = (caller(1))[3];
5238 $bad =~ s/(.+)::/$1->/;
5239 return "$good must not be invoked as $bad";
5242 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
5243 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
5248 my @parts = split( /\//, $path );
5250 return $path if @parts < 2;
5252 return File
::Spec-
>catfile( @parts );
5258 my $defaults = shift;
5259 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
5261 my %passed_parms = %{$passed_parms};
5264 for my $key ( keys %{$defaults} ) {
5266 exists $passed_parms{$key}
5267 ? delete $passed_parms{$key}
5268 : $defaults->{$key};
5271 # Any leftover keys are bogus
5272 for my $badkey ( keys %passed_parms ) {
5273 my $sub = (caller(1))[3];
5274 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
5277 # If it's not a code ref, assume standard sort
5278 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
5279 $parms->{sort_files
} = \
&sort_standard
;
5284 my $start = reslash
( $_ );
5286 push @queue, ($start,undef,$start);
5289 push @queue, (undef,$start,$start);
5293 return ($parms,@queue);
5297 sub _candidate_files
{
5299 my $dirname = shift;
5302 if ( !opendir $dh, $dirname ) {
5303 $parms->{error_handler
}->( "$dirname: $!", $! + 0 );
5308 my $descend_filter = $parms->{descend_filter
};
5309 my $follow_symlinks = $parms->{follow_symlinks
};
5310 my $sort_sub = $parms->{sort_files
};
5312 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
5315 my $fullpath = File
::Spec-
>catdir( $dirname, $file );
5316 if ( !$follow_symlinks ) {
5317 next if -l
$fullpath;
5321 # Only do directory checking if we have a descend_filter
5322 if ( $descend_filter ) {
5323 if ( $has_stat ? (-d _
) : (-d
$fullpath) ) {
5324 local $File::Next
::dir
= $fullpath;
5326 next if not $descend_filter->();
5330 push( @newfiles, [ $dirname, $file, $fullpath ] );
5333 push( @newfiles, $dirname, $file, $fullpath );
5339 return map { @{$_} } sort $sort_sub @newfiles;
5346 1; # End of File::Next