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/ack3
8 # and submit patches against the individual files
12 $App::Ack
::STANDALONE
= 1;
18 our $VERSION = 'v3.3.1'; # Check https://beyondgrep.com/ for updates
26 # Global command-line options
46 our $opt_range_invert;
48 our $opt_show_filename;
53 # Flag if we need any context tracking.
54 our $is_tracking_context;
56 # The regex that we search for in each file.
59 # Special /m version of our $search_re.
62 our @special_vars_used_by_opt_output;
66 # Internal stats for debugging.
70 $App::Ack
::ORIGINAL_PROGRAM_NAME
= $0;
71 $0 = join(' ', 'ack', $0);
72 $App::Ack
::ors
= "\n";
73 if ( $App::Ack
::VERSION
ne $main::VERSION
) {
74 App
::Ack
::die( "Program/library version mismatch\n\t$0 is $main::VERSION\n\t$INC{'App/Ack.pm'} is $App::Ack::VERSION" );
77 # Do preliminary arg checking;
78 my $env_is_usable = 1;
79 for my $arg ( @ARGV ) {
80 last if ( $arg eq '--' );
82 # Get the --thpppt, --bar, --cathy and --man checking out of the way.
83 $arg =~ /^--th[pt]+t+$/ and App
::Ack
::thpppt
($arg);
84 $arg eq '--bar' and App
::Ack
::ackbar
();
85 $arg eq '--cathy' and App
::Ack
::cathy
();
87 # See if we want to ignore the environment. (Don't tell Al Gore.)
88 $arg eq '--env' and $env_is_usable = 1;
89 $arg eq '--noenv' and $env_is_usable = 0;
92 if ( $env_is_usable ) {
93 if ( $ENV{ACK_OPTIONS
} ) {
94 App
::Ack
::warn( 'WARNING: ack no longer uses the ACK_OPTIONS environment variable. Use an ackrc file instead.' );
98 my @keys = ( 'ACKRC', grep { /^ACK_/ } keys %ENV );
103 my $modules_loaded_ok = eval 'use Term::ANSIColor 1.10 (); 1;';
104 if ( $modules_loaded_ok && $App::Ack
::is_windows
) {
105 $modules_loaded_ok = eval 'use Win32::Console::ANSI; 1;';
107 if ( $modules_loaded_ok ) {
108 $ENV{ACK_COLOR_MATCH
} ||= 'black on_yellow';
109 $ENV{ACK_COLOR_FILENAME
} ||= 'bold green';
110 $ENV{ACK_COLOR_LINENO
} ||= 'bold yellow';
111 $ENV{ACK_COLOR_COLNO
} ||= 'bold yellow';
114 my $p = App
::Ack
::ConfigLoader
::opt_parser
( 'no_auto_abbrev', 'pass_through' );
116 help
=> sub { App
::Ack
::show_help
(); exit; },
117 version
=> sub { App
::Ack
::print( App
::Ack
::get_version_statement
() ); exit; },
118 man
=> sub { App
::Ack
::show_man
(); },
122 App
::Ack
::show_help
();
126 my @arg_sources = App
::Ack
::ConfigLoader
::retrieve_arg_sources
();
128 my $opt = App
::Ack
::ConfigLoader
::process_args
( @arg_sources );
133 $opt_break = $opt->{break};
135 $opt_color = $opt->{color
};
136 $opt_column = $opt->{column
};
137 $opt_debug = $opt->{debug
};
140 $opt_heading = $opt->{heading
};
144 $opt_output = $opt->{output
};
146 $opt_passthru = $opt->{passthru
};
147 $opt_range_start = $opt->{range_start
};
148 $opt_range_end = $opt->{range_end
};
149 $opt_range_invert = $opt->{range_invert
};
150 $opt_regex = $opt->{regex
};
151 $opt_show_filename = $opt->{show_filename
};
152 $opt_show_types = $opt->{show_types
};
153 $opt_underline = $opt->{underline
};
156 if ( $opt_show_types && not( $opt_f || $opt_g ) ) {
157 App
::Ack
::die( '--show-types can only be used with -f or -g.' );
160 if ( $opt_range_start ) {
161 ($opt_range_start, undef) = build_regex
( $opt_range_start, {} );
163 if ( $opt_range_end ) {
164 ($opt_range_end, undef) = build_regex
( $opt_range_end, {} );
166 $using_ranges = $opt_range_start || $opt_range_end;
168 $App::Ack
::report_bad_filenames
= !$opt->{s
};
169 $App::Ack
::ors
= $opt->{print0
} ? "\0" : "\n";
171 if ( !defined($opt_color) && !$opt_g ) {
172 my $windows_color = 1;
173 if ( $App::Ack
::is_windows
) {
174 $windows_color = eval { require Win32
::Console
::ANSI
; };
176 $opt_color = !App
::Ack
::output_to_pipe
() && $windows_color;
178 $opt_heading //= !App
::Ack
::output_to_pipe
();
179 $opt_break //= !App
::Ack
::output_to_pipe
();
181 if ( defined($opt->{H
}) || defined($opt->{h
}) ) {
182 $opt_show_filename = $opt->{show_filename
} = $opt->{H
} && !$opt->{h
};
185 if ( defined $opt_output ) {
186 # Expand out \t, \n and \r.
187 $opt_output =~ s/\\n/\n/g;
188 $opt_output =~ s/\\r/\r/g;
189 $opt_output =~ s/\\t/\t/g;
191 my @supported_special_variables = ( 1..9, qw( _ . ` & ' + f ) );
192 @special_vars_used_by_opt_output = grep { $opt_output =~ /\$$_/ } @supported_special_variables;
194 # If the $opt_output contains $&, $` or $', those vars won't be
195 # captured until they're used at least once in the program.
196 # Do the eval to make this happen.
197 for my $i ( @special_vars_used_by_opt_output ) {
198 if ( $i eq q{&} || $i eq q{'} || $i eq q{`} ) {
199 no warnings
; # They will be undef, so don't warn.
205 # Set up file filters.
207 if ( $App::Ack
::is_filter_mode
&& !$opt->{files_from
} ) { # probably -x
208 $files = App
::Ack
::Files-
>from_stdin();
209 $opt_regex //= shift @ARGV;
210 ($search_re, $scan_re) = build_regex
( $opt_regex, $opt );
211 $stats{search_re
} = $search_re;
212 $stats{scan_re
} = $scan_re;
216 # No need to check for regex, since mutex options are handled elsewhere.
219 $opt_regex //= shift @ARGV;
220 ($search_re, $scan_re) = build_regex
( $opt_regex, $opt );
221 $stats{search_re
} = $search_re;
222 $stats{scan_re
} = $scan_re;
224 # XXX What is this checking for?
225 if ( $search_re && $search_re =~ /\n/ ) {
226 App
::Ack
::exit_from_ack
( 0 );
229 if ( not defined $opt->{files_from
} ) {
232 if ( !exists($opt->{show_filename
}) ) {
233 unless(@start == 1 && !(-d
$start[0])) {
234 $opt_show_filename = $opt->{show_filename
} = 1;
238 if ( defined $opt->{files_from
} ) {
239 $files = App
::Ack
::Files-
>from_file( $opt, $opt->{files_from
} );
240 exit 1 unless $files;
243 @start = ('.') unless @start;
244 foreach my $target (@start) {
245 if ( !-e
$target && $App::Ack
::report_bad_filenames
) {
246 App
::Ack
::warn( "$target: No such file or directory" );
250 $opt->{file_filter
} = _compile_file_filter
($opt, \
@start);
251 $opt->{descend_filter
} = _compile_descend_filter
($opt);
253 $files = App
::Ack
::Files-
>from_argv( $opt, \
@start );
256 App
::Ack
::set_up_pager
( $opt->{pager
} ) if defined $opt->{pager
};
259 if ( $opt_f || $opt_g ) {
260 $nmatches = file_loop_fg
( $files );
263 $nmatches = file_loop_c
( $files );
265 elsif ( $opt_l || $opt_L ) {
266 $nmatches = file_loop_lL
( $files );
269 $nmatches = file_loop_normal
( $files );
274 my @stats = qw( search_re scan_re prescans linescans filematches linematches );
275 my $width = List
::Util
::max
( map { length } @stats );
277 for my $stat ( @stats ) {
278 App
::Ack
::warn( sprintf( '%-*.*s = %s', $width, $width, $stat, $stats{$stat} // 'undef' ) );
284 App
::Ack
::exit_from_ack
( $nmatches );
293 while ( defined( my $file = $files->next ) ) {
294 if ( $opt_show_types ) {
295 App
::Ack
::show_types
( $file );
298 print_line_with_options
( undef, $file->name, 0, $App::Ack
::ors
);
301 App
::Ack
::say( $file->name );
304 last if defined($opt_m) && ($nmatches >= $opt_m);
315 while ( defined( my $file = $files->next ) ) {
316 my $matches_for_this_file = count_matches_in_file
( $file );
318 if ( not $opt_show_filename ) {
319 $total_count += $matches_for_this_file;
323 if ( !$opt_l || $matches_for_this_file > 0 ) {
324 if ( $opt_show_filename ) {
325 App
::Ack
::say( $file->name, ':', $matches_for_this_file );
328 App
::Ack
::say( $matches_for_this_file );
333 if ( !$opt_show_filename ) {
334 App
::Ack
::say( $total_count );
345 while ( defined( my $file = $files->next ) ) {
346 my $is_match = count_matches_in_file
( $file, 1 );
348 if ( $opt_L ? !$is_match : $is_match ) {
349 App
::Ack
::say( $file->name );
353 last if defined($opt_m) && ($nmatches >= $opt_m);
361 sub _compile_descend_filter
{
365 my $dont_ignore_dirs = 0;
367 for my $filter (@{$opt->{idirs
} || []}) {
368 if ($filter->is_inverted()) {
376 # If we have one or more --noignore-dir directives, we can't ignore
377 # entire subdirectory hierarchies, so we return an "accept all"
378 # filter and scrutinize the files more in _compile_file_filter.
379 return if $dont_ignore_dirs;
380 return unless $idirs;
382 $idirs = $opt->{idirs
};
385 my $file = App
::Ack
::File-
>new($File::Next
::dir
);
386 return !grep { $_->filter($file) } @{$idirs};
390 sub _compile_file_filter
{
391 my ( $opt, $start ) = @_;
393 my $ifiles_filters = $opt->{ifiles
};
395 my $filters = $opt->{'filters'} || [];
396 my $direct_filters = App
::Ack
::Filter
::Collection-
>new();
397 my $inverse_filters = App
::Ack
::Filter
::Collection-
>new();
399 foreach my $filter (@{$filters}) {
400 if ($filter->is_inverted()) {
401 # We want to check if files match the uninverted filters
402 $inverse_filters->add($filter->invert());
405 $direct_filters->add($filter);
409 my %is_member_of_starting_set = map { (get_file_id
($_) => 1) } @{$start};
411 my @ignore_dir_filter = @{$opt->{idirs
} || []};
412 my @is_inverted = map { $_->is_inverted() } @ignore_dir_filter;
413 # This depends on InverseFilter->invert returning the original filter (for optimization).
414 @ignore_dir_filter = map { $_->is_inverted() ? $_->invert() : $_ } @ignore_dir_filter;
415 my $dont_ignore_dir_filter = grep { $_ } @is_inverted;
416 my $previous_dir = '';
417 my $previous_dir_ignore_result;
421 if ( $File::Next
::name
=~ /$search_re/o ) {
428 # ack always selects files that are specified on the command
429 # line, regardless of filetype. If you want to ack a JPEG,
430 # and say "ack foo whatever.jpg" it will do it for you.
431 return 1 if $is_member_of_starting_set{ get_file_id
($File::Next
::name
) };
433 if ( $dont_ignore_dir_filter ) {
434 if ( $previous_dir eq $File::Next
::dir
) {
435 if ( $previous_dir_ignore_result ) {
440 my @dirs = File
::Spec-
>splitdir($File::Next
::dir
);
444 for ( my $i = 0; $i < @dirs; $i++) {
445 my $dir_rsrc = App
::Ack
::File-
>new(File
::Spec-
>catfile(@dirs[0 .. $i]));
448 for my $filter (@ignore_dir_filter) {
449 if ( $filter->filter($dir_rsrc) ) {
450 $is_ignoring = !$is_inverted[$j];
456 $previous_dir = $File::Next
::dir
;
457 $previous_dir_ignore_result = $is_ignoring;
459 if ( $is_ignoring ) {
465 # Ignore named pipes found in directory searching. Named
466 # pipes created by subprocesses get specified on the command
467 # line, so the rule of "always select whatever is on the
468 # command line" wins.
469 return 0 if -p
$File::Next
::name
;
471 # We can't handle unreadable filenames; report them.
473 use filetest
'access';
475 if ( not -R
$File::Next
::name
) {
476 if ( $App::Ack
::report_bad_filenames
) {
477 App
::Ack
::warn( "${File::Next::name}: cannot open file for reading" );
483 my $file = App
::Ack
::File-
>new($File::Next
::name
);
485 if ( $ifiles_filters && $ifiles_filters->filter($file) ) {
489 my $match_found = $direct_filters->filter($file);
491 # Don't bother invoking inverse filters unless we consider the current file a match.
492 if ( $match_found && $inverse_filters->filter( $file ) ) {
500 # Returns a (fairly) unique identifier for a file.
501 # Use this function to compare two files to see if they're
502 # equal (ie. the same file, but with a different path/links/etc).
504 my ( $filename ) = @_;
506 if ( $App::Ack
::is_windows
) {
507 return File
::Next
::reslash
( $filename );
510 # XXX Is this the best method? It always hits the FS.
511 if ( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
512 return join(':', $dev, $inode);
515 # XXX This could be better.
521 # Returns a regex object based on a string and command-line options.
522 # Dies when the regex $str is undefined (i.e. not given on command line).
528 defined $str or App
::Ack
::die( 'No regular expression found.' );
531 # Compile the regex to see if it dies or throws warnings.
532 local $SIG{__WARN__
} = sub { die @_ }; # Anything that warns becomes a die.
533 my $scratch_regex = eval { qr/$str/ };
534 if ( not $scratch_regex ) {
538 if ( $err =~ m{^(.+?); marked by <-- HERE in m/(.+?) <-- HERE} ) {
539 my ($why, $where) = ($1,$2);
540 my $pointy = ' ' x
(6+length($where)) . '^---HERE';
541 App
::Ack
::die( "Invalid regex '$str'\nRegex: $str\n$pointy $why" );
544 App
::Ack
::die( "Invalid regex '$str'\n$err" );
549 # Check for lowercaseness before we do any modifications.
550 my $regex_is_lc = App
::Ack
::is_lowercase
( $str );
552 $str = quotemeta( $str ) if $opt->{Q
};
560 if ( $str =~ /^\\[wd]/ ) {
561 # Explicit \w is good.
564 # Can start with \w, (, [ or dot.
565 if ( $str !~ /^[\w\(\[\.]/ ) {
570 # Can end with \w, }, ), ], +, *, or dot.
571 if ( $str !~ /[\w\}\)\]\+\*\?\.]$/ ) {
574 # ... unless it's escaped.
575 elsif ( $str =~ /\\[\}\)\]\+\*\?\.]$/ ) {
580 App
::Ack
::die( '-w will not do the right thing if your regex does not begin and end with a word character.' );
583 if ( $str =~ /^\w+$/ ) {
584 # No need for fancy regex if it's a simple word.
585 $str = sprintf( '\b(?:%s)\b', $str );
588 $str = sprintf( '(?:^|\b|\s)\K(?:%s)(?=\s|\b|$)', $str );
592 if ( $opt->{i
} || ($opt->{S
} && $regex_is_lc) ) {
593 $_ = "(?i)$_" for ( $str, $scan_str );
596 my $scan_regex = undef;
597 my $regex = eval { qr/$str/ };
599 if ( $scan_str !~ /\$/ ) {
600 # No line_scan is possible if there's a $ in the regex.
601 $scan_regex = eval { qr/$scan_str/m };
607 App
::Ack
::die( "Invalid regex '$str':\n $err" );
610 return ($regex, $scan_regex);
617 # Number of context lines
618 my $n_before_ctx_lines;
619 my $n_after_ctx_lines;
621 # Array to keep track of lines that might be required for a "before" context
622 my @before_context_buf;
623 # Position to insert next line in @before_context_buf
624 my $before_context_pos;
626 # Number of "after" context lines still pending
627 my $after_context_pending;
629 # Number of latest line that got printed
633 state $has_printed_from_any_file = 0;
636 sub file_loop_normal
{
639 $n_before_ctx_lines = $opt_output ? 0 : ($opt_B || 0);
640 $n_after_ctx_lines = $opt_output ? 0 : ($opt_A || 0);
642 @before_context_buf = (undef) x
$n_before_ctx_lines;
643 $before_context_pos = 0;
645 $is_tracking_context = $n_before_ctx_lines || $n_after_ctx_lines;
650 while ( defined( my $file = $files->next ) ) {
651 if ($is_tracking_context) {
653 $after_context_pending = 0;
654 if ( $opt_heading ) {
658 my $needs_line_scan = 1;
659 if ( !$opt_passthru && !$opt_v ) {
661 if ( $file->may_be_present( $scan_re ) ) {
665 $needs_line_scan = 0;
668 if ( $needs_line_scan ) {
670 $nmatches += print_matches_in_file
( $file );
672 last if $opt_1 && $nmatches;
679 sub print_matches_in_file
{
682 my $max_count = $opt_m || -1; # Go negative for no limit so it can never reduce to 0.
684 my $filename = $file->name;
686 my $has_printed_from_this_file = 0;
688 my $fh = $file->open;
690 if ( $App::Ack
::report_bad_filenames
) {
691 App
::Ack
::warn( "$filename: $!" );
696 my $display_filename = $filename;
697 if ( $opt_show_filename && $opt_heading && $opt_color ) {
698 $display_filename = Term
::ANSIColor
::colored
($display_filename, $ENV{ACK_COLOR_FILENAME
});
701 # Check for context before the main loop, so we don't pay for it if we don't need it.
702 if ( $is_tracking_context ) {
705 $after_context_pending = 0;
707 my $in_range = range_setup
();
711 $match_colno = undef;
713 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
718 $does_match = !/$search_re/o;
721 if ( $does_match = /$search_re/o ) {
722 # @- = @LAST_MATCH_START
723 # @+ = @LAST_MATCH_END
724 $match_colno = $-[0] + 1;
729 if ( $does_match && $max_count ) {
730 if ( !$has_printed_from_this_file ) {
731 $stats{filematches
}++;
732 if ( $opt_break && $has_printed_from_any_file ) {
733 App
::Ack
::print_blank_line
();
735 if ( $opt_show_filename && $opt_heading ) {
736 App
::Ack
::say( $display_filename );
739 print_line_with_context
( $filename, $_, $. );
740 $has_printed_from_this_file = 1;
741 $stats{linematches
}++;
746 if ( $after_context_pending ) {
747 # Disable $opt_column since there are no matches in the context lines.
748 local $opt_column = 0;
749 print_line_with_options
( $filename, $_, $., '-' );
750 --$after_context_pending;
752 elsif ( $n_before_ctx_lines ) {
753 # Save line for "before" context.
754 $before_context_buf[$before_context_pos] = $_;
755 $before_context_pos = ($before_context_pos+1) % $n_before_ctx_lines;
759 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
761 last if ($max_count == 0) && ($after_context_pending == 0);
764 elsif ( $opt_passthru ) {
767 my $in_range = range_setup
();
772 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
774 $match_colno = undef;
775 if ( $in_range && ($opt_v xor /$search_re/o) ) {
777 $match_colno = $-[0] + 1;
779 if ( !$has_printed_from_this_file ) {
780 if ( $opt_break && $has_printed_from_any_file ) {
781 App
::Ack
::print_blank_line
();
783 if ( $opt_show_filename && $opt_heading ) {
784 App
::Ack
::say( $display_filename );
787 print_line_with_options
( $filename, $_, $., ':' );
788 $has_printed_from_this_file = 1;
793 if ( $opt_break && !$has_printed_from_this_file && $has_printed_from_any_file ) {
794 App
::Ack
::print_blank_line
();
796 print_line_with_options
( $filename, $_, $., '-', 1 );
797 $has_printed_from_this_file = 1;
800 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
802 last if $max_count == 0;
808 $match_colno = undef;
809 my $in_range = range_setup
();
814 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
817 if ( !/$search_re/o ) {
818 if ( !$has_printed_from_this_file ) {
819 if ( $opt_break && $has_printed_from_any_file ) {
820 App
::Ack
::print_blank_line
();
822 if ( $opt_show_filename && $opt_heading ) {
823 App
::Ack
::say( $display_filename );
826 print_line_with_context
( $filename, $_, $. );
827 $has_printed_from_this_file = 1;
833 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
835 last if $max_count == 0;
838 else { # Normal search: No context, no -v, no --passthru
841 my $last_match_lineno;
842 my $in_range = range_setup
();
847 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
850 $match_colno = undef;
851 if ( /$search_re/o ) {
852 $match_colno = $-[0] + 1;
853 if ( !$has_printed_from_this_file ) {
854 $stats{filematches
}++;
855 if ( $opt_break && $has_printed_from_any_file ) {
856 App
::Ack
::print_blank_line
();
858 if ( $opt_show_filename && $opt_heading ) {
859 App
::Ack
::say( $display_filename );
863 if ( $last_match_lineno ) {
864 if ( $. > $last_match_lineno + $opt_p ) {
865 App
::Ack
::print_blank_line
();
868 elsif ( !$opt_break && $has_printed_from_any_file ) {
869 App
::Ack
::print_blank_line
();
873 print_line_with_options
( $filename, $_, $., ':' );
874 $has_printed_from_this_file = 1;
876 $stats{linematches
}++;
878 $last_match_lineno = $.;
882 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
884 last if $max_count == 0;
892 sub print_line_with_options
{
893 my ( $filename, $line, $lineno, $separator, $skip_coloring ) = @_;
895 $has_printed_from_any_file = 1;
896 $printed_lineno = $lineno;
900 if ( $opt_show_filename && defined($filename) ) {
902 $colno = get_match_colno
() if $opt_column;
904 $filename = Term
::ANSIColor
::colored
( $filename, $ENV{ACK_COLOR_FILENAME
} );
905 $lineno = Term
::ANSIColor
::colored
( $lineno, $ENV{ACK_COLOR_LINENO
} );
906 $colno = Term
::ANSIColor
::colored
( $colno, $ENV{ACK_COLOR_COLNO
} ) if $opt_column;
908 if ( $opt_heading ) {
909 push @line_parts, $lineno;
912 push @line_parts, $filename, $lineno;
914 push @line_parts, $colno if $opt_column;
918 while ( $line =~ /$search_re/og ) {
919 my $output = $opt_output;
920 if ( @special_vars_used_by_opt_output ) {
923 # Stash copies of the special variables because we can't rely
924 # on them not changing in the process of doing the s///.
926 my %keep = map { ($_ => ${$_} // '') } @special_vars_used_by_opt_output;
927 $keep{_
} = $line if exists $keep{_
}; # Manually set it because $_ gets reset in a map.
928 $keep{f
} = $filename if exists $keep{f
};
929 my $special_vars_used_by_opt_output = join( '', @special_vars_used_by_opt_output );
930 $output =~ s/\$([$special_vars_used_by_opt_output])/$keep{$1}/ego;
932 App
::Ack
::say( join( $separator, @line_parts, $output ) );
938 # We have to do underlining before any highlighting because highlighting modifies string length.
939 if ( $opt_underline && !$skip_coloring ) {
940 while ( $line =~ /$search_re/og ) {
941 my $match_start = $-[0] // next;
942 my $match_end = $+[0];
943 my $match_length = $match_end - $match_start;
944 last if $match_length <= 0;
946 my $spaces_needed = $match_start - length $underline;
948 $underline .= (' ' x
$spaces_needed);
949 $underline .= ('^' x
$match_length);
952 if ( $opt_color && !$skip_coloring ) {
953 my $highlighted = 0; # If highlighted, need to escape afterwards.
955 while ( $line =~ /$search_re/og ) {
956 my $match_start = $-[0] // next;
957 my $match_end = $+[0];
958 my $match_length = $match_end - $match_start;
959 last if $match_length <= 0;
961 my $substring = substr( $line, $match_start, $match_length );
962 my $substitution = Term
::ANSIColor
::colored
( $substring, $ENV{ACK_COLOR_MATCH
} );
964 # Fourth argument replaces the string specified by the first three.
965 substr( $line, $match_start, $match_length, $substitution );
967 # Move the offset of where /g left off forward the number of spaces of highlighting.
968 pos($line) = $match_end + (length( $substitution ) - length( $substring ));
971 # Reset formatting and delete everything to the end of the line.
972 $line .= "\e[0m\e[K" if $highlighted;
975 push @line_parts, $line;
976 App
::Ack
::say( join( $separator, @line_parts ) );
978 # Print the underline, if appropriate.
979 if ( $underline ne '' ) {
980 # Figure out how many spaces are used per line for the ANSI coloring.
981 state $chars_used_by_coloring;
982 if ( !defined($chars_used_by_coloring) ) {
983 $chars_used_by_coloring = 0;
985 my $len_fn = sub { length( Term
::ANSIColor
::colored
( 'x', $ENV{$_[0]} ) ) - 1 };
986 $chars_used_by_coloring += $len_fn->('ACK_COLOR_FILENAME') unless $opt_heading;
987 $chars_used_by_coloring += $len_fn->('ACK_COLOR_LINENO');
988 $chars_used_by_coloring += $len_fn->('ACK_COLOR_COLNO') if $opt_column;
992 pop @line_parts; # Leave only the stuff on the left.
994 my $stuff_on_the_left = join( $separator, @line_parts );
995 my $spaces_needed = length($stuff_on_the_left) - $chars_used_by_coloring + 1;
997 App
::Ack
::print( ' ' x
$spaces_needed );
999 App
::Ack
::say( $underline );
1006 sub print_line_with_context
{
1007 my ( $filename, $matching_line, $lineno ) = @_;
1009 $matching_line =~ s/[\r\n]+$//;
1011 # Check if we need to print context lines first.
1012 if ( $opt_A || $opt_B ) {
1013 my $before_unprinted = $lineno - $printed_lineno - 1;
1014 if ( !$is_first_match && ( !$printed_lineno || $before_unprinted > $n_before_ctx_lines ) ) {
1015 App
::Ack
::say( '--' );
1018 # We want at most $n_before_ctx_lines of context.
1019 if ( $before_unprinted > $n_before_ctx_lines ) {
1020 $before_unprinted = $n_before_ctx_lines;
1023 while ( $before_unprinted > 0 ) {
1024 my $line = $before_context_buf[($before_context_pos - $before_unprinted + $n_before_ctx_lines) % $n_before_ctx_lines];
1028 # Disable $opt->{column} since there are no matches in the context lines.
1029 local $opt_column = 0;
1031 print_line_with_options
( $filename, $line, $lineno-$before_unprinted, '-' );
1032 $before_unprinted--;
1036 print_line_with_options
( $filename, $matching_line, $lineno, ':' );
1038 # We want to get the next $n_after_ctx_lines printed.
1039 $after_context_pending = $n_after_ctx_lines;
1041 $is_first_match = 0;
1048 sub get_match_colno
{
1049 return $match_colno;
1052 sub count_matches_in_file
{
1054 my $bail = shift; # True if we're just checking for existence.
1059 if ( !$file->open() ) {
1061 if ( $App::Ack
::report_bad_filenames
) {
1062 App
::Ack
::warn( $file->name . ": $!" );
1067 if ( !$file->may_be_present( $scan_re ) ) {
1076 my $in_range = range_setup
();
1078 my $fh = $file->{fh
};
1079 if ( $using_ranges ) {
1082 $in_range = 1 if ( !$in_range && $opt_range_start && /$opt_range_start/o );
1084 if ( /$search_re/o xor $opt_v ) {
1089 $in_range = 0 if ( $in_range && $opt_range_end && /$opt_range_end/o );
1095 if ( /$search_re/o xor $opt_v ) {
1109 return !$using_ranges || (!$opt_range_start && $opt_range_end);
1119 ack - grep-like text finder
1123 ack [options] PATTERN [FILE...]
1124 ack -f [options] [DIRECTORY...]
1128 ack is designed as an alternative to F<grep> for programmers.
1130 ack searches the named input FILEs or DIRECTORYs for lines containing a
1131 match to the given PATTERN. By default, ack prints the matching lines.
1132 If no FILE or DIRECTORY is given, the current directory will be searched.
1134 PATTERN is a Perl regular expression. Perl regular expressions
1135 are commonly found in other programming languages, but for the particulars
1136 of their behavior, please consult
1137 L<perlreref|https://perldoc.perl.org/perlreref.html>. If you don't know
1138 how to use regular expression but are interested in learning, you may
1139 consult L<perlretut|https://perldoc.perl.org/perlretut.html>. If you do not
1140 need or want ack to use regular expressions, please see the
1141 C<-Q>/C<--literal> option.
1143 Ack can also list files that would be searched, without actually
1144 searching them, to let you take advantage of ack's file-type filtering
1147 =head1 FILE SELECTION
1149 If files are not specified for searching, either on the command
1150 line or piped in with the C<-x> option, I<ack> delves into
1151 subdirectories selecting files for searching.
1153 I<ack> is intelligent about the files it searches. It knows about
1154 certain file types, based on both the extension on the file and,
1155 in some cases, the contents of the file. These selections can be
1156 made with the B<--type> option.
1158 With no file selection, I<ack> searches through regular files that
1159 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
1160 options, either present in F<ackrc> files or on the command line.
1162 The default options for I<ack> ignore certain files and directories. These
1167 =item * Backup files: Files matching F<#*#> or ending with F<~>.
1169 =item * Coredumps: Files matching F<core.\d+>
1171 =item * Version control directories like F<.svn> and F<.git>.
1175 Run I<ack> with the C<--dump> option to see what settings are set.
1177 However, I<ack> always searches the files given on the command line,
1178 no matter what type. If you tell I<ack> to search in a coredump,
1179 it will search in a coredump.
1181 =head1 DIRECTORY SELECTION
1183 I<ack> descends through the directory tree of the starting directories
1184 specified. If no directories are specified, the current working directory is
1185 used. However, it will ignore the shadow directories used by
1186 many version control systems, and the build directories used by the
1187 Perl MakeMaker system. You may add or remove a directory from this
1188 list with the B<--[no]ignore-dir> option. The option may be repeated
1189 to add/remove multiple directories from the ignore list.
1191 For a complete list of directories that do not get searched, run
1194 =head1 MATCHING IN A RANGE OF LINES
1196 The C<--range-start> and C<--range-end> options let you specify ranges of
1197 lines to search within each file.
1199 Say you had the following file, called F<testfile>:
1201 # This function calls print on "foo".
1211 Calling C<ack print> will give us five matches:
1213 $ ack print testfile
1214 # This function calls print on "foo".
1220 What if we only want to search for C<print> within the subroutines? We can
1221 specify ranges of lines that we want ack to search. The range starts with
1222 any line that matches the pattern C<^sub \w+>, and stops with any line that
1225 $ ack --range-start='^sub \w+' --range-end='^}' print testfile
1229 Note that ack searched two ranges of lines. The listing below shows which
1230 lines were in a range and which were out of the range.
1232 Out # This function calls print on "foo".
1240 Out my $task = 'print';
1242 You don't have to specify both C<--range-start> and C<--range-end>. IF
1243 C<--range-start> is omitted, then the range runs from the first line in the
1244 file unitl the first line that matches C<--range-end>. Similarly, if
1245 C<--range-end> is omitted, the range runs from the first line matching
1246 C<--range-start> to the end of the file.
1248 For example, if you wanted to search all HTML files up until the first
1249 instance of the C<< <body> >>, you could do
1251 ack foo --range-end='<body>'
1253 Or to search after Perl's `__DATA__` or `__END__` markers, you would do
1255 ack pattern --range-end='^__(END|DATA)__'
1257 It's possible for a range to start and stop on the same line. For example
1259 --range-start='<title>' --range-end='</title>'
1261 would match this line as both the start and end of the range, making a
1264 <title>Page title</title>
1266 Note that the patterns in C<--range-start> and C<--range-end> are not
1267 affected by options like C<-i>, C<-w> and C<-Q> that modify the behavior of
1268 the main pattern being matched.
1270 Again, ranges only affect where matches are looked for. Everything else in
1271 ack works the same way. Using C<-c> option with a range will give a count
1272 of all the matches that appear within those ranges. The C<-l> shows those
1273 files that have a match within a range, and the C<-L> option shows files
1274 that do not have a match within a range.
1276 The C<-v> option for negating a match works inside the range, too.
1277 To see lines that don't match "google" within the "<head>" section of
1278 your HTML files, you could do:
1280 ack google -v --html --range-start='<head' --range-end='</head>'
1282 Specifying a range to search does not affect how matches are displayed.
1283 The context for a match will still be the same, and
1285 Using the context options work the same way, and will show context
1286 lines for matches even if the context lines fall outside the range.
1287 Similarly, C<--passthru> will show all lines in the file, but only show
1288 matches for lines within the range.
1296 Specifies an ackrc file to load after all others; see L</"ACKRC LOCATION SEMANTICS">.
1298 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
1300 Print I<NUM> lines of trailing context after matching lines.
1302 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
1304 Print I<NUM> lines of leading context before matching lines.
1306 =item B<--[no]break>
1308 Print a break between results from different files. On by default
1309 when used interactively.
1311 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
1313 Print I<NUM> lines (default 2) of context around matching lines.
1314 You can specify zero lines of context to override another context
1315 specified in an ackrc.
1317 =item B<-c>, B<--count>
1319 Suppress normal output; instead print a count of matching lines for
1320 each input file. If B<-l> is in effect, it will only show the
1321 number of lines for each file that has lines matching. Without
1322 B<-l>, some line counts may be zeroes.
1324 If combined with B<-h> (B<--no-filename>) ack outputs only one total
1327 =item B<--[no]color>, B<--[no]colour>
1329 B<--color> highlights the matching text. B<--nocolor> suppresses
1330 the color. This is on by default unless the output is redirected.
1332 On Windows, this option is off by default unless the
1333 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
1334 environment variable is used.
1336 =item B<--color-filename=I<color>>
1338 Sets the color to be used for filenames.
1340 =item B<--color-match=I<color>>
1342 Sets the color to be used for matches.
1344 =item B<--color-colno=I<color>>
1346 Sets the color to be used for column numbers.
1348 =item B<--color-lineno=I<color>>
1350 Sets the color to be used for line numbers.
1352 =item B<--[no]column>
1354 Show the column number of the first match. This is helpful for
1355 editors that can place your cursor at a given position.
1357 =item B<--create-ackrc>
1359 Dumps the default ack options to standard output. This is useful for
1360 when you want to customize the defaults.
1364 Writes the list of options loaded and where they came from to standard
1365 output. Handy for debugging.
1369 B<--noenv> disables all environment processing. No F<.ackrc> is
1370 read and all environment variables are ignored. By default, F<ack>
1371 considers F<.ackrc> and settings in the environment.
1375 B<--flush> flushes output immediately. This is off by default
1376 unless ack is running interactively (when output goes to a pipe or
1381 Only print the files that would be searched, without actually doing
1382 any searching. PATTERN must not be specified, or it will be taken
1383 as a path to search.
1385 =item B<--files-from=I<FILE>>
1387 The list of files to be searched is specified in I<FILE>. The list of
1388 files are separated by newlines. If I<FILE> is C<->, the list is loaded
1389 from standard input.
1391 Note that the list of files is B<not> filtered in any way. If you
1392 add C<--type=html> in addition to C<--files-from>, the C<--type> will
1396 =item B<--[no]filter>
1398 Forces ack to act as if it were receiving input via a pipe.
1400 =item B<--[no]follow>
1402 Follow or don't follow symlinks, other than whatever starting files
1403 or directories were specified on the command line.
1405 This is off by default.
1407 =item B<-g I<PATTERN>>
1409 Print searchable files where the relative path + filename matches
1416 is exactly the same as
1420 This means that just as ack will not search, for example, F<.jpg>
1421 files, C<-g> will not list F<.jpg> files either. ack is not intended
1422 to be a general-purpose file finder.
1424 Note also that if you have C<-i> in your .ackrc that the filenames
1425 to be matched will be case-insensitive as well.
1427 This option can be combined with B<--color> to make it easier to
1430 =item B<--[no]group>
1432 B<--group> groups matches by file name. This is the default
1433 when used interactively.
1435 B<--nogroup> prints one result per line, like grep. This is the
1436 default when output is redirected.
1438 =item B<-H>, B<--with-filename>
1440 Print the filename for each match. This is the default unless searching
1441 a single explicitly specified file.
1443 =item B<-h>, B<--no-filename>
1445 Suppress the prefixing of filenames on output when multiple files are
1448 =item B<--[no]heading>
1450 Print a filename heading above each file's results. This is the default
1451 when used interactively.
1455 Print a short help statement.
1457 =item B<--help-types>
1459 Print all known types.
1461 =item B<--help-colors>
1463 Print a chart of various color combinations.
1465 =item B<--help-rgb-colors>
1467 Like B<--help-colors> but with more precise RGB colors.
1469 =item B<-i>, B<--ignore-case>
1471 Ignore case distinctions in PATTERN. Overrides B<--smart-case> and B<-I>.
1473 =item B<-I>, B<--no-ignore-case>
1475 Turns on case distinctions in PATTERN. Overrides B<--smart-case> and B<-i>.
1477 =item B<--ignore-ack-defaults>
1479 Tells ack to completely ignore the default definitions provided with ack.
1480 This is useful in combination with B<--create-ackrc> if you I<really> want
1483 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
1485 Ignore directory (as CVS, .svn, etc are ignored). May be used
1486 multiple times to ignore multiple directories. For example, mason
1487 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
1488 option allows users to search directories which would normally be
1489 ignored (perhaps to research the contents of F<.svn/props> directories).
1491 The I<DIRNAME> must always be a simple directory name. Nested
1492 directories like F<foo/bar> are NOT supported. You would need to
1493 specify B<--ignore-dir=foo> and then no files from any foo directory
1494 are taken into account by ack unless given explicitly on the command
1497 =item B<--ignore-file=I<FILTER:ARGS>>
1499 Ignore files matching I<FILTER:ARGS>. The filters are specified
1500 identically to file type filters as seen in L</"Defining your own types">.
1502 =item B<-k>, B<--known-types>
1504 Limit selected files to those with types that ack knows about.
1506 =item B<-l>, B<--files-with-matches>
1508 Only print the filenames of matching files, instead of the matching text.
1510 =item B<-L>, B<--files-without-matches>
1512 Only print the filenames of files that do I<NOT> match.
1514 =item B<--match I<PATTERN>>
1516 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
1517 regex as your first argument, e.g. when executing multiple searches over the
1520 # search for foo and bar in given files
1521 ack file1 t/file* --match foo
1522 ack file1 t/file* --match bar
1524 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
1526 Print only I<NUM> matches out of each file. If you want to stop ack
1527 after printing the first match of any kind, use the B<-1> options.
1531 Print this manual page.
1533 =item B<-n>, B<--no-recurse>
1535 No descending into subdirectories.
1539 Show only the part of each line matching PATTERN (turns off text
1540 highlighting). This is exactly the same as C<--output=$&>.
1542 =item B<--output=I<expr>>
1544 Output the evaluation of I<expr> for each line (turns off text
1545 highlighting). If PATTERN matches more than once then a line is
1546 output for each non-overlapping match.
1548 I<expr> may contain the strings "\n", "\r" and "\t", which will be
1549 expanded to their corresponding characters line feed, carriage return
1550 and tab, respectively.
1552 I<expr> may also contain the following Perl special variables:
1556 =item C<$1> through C<$9>
1558 The subpattern from the corresponding set of capturing parentheses.
1559 If your pattern is C<(.+) and (.+)>, and the string is "this and
1560 that', then C<$1> is "this" and C<$2> is "that".
1564 The contents of the line in the file.
1568 The number of the line in the file.
1570 =item C<$&>, C<$`> and C<$'>
1572 C<$&> is the the string matched by the pattern, C<$`> is what
1573 precedes the match, and C<$'> is what follows it. If the pattern
1574 is C<gra(ph|nd)> and the string is "lexicographic", then C<$&> is
1575 "graph", C<$`> is "lexico" and C<$'> is "ic".
1577 Use of these variables in your output will slow down the pattern
1582 The match made by the last parentheses that matched in the pattern.
1583 For example, if your pattern is C<Version: (.+)|Revision: (.+)>,
1584 then C<$+> will contain whichever set of parentheses matched.
1588 C<$f> is available, in C<--output> only, to insert the filename.
1589 This is a stand-in for the discovered C<$filename> usage in old C<< ack2 --output >>,
1590 which is disallowed with C<ack3> improved security.
1592 The intended usage is to provide the grep or compile-error syntax needed for editor/IDE go-to-line integration,
1593 e.g. C<--output=$f:$.:$_> or C<--output=$f\t$.\t$&>
1597 =item B<--pager=I<program>>, B<--nopager>
1599 B<--pager> directs ack's output through I<program>. This can also be specified
1600 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
1602 Using --pager does not suppress grouping and coloring like piping
1603 output on the command-line does.
1605 B<--nopager> cancels any setting in F<~/.ackrc>, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
1606 No output will be sent through a pager.
1610 Prints all lines, whether or not they match the expression. Highlighting
1611 will still work, though, so it can be used to highlight matches while
1612 still seeing the entire file, as in:
1614 # Watch a log file, and highlight a certain IP address.
1615 $ tail -f ~/access.log | ack --passthru 123.45.67.89
1619 Only works in conjunction with B<-f>, B<-g>, B<-l> or B<-c>, options
1620 that only list filenames. The filenames are output separated with a
1621 null byte instead of the usual newline. This is helpful when dealing
1622 with filenames that contain whitespace, e.g.
1624 # Remove all files of type HTML.
1625 ack -f --html --print0 | xargs -0 rm -f
1627 =item B<-p[N]>, B<--proximate[=N]>
1629 Groups together match lines that are within N lines of each other.
1630 This is useful for visually picking out matches that appear close
1633 For example, if you got these results without the C<--proximate> option,
1640 they would look like this with C<--proximate=1>
1649 and this with C<--proximate=3>.
1657 If N is omitted, N is set to 1.
1661 Negates the effect of the B<--proximate> option. Shortcut for B<--proximate=0>.
1663 =item B<-Q>, B<--literal>
1665 Quote all metacharacters in PATTERN, it is treated as a literal.
1667 =item B<-r>, B<-R>, B<--recurse>
1669 Recurse into sub-directories. This is the default and just here for
1670 compatibility with grep. You can also use it for turning B<--no-recurse> off.
1672 =item B<--range-start=PATTERN>, B<--range-end=PATTERN>
1674 Specifies patterns that mark the start and end of a range. See
1675 L<MATCHING IN A RANGE OF LINES> for details.
1679 Suppress error messages about nonexistent or unreadable files. This is taken
1682 =item B<-S>, B<--[no]smart-case>, B<--no-smart-case>
1684 Ignore case in the search strings if PATTERN contains no uppercase
1685 characters. This is similar to C<smartcase> in the vim text editor.
1686 The options overrides B<-i> and B<-I>.
1688 B<-S> is a synonym for B<--smart-case>.
1690 B<-i> always overrides this option.
1692 =item B<--sort-files>
1694 Sorts the found files lexicographically. Use this if you want your file
1695 listings to be deterministic between runs of I<ack>.
1697 =item B<--show-types>
1699 Outputs the filetypes that ack associates with each file.
1701 Works with B<-f> and B<-g> options.
1703 =item B<-t TYPE>, B<--type=TYPE>, B<--TYPE>
1705 Specify the types of files to include in the search.
1706 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
1707 also be specified as B<--perl>, although this is deprecated.
1709 Type inclusions can be repeated and are ORed together.
1711 See I<ack --help-types> for a list of valid types.
1713 =item B<-T TYPE>, B<--type=noTYPE>, B<--noTYPE>
1715 Specifies the type of files to exclude from the search. B<--type=noperl>
1716 can be done as B<--noperl>, although this is deprecated.
1718 If a file is of both type "foo" and "bar", specifying both B<--type=foo>
1719 and B<--type=nobar> will exclude the file, because an exclusion takes
1720 precedence over an inclusion.
1722 =item B<--type-add I<TYPE>:I<FILTER>:I<ARGS>>
1724 Files with the given ARGS applied to the given FILTER
1725 are recognized as being of (the existing) type TYPE.
1726 See also L</"Defining your own types">.
1728 =item B<--type-set I<TYPE>:I<FILTER>:I<ARGS>>
1730 Files with the given ARGS applied to the given FILTER are recognized as
1731 being of type TYPE. This replaces an existing definition for type TYPE. See
1732 also L</"Defining your own types">.
1734 =item B<--type-del I<TYPE>>
1736 The filters associated with TYPE are removed from Ack, and are no longer considered
1739 =item B<--[no]underline>
1741 Turns on underlining of matches, where "underlining" is printing a line of
1742 carets under the match.
1746 17: Come kick the football you fool
1748 623: Price per square foot
1751 This is useful if you're dumping the results of an ack run into a text
1752 file or printer that doesn't support ANSI color codes.
1754 The setting of underline does not affect highlighting of matches.
1756 =item B<-v>, B<--invert-match>
1758 Invert match: select non-matching lines.
1762 Display version and copyright information.
1764 =item B<-w>, B<--word-regexp>
1766 Force PATTERN to match only whole words.
1770 An abbreviation for B<--files-from=->. The list of files to search are read
1771 from standard input, with one line per file.
1773 Note that the list of files is B<not> filtered in any way. If you add
1774 C<--type=html> in addition to C<-x>, the C<--type> will be ignored.
1778 Stops after reporting first match of any kind. This is different
1779 from B<--max-count=1> or B<-m1>, where only one match per file is
1780 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
1785 Display the all-important Bill The Cat logo. Note that the exact
1786 spelling of B<--thpppppt> is not important. It's checked against
1787 a regular expression.
1791 Check with the admiral for traps.
1795 Chocolate, Chocolate, Chocolate!
1799 =head1 THE .ackrc FILE
1801 The F<.ackrc> file contains command-line options that are prepended
1802 to the command line before processing. Multiple options may live
1803 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
1804 might look like this:
1806 # Always sort the files
1809 # Always color, even if piping to another program
1812 # Use "less -r" as my pager
1815 Note that arguments with spaces in them do not need to be quoted,
1816 as they are not interpreted by the shell. Basically, each I<line>
1817 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
1819 F<ack> looks in several locations for F<.ackrc> files; the searching
1820 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
1821 files are not considered if B<--noenv> is specified on the command line.
1823 =head1 Defining your own types
1825 ack allows you to define your own types in addition to the predefined
1826 types. This is done with command line options that are best put into
1827 an F<.ackrc> file - then you do not have to define your types over and
1828 over again. In the following examples the options will always be shown
1829 on one command line so that they can be easily copy & pasted.
1831 File types can be specified both with the the I<--type=xxx> option,
1832 or the file type as an option itself. For example, if you create
1833 a filetype of "cobol", you can specify I<--type=cobol> or simply
1834 I<--cobol>. File types must be at least two characters long. This
1835 is why the C language is I<--cc> and the R language is I<--rr>.
1837 I<ack --perl foo> searches for foo in all perl files. I<ack --help-types>
1838 tells you, that perl files are files ending
1839 in .pl, .pm, .pod or .t. So what if you would like to include .xs
1840 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
1841 does this for you. B<--type-add> appends
1842 additional extensions to an existing type.
1844 If you want to define a new type, or completely redefine an existing
1845 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
1846 the type I<eiffel> to include files with
1847 the extensions .e or .eiffel. So to search for all eiffel files
1848 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
1849 As usual, you can also write B<--type=eiffel>
1850 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
1851 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
1852 and I<.xs> files no longer belong to the type I<cc>.
1854 When defining your own types in the F<.ackrc> file you have to use
1857 --type-set=eiffel:ext:e,eiffel
1859 or writing on separate lines
1864 The following does B<NOT> work in the F<.ackrc> file:
1866 --type-set eiffel:ext:e,eiffel
1868 In order to see all currently defined types, use I<--help-types>, e.g.
1869 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
1871 In addition to filtering based on extension, ack offers additional
1872 filter types. The generic syntax is
1873 I<--type-set TYPE:FILTER:ARGS>; I<ARGS> depends on the value
1878 =item is:I<FILENAME>
1880 I<is> filters match the target filename exactly. It takes exactly one
1881 argument, which is the name of the file to match.
1885 --type-set make:is:Makefile
1887 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
1889 I<ext> filters match the extension of the target file against a list
1890 of extensions. No leading dot is needed for the extensions.
1894 --type-set perl:ext:pl,pm,t
1896 =item match:I<PATTERN>
1898 I<match> filters match the target filename against a regular expression.
1899 The regular expression is made case-insensitive for the search.
1903 --type-set make:match:/(gnu)?makefile/
1905 =item firstlinematch:I<PATTERN>
1907 I<firstlinematch> matches the first line of the target file against a
1908 regular expression. Like I<match>, the regular expression is made
1913 --type-add perl:firstlinematch:/perl/
1919 ack allows customization of the colors it uses when presenting matches
1920 onscreen. It uses the colors available in Perl's L<Term::ANSIColor>
1921 module, which provides the following listed values. Note that case does not
1922 matter when using these values.
1924 There are four different colors ack uses:
1926 Aspect Option Env. variable Default
1927 -------- ----------------- ------------------ ---------------
1928 filename --color-filename ACK_COLOR_FILENAME black on_yellow
1929 match --color-match ACK_COLOR_MATCH bold green
1930 line no. --color-lineno ACK COLOR_LINENO bold yellow
1931 column no. --color-colno ACK COLOR_COLNO bold yellow
1933 The column number column is only used if the column number is shown because
1934 of the --column option.
1936 Colors may be specified by command-line option, such as
1937 C<ack --color-filename='red on_white'>, or by setting an environment
1938 variable, such as C<ACK_COLOR_FILENAME='red on_white'>. Options for colors
1939 can be set in your ACKRC file (See "THE .ackrc FILE").
1941 ack can understand the following colors for the foreground:
1943 black red green yellow blue magenta cyan white
1945 The optional background color is specified by prepending "on_" to one of
1946 the foreground colors:
1948 on_black on_red on_green on_yellow on_blue on_magenta on_cyan on_white
1950 Each of the foreground colors can be modified with the following
1951 attributes, which may or may not be supported by your terminal:
1953 bold faint italic underline blink reverse concealed
1955 Any combinations of modifiers can be added to the foreground color. If your
1956 terminal supports it, and you enjoy visual punishment, you can specify:
1958 ack --color-filename="blink italic underline bold red on_yellow"
1960 For charts of the colors and what they look like, run C<ack --help-colors>
1961 and C<ack --help-rgb-colors>.
1963 If the eight standard colors, in their bold, faint and unmodified states,
1964 aren't enough for you to choose from, you can also specify colors by their
1965 RGB values. They are specified as "rgbXYZ" where X, Y, and Z are values
1966 between 0 and 5 giving the intensity of red, green and blue, respectively.
1967 Therefore, "rgb500" is pure red, "rgb505" is purple, and so on.
1969 Background colors can be specified with the "on_" prefix prepended on an
1970 RGB color, so that "on_rgb505" would be a purple background.
1972 The modifier attributes of blink, italic, underscore and so on may or may
1973 not work on the RGB colors.
1975 For a chart of the 216 possible RGB colors, run C<ack --help-rgb-colors>.
1977 =head1 ENVIRONMENT VARIABLES
1979 For commonly-used ack options, environment variables can make life
1980 much easier. These variables are ignored if B<--noenv> is specified
1981 on the command line.
1987 Specifies the location of the user's F<.ackrc> file. If this file doesn't
1988 exist, F<ack> looks in the default location.
1990 =item ACK_COLOR_COLNO
1992 Color specification for the column number in ack's output. By default, the
1993 column number is not shown. You have to enable it with the B<--column>
1994 option. See the section "ack Colors" above.
1996 =item ACK_COLOR_FILENAME
1998 Color specification for the filename in ack's output. See the section "ack
2001 =item ACK_COLOR_LINENO
2003 Color specification for the line number in ack's output. See the section
2006 =item ACK_COLOR_MATCH
2008 Color specification for the matched text in ack's output. See the section
2013 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
2014 ack will send its output.
2016 Using C<ACK_PAGER> does not suppress grouping and coloring like
2017 piping output on the command-line does, except that on Windows
2018 ack will assume that C<ACK_PAGER> does not support color.
2020 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
2022 =item ACK_PAGER_COLOR
2024 Specifies a pager program that understands ANSI color sequences.
2025 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
2026 like piping output on the command-line does.
2028 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
2032 =head1 ACK & OTHER TOOLS
2034 =head2 Simple vim integration
2036 F<ack> integrates easily with the Vim text editor. Set this in your
2037 F<.vimrc> to use F<ack> instead of F<grep>:
2041 That example uses C<-k> to search through only files of the types ack
2042 knows about, but you may use other default flags. Now you can search
2043 with F<ack> and easily step through the results in Vim:
2045 :grep Dumper perllib
2047 =head2 Editor integration
2049 Many users have integrated ack into their preferred text editors.
2050 For details and links, see L<https://beyondgrep.com/more-tools/>.
2052 =head2 Shell and Return Code
2054 For greater compatibility with I<grep>, I<ack> in normal use returns
2055 shell return or exit code of 0 only if something is found and 1 if
2058 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
2060 The I<grep> code 2 for errors is not used.
2062 If C<-f> or C<-g> are specified, then 0 is returned if at least one
2063 file is found. If no files are found, then 1 is returned.
2067 =head1 DEBUGGING ACK PROBLEMS
2069 If ack gives you output you're not expecting, start with a few simple steps.
2071 =head2 Try it with B<--noenv>
2073 Your environment variables and F<.ackrc> may be doing things you're
2074 not expecting, or forgotten you specified. Use B<--noenv> to ignore
2075 your environment and F<.ackrc>.
2077 =head2 Use B<-f> to see what files have been selected for searching
2079 Ack's B<-f> was originally added as a debugging tool. If ack is
2080 not finding matches you think it should find, run F<ack -f> to see
2081 what files have been selected. You can also add the C<--show-types>
2082 options to show the type of each file selected.
2084 =head2 Use B<--dump>
2086 This lists the ackrc files that are loaded and the options loaded
2087 from them. You may be loading an F<.ackrc> file that you didn't know
2090 =head1 ACKRC LOCATION SEMANTICS
2092 Ack can load its configuration from many sources. The following list
2093 specifies the sources Ack looks for configuration files; each one
2094 that is found is loaded in the order specified here, and
2095 each one overrides options set in any of the sources preceding
2096 it. (For example, if I set --sort-files in my user ackrc, and
2097 --nosort-files on the command line, the command line takes
2104 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
2105 using C<--ignore-ack-defaults>.
2107 =item * Global ackrc
2109 Options are then loaded from the global ackrc. This is located at
2110 C</etc/ackrc> on Unix-like systems.
2112 Under Windows XP and earlier, the global ackrc is at
2113 C<C:\Documents and Settings\All Users\Application Data\ackrc>
2115 Under Windows Vista/7, the global ackrc is at
2116 C<C:\ProgramData\ackrc>
2118 The C<--noenv> option prevents all ackrc files from being loaded.
2122 Options are then loaded from the user's ackrc. This is located at
2123 C<$HOME/.ackrc> on Unix-like systems.
2125 Under Windows XP and earlier, the user's ackrc is at
2126 C<C:\Documents and Settings\$USER\Application Data\ackrc>.
2128 Under Windows Vista/7, the user's ackrc is at
2129 C<C:\Users\$USER\AppData\Roaming\ackrc>.
2131 If you want to load a different user-level ackrc, it may be specified
2132 with the C<$ACKRC> environment variable.
2134 The C<--noenv> option prevents all ackrc files from being loaded.
2136 =item * Project ackrc
2138 Options are then loaded from the project ackrc. The project ackrc is
2139 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
2140 in the current directory, then the parent directory, then the grandparent
2141 directory, etc. This can be omitted using C<--noenv>.
2145 The C<--ackrc> option may be included on the command line to specify an
2146 ackrc file that can override all others. It is consulted even if C<--noenv>
2149 =item * Command line
2151 Options are then loaded from the command line.
2155 =head1 BUGS & ENHANCEMENTS
2157 ack is based at GitHub at L<https://github.com/beyondgrep/ack3>
2159 Please report any bugs or feature requests to the issues list at
2160 Github: L<https://github.com/beyondgrep/ack3/issues>.
2162 Please include the operating system that you're using; the output of
2163 the command C<ack --version>; and any customizations in your F<.ackrc>
2166 To suggest enhancements, please submit an issue at
2167 L<https://github.com/beyondgrep/ack3/issues>. Also read the
2168 F<DEVELOPERS.md> file in the ack code repository.
2170 Also, feel free to discuss your issues on the ack mailing
2171 list at L<https://groups.google.com/group/ack-users>.
2175 Support for and information about F<ack> can be found at:
2179 =item * The ack homepage
2181 L<https://beyondgrep.com/>
2183 =item * Source repository
2185 L<https://github.com/beyondgrep/ack3>
2187 =item * The ack issues list at Github
2189 L<https://github.com/beyondgrep/ack3/issues>
2191 =item * The ack announcements mailing list
2193 L<https://groups.google.com/group/ack-announcement>
2195 =item * The ack users' mailing list
2197 L<https://groups.google.com/group/ack-users>
2199 =item * The ack development mailing list
2201 L<https://groups.google.com/group/ack-users>
2207 There are ack mailing lists and a Slack channel for ack. See
2208 L<https://beyondgrep.com/community/> for details.
2212 This is the Frequently Asked Questions list for ack.
2214 =head2 Can I stop using grep now?
2216 Many people find I<ack> to be better than I<grep> as an everyday tool
2217 99% of the time, but don't throw I<grep> away, because there are times
2218 you'll still need it. For example, you might be looking through huge
2219 log files and not using regular expressions. In that case, I<grep>
2220 will probably perform better.
2222 =head2 Why isn't ack finding a match in (some file)?
2224 First, take a look and see if ack is even looking at the file. ack is
2225 intelligent in what files it will search and which ones it won't, but
2226 sometimes that can be surprising.
2228 Use the C<-f> switch, with no regex, to see a list of files that ack
2229 will search for you. If your file doesn't show up in the list of files
2230 that C<ack -f> shows, then ack never looks in it.
2232 =head2 Wouldn't it be great if F<ack> did search & replace?
2234 No, ack will always be read-only. Perl has a perfectly good way
2235 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
2238 You can certainly use ack to select your files to update. For
2239 example, to change all "foo" to "bar" in all PHP files, you can do
2240 this from the Unix shell:
2242 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
2244 =head2 Can I make ack recognize F<.xyz> files?
2246 Yes! Please see L</"Defining your own types"> in the ack manual.
2248 =head2 Will you make ack recognize F<.xyz> files by default?
2250 We might, depending on how widely-used the file format is.
2252 Submit an issue at in the GitHub issue queue at
2253 L<https://github.com/beyondgrep/ack3/issues>. Explain what the file format
2254 is, where we can find out more about it, and what you have been using
2255 in your F<.ackrc> to support it.
2257 Please do not bother creating a pull request. The code for filetypes
2258 is trivial compared to the rest of the process we go through.
2260 =head2 Why is it called ack if it's called ack-grep?
2262 The name of the program is "ack". Some packagers have called it
2263 "ack-grep" when creating packages because there's already a package
2264 out there called "ack" that has nothing to do with this ack.
2266 I suggest you make a symlink named F<ack> that points to F<ack-grep>
2267 because one of the crucial benefits of ack is having a name that's
2268 so short and simple to type.
2270 To do that, run this with F<sudo> or as root:
2272 ln -s /usr/bin/ack-grep /usr/bin/ack
2274 Alternatively, you could use a shell alias:
2282 =head2 What does F<ack> mean?
2284 Nothing. I wanted a name that was easy to type and that you could
2285 pronounce as a single syllable.
2287 =head2 Can I do multi-line regexes?
2289 No, ack does not support regexes that match multiple lines. Doing
2290 so would require reading in the entire file at a time.
2292 If you want to see lines near your match, use the C<--A>, C<--B>
2293 and C<--C> switches for displaying context.
2295 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
2297 ack treats command line options beginning with C<+> or C<-> as options; if you
2298 would like to search for these, you may prefix your search term with C<--> or
2299 use the C<--match> option. (However, don't forget that C<+> is a regular
2300 expression metacharacter!)
2302 =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex?
2304 The Perl language limits the repetition quantifier to 32K. You
2305 can search for C<.{32767}> but not C<.{32768}>.
2307 =head2 Ack does "X" and shouldn't, should it?
2309 We try to remain as close to grep's behavior as possible, so when in
2310 doubt, see what grep does! If there's a mismatch in functionality there,
2311 please submit an issue to GitHub, and/or bring it up on the ack-users
2316 =head1 ACKNOWLEDGEMENTS
2318 How appropriate to have I<ack>nowledgements!
2320 Thanks to everyone who has contributed to ack in any way, including
2337 SE<eacute>bastien FeugE<egrave>re,
2344 RaE<uacute>l GundE<iacute>n,
2350 RaE<aacute>l GundE<aacute>n,
2386 Eric Van Dewoestine,
2395 Christopher J. Madsen,
2407 GE<aacute>bor SzabE<oacute>,
2410 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
2414 Mark Leighton Fisher,
2420 Nilson Santos F. Jr,
2425 Ask BjE<oslash>rn Hansen,
2429 Slaven ReziE<0x107>,
2441 Andy Lester, C<< <andy at petdance.com> >>
2443 =head1 COPYRIGHT & LICENSE
2445 Copyright 2005-2020 Andy Lester.
2447 This program is free software; you can redistribute it and/or modify
2448 it under the terms of the Artistic License v2.0.
2450 See https://www.perlfoundation.org/artistic-license-20.html or the LICENSE.md
2451 file that comes with the ack distribution.
2465 $VERSION = 'v3.3.1'; # Check https://beyondgrep.com/ for updates
2466 $COPYRIGHT = 'Copyright 2005-2020 Andy Lester.';
2468 our $STANDALONE = 0;
2469 our $ORIGINAL_PROGRAM_NAME;
2483 our $is_filter_mode;
2484 our $output_to_pipe;
2488 our $debug_nopens = 0;
2490 # Line ending, changes to "\0" if --print0.
2494 # These have to be checked before any filehandle diddling.
2495 $output_to_pipe = not -t
*STDOUT
;
2496 $is_filter_mode = -p STDIN
;
2498 $is_windows = ($^O eq 'MSWin32');
2503 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2508 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2512 require File
::Basename
;
2513 return File
::Basename
::basename
( $0 );
2518 my $y = q{_ /|,\\'!.x',=(www)=, U };
2519 $y =~ tr/,x!w/\nOo_/;
2521 App
::Ack
::print( "$y ack $_[0]!\n" );
2529 3~!I#7#I"7#I!?!+!="+"="+!:!
2530 2?#I!7!I!?#I!7!I"+"=%+"=#
2531 1?"+!?*+!=#~"=!+#?"="+!
2532 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2533 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2535 ,,!?%I"?(+$=$~!=#:"~$:!~!
2536 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2537 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2538 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2539 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2540 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2541 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2542 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2543 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2544 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2545 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2546 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2547 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2548 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2549 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2550 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2551 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2552 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2553 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2554 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2555 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2556 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2557 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2558 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2559 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2560 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2561 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2562 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2563 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2564 7+:!,!~#,"=!7'I!?#I"7/+!7+
2565 77I!+!7!?!7!I"71+!7,
2568 return _pic_decode
($x);
2574 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2575 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2576 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2582 4.! $\! /M!~!.!8! +.!M# 4
2583 0,!.! (\! .~!M!N! ,+!I!.!M!.! 3
2584 /?!O!.!M!:! '\! .O!.! +~!Z!=!N!.! 4
2585 ..! !D!Z!.!Z!.! '\! 9=!M".! 6
2586 /.! !.!~!M".! '\! 8~! 9
2588 4.! &:!M! !N"M# !M"N!M! #D!M&=! =
2589 :M!7!M#:! !~!M!7!,!$!M!:! #.! !O!N!.!M!:!M# ;
2590 8Z!M"~!N!$!D!.!N!?! !I!N!.! (?!M! !M!,!D!M".! 9
2591 (?!Z!M!N!:! )=!M!O!8!.!M!+!M! !M!,! !O!M! +,!M!.!M!~!Z!N!M!:! &:!~! 0
2592 &8!7!.!~!M"D!M!,! &M!?!=!8! !M!,!O! !M!+! !+!O!.!M! $M#~! !.!8!M!Z!.!M! !O!M"Z! %:!~!M!Z!M!Z!.! +
2593 &:!M!7!,! *M!.!Z!M! !8"M!.!M!~! !.!M!.!=! #~!8!.!M! !7!M! "N!Z#I! !D!M!,!M!.! $."M!,! !M!.! *
2594 2$!O! "N! !.!M!I! !7" "M! "+!O! !~!M! !d!O!.!7!I!M!.! !.!O!=!M!.! !M",!M!.! %.!$!O!D! +
2595 1~!O! "M!+! !8!$! "M! "?!O! %Z!8!D!M!?!8!I!O!7!M! #M!.!M! "M",!M! 4
2596 07!~! ".!8! !.!M! "I!+! !.!M! &Z!D!.!7!=!M! !:!.!M! #:!8"+! !.!+!8! !8! 3
2597 /~!M! #N! !~!M!$! !.!M! !.!M" &~!M! "~!M!O! "D! $M! !8! "M!,!M!+!D!.! 1
2598 #.! #?!M!N!.! #~!O! $M!.!7!$! "?" !?!~!M! '7!8!?!M!.!+!M"O! $?"$!D! !.!O! !$!7!I!.! 0
2599 $,!M!:!O!?! ".! !?!=! $=!:!O! !M! "M! !M! !+!$! (.! +.!M! !M!.! !8! !+"Z!~! $:!M!$! !.! '
2600 #.!8!.!I!$! $7!I! %M" !=!M! !~!M!D! "7!I! .I!O! %?!=!,!D! !,!M! !D!~!8!~! %D!M! (
2601 #.!M"?! $=!O! %=!N! "8!.! !Z!M! #M!~! (M!:! #.!M" &O! !M!.! !?!,! !8!.!N!~! $8!N!M!,!.! %
2602 *$!O! &M!,! "O! !.!M!.! #M! (~!M( &O!.! !7! "M! !.!M!.!M!,! #.!M! !M! &
2603 )=!8!.! $.!M!O!.! "$!.!I!N! !I!M# (7!M(I! %D"Z!M! "=!I! "M! !M!:! #~!D! '
2604 )D! &8!N!:! ".!O! !M!="M! "M! (7!M) %." !M!D!."M!.! !$!=! !M!,! +
2605 (M! &+!.!M! #Z!7!O!M!.!~!8! +,!M#D!?!M#D! #.!Z!M#,!Z!?! !~!N! "N!.! !M! +
2606 'D!:! %$!D! !?! #M!Z! !8!.! !M"?!7!?!7! '+!I!D! !?!O!:!M!:! ":!M!:! !M!7".!M! "8!+! !:!D! !.!M! *
2607 %.!O!:! $.!O!+! !D!.! #M! "M!.!+!N!I!Z! "7!M!N!M!N!?!I!7!Z!=!M'D"~! #M!.!8!$! !:! !.!M! "N!?! !,!O! )
2608 !.!?!M!:!M!I! %8!,! "M!.! #M! "N! !M!.! !M!.! !+!~! !.!M!.! ':!M! $M! $M!Z!$! !M!.! "D! "M! "?!M! (
2609 !7!8! !+!I! ".! "$!=! ":!$! "+! !M!.! !O! !M!I!M".! !=!~! ",!O! '=!M! $$!,! #N!:! ":!8!.! !D!~! !,!M!.! !:!M!.! &
2610 !:!,!.! &Z" #D! !.!8!."M!.! !8!?!Z!M!.!M! #Z!~! !?!M!Z!.! %~!O!.!8!$!N!8!O!I!:!~! !+! #M!.! !.!M!.! !+!M! ".!~!M!+! $
2611 !.! 'D!I! #?!M!.!M!,! !.!Z! !.!8! #M&O!I!?! (~!I!M"." !M!Z!.! !M!N!.! "+!$!.! "M!.! !M!?!.! "8!M! $
2612 (O!8! $M! !M!.! ".!:! !+!=! #M! #.!M! !+" *$!M":!.! !M!~! "M!7! #M! #7!Z! "M"$!M!.! !.! #
2613 '$!Z! #.!7!+!M! $.!,! !+!:! #N! #.!M!.!+!M! +D!M! #=!N! ":!O! #=!M! #Z!D! $M!I! %
2614 $,! ".! $.!M" %$!.! !?!~! "+!7!." !.!M!,! !M! *,!N!M!.$M!?! "D!,! #M!.! #N! +
2615 ,M!Z! &M! "I!,! "M! %I!M! !?!=!.! (Z!8!M! $:!M!.! !,!M! $D! #.!M!.! )
2616 +8!O! &.!8! "I!,! !~!M! &N!M! !M!D! '?!N!O!." $?!7! "?!~! #M!.! #I!D!.! (
2617 3M!,! "N!.! !D" &.!+!M!.! !M":!.":!M!7!M!D! 'M!.! "M!.! "M!,! $I! )
2618 3I! #M! "M!,! !:! &.!M" ".!,! !.!$!M!I! #.! !:! !.!M!?! "N!+! ".! /
2619 1M!,! #.!M!8!M!=!.! +~!N"O!Z"~! *+!M!.! "M! 2
2620 0.!M! &M!.! 8:! %.!M!Z! "M!=! *O!,! %
2621 0?!$! &N! )." .,! %."M! ":!M!.! 0
2622 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0
2624 return _pic_decode
($x);
2628 my($compressed) = @_;
2629 $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2630 App
::Ack
::print( $compressed );
2636 App
::Ack
::print( <<"END_OF_HELP" );
2637 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2639 Search for PATTERN in each source file in the tree from the current
2640 directory on down. If any files or directories are specified, then
2641 only those files and directories are checked. ack may also search
2642 STDIN, but only if no file or directory arguments are specified,
2643 or if one of them is "-".
2645 Default switches may be specified in an .ackrc file. If you want no dependency
2646 on the environment, turn it off with --noenv.
2648 File select actions:
2649 -f Only print the files selected, without
2650 searching. The PATTERN must not be specified.
2651 -g Same as -f, but only select files matching
2654 File listing actions:
2655 -l, --files-with-matches Print filenames with at least one match
2656 -L, --files-without-matches Print filenames with no matches
2657 -c, --count Print filenames and count of matching lines
2660 -i, --ignore-case Ignore case distinctions in PATTERN
2661 -S, --[no]smart-case Ignore case distinctions in PATTERN,
2662 only if PATTERN contains no upper case.
2663 Ignored if -i or -I are specified.
2664 -I, --no-ignore-case Turns on case-sensitivity in PATTERN.
2665 Negates -i and --smart-case.
2666 -v, --invert-match Invert match: select non-matching lines
2667 -w, --word-regexp Force PATTERN to match only whole words
2668 -Q, --literal Quote all metacharacters; PATTERN is literal
2669 --range-start PATTERN Specify PATTERN as the start of a match range.
2670 --range-end PATTERN Specify PATTERN as the end of a match range.
2671 --match PATTERN Specify PATTERN explicitly. Typically omitted.
2674 --output=expr Output the evaluation of expr for each line
2675 (turns off text highlighting)
2676 -o Show only the part of a line matching PATTERN
2677 Same as --output='\$&'
2678 --passthru Print all lines, whether matching or not
2679 -m, --max-count=NUM Stop searching in each file after NUM matches
2680 -1 Stop searching after one match of any kind
2681 -H, --with-filename Print the filename for each match (default:
2682 on unless explicitly searching a single file)
2683 -h, --no-filename Suppress the prefixing filename on output
2684 --[no]column Show the column number of the first match
2686 -A NUM, --after-context=NUM Print NUM lines of trailing context after
2688 -B NUM, --before-context=NUM Print NUM lines of leading context before
2690 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2692 --print0 Print null byte as separator between filenames,
2693 only works with -f, -g, -l, -L or -c.
2695 -s Suppress error messages about nonexistent or
2700 --pager=COMMAND Pipes all ack output through COMMAND. For
2701 example, --pager="less -R". Ignored if output
2703 --nopager Do not send output through a pager. Cancels
2704 any setting in ~/.ackrc, ACK_PAGER or
2706 --[no]heading Print a filename heading above each file's
2707 results. (default: on when used interactively)
2708 --[no]break Print a break between results from different
2709 files. (default: on when used interactively)
2710 --group Same as --heading --break
2711 --nogroup Same as --noheading --nobreak
2712 -p, --proximate=LINES Separate match output with blank lines unless
2713 they are within LINES lines from each other.
2714 -P, --proximate=0 Negates --proximate.
2715 --[no]underline Print a line of carets under the matched text.
2716 --[no]color, --[no]colour Highlight the matching text (default: on unless
2717 output is redirected, or on Windows)
2718 --color-filename=COLOR
2721 --color-lineno=COLOR Set the color for filenames, matches, line and
2723 --help-colors Show a list of possible color combinations.
2724 --help-rgb-colors Show a list of advanced RGB colors.
2725 --flush Flush output immediately, even when ack is used
2726 non-interactively (when output goes to a pipe or
2731 --sort-files Sort the found files lexically.
2732 --show-types Show which types each file has.
2733 --files-from=FILE Read the list of files to search from FILE.
2734 -x Read the list of files to search from STDIN.
2736 File inclusion/exclusion:
2737 --[no]ignore-dir=name Add/remove directory from list of ignored dirs
2738 --[no]ignore-directory=name Synonym for ignore-dir
2739 --ignore-file=FILTER:ARGS Add filter for ignoring files.
2740 -r, -R, --recurse Recurse into subdirectories (default: on)
2741 -n, --no-recurse No descending into subdirectories
2742 --[no]follow Follow symlinks. Default is off.
2744 File type inclusion/exclusion:
2745 -t X, --type=X Include only X files, where X is a filetype,
2746 e.g. python, html, markdown, etc
2747 -T X, --type=noX Exclude X files, where X is a filetype.
2748 -k, --known-types Include only files of types that ack recognizes.
2749 --help-types Display all known types, and how they're defined.
2751 File type specification:
2752 --type-set=TYPE:FILTER:ARGS Files with the given ARGS applied to the given
2753 FILTER are recognized as being of type TYPE.
2754 This replaces an existing definition for TYPE.
2755 --type-add=TYPE:FILTER:ARGS Files with the given ARGS applied to the given
2756 FILTER are recognized as being type TYPE.
2757 --type-del=TYPE Removes all filters associated with TYPE.
2760 --version Display version & copyright
2761 --[no]env Ignore environment variables and global ackrc
2762 files. --env is legal but redundant.
2763 --ackrc=filename Specify an ackrc file to use
2764 --ignore-ack-defaults Ignore default definitions included with ack.
2765 --create-ackrc Outputs a default ackrc for your customization
2767 --dump Dump information on which options are loaded
2768 and where they're defined.
2769 --[no]filter Force ack to treat standard input as a pipe
2770 (--filter) or tty (--nofilter)
2772 --man Print the manual.
2773 --help-types Display all known types, and how they're defined.
2774 --help-colors Show a list of possible color combinations.
2775 --help-rgb-colors Show a list of advanced RGB colors.
2776 --thpppt Bill the Cat
2777 --bar The warning admiral
2778 --cathy Chocolate! Chocolate! Chocolate!
2780 Filter specifications:
2781 If FILTER is "ext", ARGS is a list of extensions checked against the
2783 If FILTER is "is", ARGS must match the file's name exactly.
2784 If FILTER is "match", ARGS is matched as a case-insensitive regex
2785 against the filename.
2786 If FILTER is "firstlinematch", ARGS is matched as a regex the first
2787 line of the file's contents.
2789 Exit status is 0 if match, 1 if no match.
2791 ack's home page is at https://beyondgrep.com/
2793 The full ack manual is available by running "ack --man".
2795 This is version $App::Ack::VERSION of ack. Run "ack --version" for full version info.
2803 sub show_help_types
{
2804 App
::Ack
::print( <<'END_OF_HELP' );
2805 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2807 The following is the list of filetypes supported by ack. You can specify a
2808 filetype to include with -t TYPE or --type=TYPE. You can exclude a
2809 filetype with -T TYPE or --type=noTYPE.
2811 Note that some files may appear in multiple types. For example, a file
2812 called Rakefile is both Ruby (--type=ruby) and Rakefile (--type=rakefile).
2816 my @types = keys %App::Ack
::mappings
;
2819 $maxlen = length if $maxlen < length;
2821 for my $type ( sort @types ) {
2822 next if $type =~ /^-/; # Stuff to not show
2823 my $ext_list = $mappings{$type};
2825 if ( ref $ext_list ) {
2826 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
2828 App
::Ack
::print( sprintf( " %-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2836 sub show_help_colors
{
2837 App
::Ack
::print( <<'END_OF_HELP' );
2838 ack allows customization of the colors it uses when presenting matches
2839 onscreen. See the "ACK COLORS" section of the ack manual (ack --man).
2841 Here is a chart of how various color combinations appear: Each of the eight
2842 foreground colors, on each of the eight background colors or no background
2843 color, with and without the bold modifier.
2845 Run ack --help-rgb-colors for a chart of the RGB colors.
2857 App
::Ack
::print( <<'END_OF_HELP' );
2858 ack allows customization of the colors it uses when presenting matches
2859 onscreen. See the "ACK COLORS" section of the ack manual (ack --man).
2861 Colors may be specified as "rggNNN" where "NNN" is a triplet of digits
2862 from 0 to 5 specifying the intensity of red, green and blue, respectively.
2864 Here is a grid of the 216 possible values for NNN.
2870 App
::Ack
::say( 'Here are the 216 possible colors with the "reverse" modifier applied.', "\n" );
2872 _show_rgb_grid
( 'reverse' );
2878 sub _show_color_grid
{
2881 my @fg_colors = qw( black red green yellow blue magenta cyan white );
2882 my @bg_colors = map { "on_$_" } @fg_colors;
2886 map { _color_cell
( $_ ) } @fg_colors
2891 map { _color_cell
( '-' x
$cell_width ) } @fg_colors
2894 for my $bg ( '', @bg_colors ) {
2897 ( map { _color_cell
( $_, "$_ $bg" ) } @fg_colors ),
2902 _color_cell
( 'bold' ),
2903 ( map { _color_cell
( $_, "bold $_ $bg" ) } @fg_colors ),
2918 $text = sprintf( '%-*s', $cell_width, $text );
2920 return ($color ? Term
::ANSIColor
::colored
( $text, $color ) : $text) . ' ';
2924 sub _show_rgb_grid
{
2925 my $modifier = shift // '';
2927 my $grid = <<'HERE';
2928 544 544 544 544 544 554 554 554 554 554 454 454 454 454 454 455 455 455 455 455 445 445 445 445 445 545 545 545 545 545
2929 533 533 533 543 543 553 553 553 453 453 353 353 353 354 354 355 355 355 345 345 335 335 335 435 435 535 535 535 534 534
2930 511 521 531 531 541 551 451 451 351 251 151 152 152 153 154 155 145 145 135 125 115 215 215 315 415 515 514 514 513 512
2931 500 510 520 530 540 550 450 350 250 150 050 051 052 053 054 055 045 035 025 015 005 105 205 305 405 505 504 503 502 501
2932 400 410 410 420 430 440 340 340 240 140 040 041 041 042 043 044 034 034 024 014 004 104 104 204 304 404 403 403 402 401
2933 300 300 310 320 320 330 330 230 130 130 030 030 031 032 032 033 033 023 013 013 003 003 103 203 203 303 303 302 301 301
2934 200 200 200 210 210 220 220 220 120 120 020 020 020 021 021 022 022 022 012 012 002 002 002 102 102 202 202 202 201 201
2935 100 100 100 100 100 110 110 110 110 110 010 010 010 010 010 011 011 011 011 011 001 001 001 001 001 101 101 101 101 101
2937 522 522 532 542 542 552 552 452 352 352 252 252 253 254 254 255 255 245 235 235 225 225 325 425 425 525 525 524 523 523
2939 411 411 421 431 431 441 441 341 241 241 141 141 142 143 143 144 144 134 124 124 114 114 214 314 314 414 414 413 412 412
2941 422 422 432 432 432 442 442 442 342 342 242 242 242 243 243 244 244 244 234 234 224 224 224 324 324 424 424 424 423 423
2943 311 311 311 321 321 331 331 331 231 231 131 131 131 132 132 133 133 133 123 123 113 113 113 213 213 313 313 313 312 312
2945 433 433 433 433 433 443 443 443 443 443 343 343 343 343 343 344 344 344 344 344 334 334 334 334 334 434 434 434 434 434
2946 211 211 211 211 211 221 221 221 221 221 121 121 121 121 121 122 122 122 122 122 112 112 112 112 112 212 212 212 212 212
2948 322 322 322 322 322 332 332 332 332 332 232 232 232 232 232 233 233 233 233 233 223 223 223 223 223 323 323 323 323 323
2950 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555 555
2951 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444 444
2952 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333 333
2953 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222 222
2954 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111
2955 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
2958 $grid =~ s/(\d\d\d)/Term::ANSIColor::colored( "$1", "$modifier rgb$1" )/eg;
2960 App
::Ack
::say( $grid );
2968 Pod
::Usage
::pod2usage
({
2969 -input
=> $App::Ack
::ORIGINAL_PROGRAM_NAME
,
2979 sub get_version_statement
{
2982 my $copyright = $App::Ack
::COPYRIGHT
;
2983 my $this_perl = $Config::Config
{perlpath
};
2985 my $ext = $Config::Config
{_exe
};
2986 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2988 my $perl_ver = sprintf( 'v%vd', $^V );
2990 my $build_type = $App::Ack
::STANDALONE
? 'standalone version' : 'standard build';
2992 return <<"END_OF_VERSION";
2993 ack $App::Ack::VERSION ($build_type)
2994 Running under Perl $perl_ver at $this_perl
2998 This program is free software. You may modify or distribute it
2999 under the terms of the Artistic License v2.0.
3004 sub print { print {$fh} @_; return; }
3005 sub say { print {$fh} @_, $ors; return; }
3006 sub print_blank_line
{ print {$fh} "\n"; return; }
3009 my $command = shift;
3011 return if App
::Ack
::output_to_pipe
();
3014 if ( not open( $pager, '|-', $command ) ) {
3015 App
::Ack
::die( qq{Unable to pipe to pager "$command": $!} );
3023 sub output_to_pipe
{
3024 return $output_to_pipe;
3029 my $nmatches = shift;
3031 my $rc = $nmatches ? 0 : 1;
3039 my @types = filetypes
( $file );
3040 my $arrow = @types ? ' => ' : ' =>';
3041 App
::Ack
::say( $file->name, $arrow, join( ',', @types ) );
3052 foreach my $k (keys %App::Ack
::mappings
) {
3053 my $filters = $App::Ack
::mappings
{$k};
3055 foreach my $filter (@{$filters}) {
3057 my $clone = $file->clone;
3058 if ( $filter->filter($clone) ) {
3065 # https://metacpan.org/pod/distribution/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm
3066 @matches = sort @matches;
3074 # The simplest case.
3075 return 1 if lc($pat) eq $pat;
3077 # If we have capitals, then go clean up any metacharacters that might have capitals.
3079 # Get rid of any literal backslashes first to avoid confusion.
3082 my $metacharacter = qr
/
3083 |\\A
# Beginning of string
3084 |\\B
# Not word boundary
3085 |\\c
[a-zA-Z
] # Control characters
3086 |\\D
# Non-digit character
3087 |\\G
# End-of-match position of prior match
3088 |\\H
# Not horizontal whitespace
3089 |\\K
# Keep to the left
3090 |\\N
(\
{.+?\
})? # Anything but \n, OR Unicode sequence
3091 |\\[pP
]\
{.+?\
} # Named property and negation
3092 |\\[pP
][A-Z
] # Named property and negation, single-character shorthand
3094 |\\S
# Non-space character
3095 |\\V
# Not vertical whitespace
3096 |\\W
# Non-word character
3098 |\\x
[0-9A-Fa-f
]{2} # Hex sequence
3099 |\\Z
# End of string
3101 $pat =~ s/$metacharacter//g;
3103 my $name = qr/[_A-Za-z][_A-Za-z0-9]*?/;
3104 # Eliminate named captures.
3105 $pat =~ s/\(\?'$name'//g;
3106 $pat =~ s/\(\?<$name>//g;
3108 # Eliminate named backreferences.
3109 $pat =~ s/\\k'$name'//g;
3110 $pat =~ s/\\k<$name>//g;
3111 $pat =~ s/\\k\{$name\}//g;
3113 # Now with those metacharacters and named things removed, now see if it's lowercase.
3114 return 1 if lc($pat) eq $pat;
3120 1; # End of App::Ack
3121 package App
::Ack
::ConfigDefault
;
3130 return split( /\n/, _options_block
() );
3135 return grep { /./ && !/^#/ } options
();
3139 sub _options_block
{
3140 my $lines = <<'HERE';
3141 # This is the default ackrc for ack version ==VERSION==.
3143 # There are four different ways to match
3145 # is: Match the filename exactly
3147 # ext: Match the extension of the filename exactly
3149 # match: Match the filename against a Perl regular expression
3151 # firstlinematch: Match the first 250 characters of the first line
3152 # of text against a Perl regular expression. This is only for
3153 # the --type-add option.
3156 ### Directories to ignore
3159 # https://bazaar.canonical.com/
3160 --ignore-directory=is:.bzr
3163 # http://freshmeat.sourceforge.net/projects/codeville
3164 --ignore-directory=is:.cdv
3166 # Interface Builder (Xcode)
3167 # https://en.wikipedia.org/wiki/Interface_Builder
3168 --ignore-directory=is:~.dep
3169 --ignore-directory=is:~.dot
3170 --ignore-directory=is:~.nib
3171 --ignore-directory=is:~.plst
3174 # https://git-scm.com/
3175 --ignore-directory=is:.git
3176 # When submodules are used, .git is a file.
3177 --ignore-file=is:.git
3180 # https://www.mercurial-scm.org/
3181 --ignore-directory=is:.hg
3184 # https://directory.fsf.org/wiki/Quilt
3185 --ignore-directory=is:.pc
3188 # https://subversion.apache.org/
3189 --ignore-directory=is:.svn
3192 # https://www.monotone.ca/
3193 --ignore-directory=is:_MTN
3196 # https://savannah.nongnu.org/projects/cvs
3197 --ignore-directory=is:CVS
3200 # https://www.gnu.org/software/rcs/
3201 --ignore-directory=is:RCS
3204 # https://en.wikipedia.org/wiki/Source_Code_Control_System
3205 --ignore-directory=is:SCCS
3209 --ignore-directory=is:_darcs
3212 --ignore-directory=is:_sgbak
3215 # https://www.gnu.org/software/autoconf/
3216 --ignore-directory=is:autom4te.cache
3218 # Perl module building
3219 --ignore-directory=is:blib
3220 --ignore-directory=is:_build
3222 # Perl Devel::Cover module's output directory
3223 # https://metacpan.org/release/Devel-Cover
3224 --ignore-directory=is:cover_db
3226 # Node modules created by npm
3227 --ignore-directory=is:node_modules
3230 # https://www.cmake.org/
3231 --ignore-directory=is:CMakeFiles
3233 # Eclipse workspace folder
3234 # https://eclipse.org/
3235 --ignore-directory=is:.metadata
3237 # Cabal (Haskell) sandboxes
3238 # https://www.haskell.org/cabal/users-guide/installing-packages.html
3239 --ignore-directory=is:.cabal-sandbox
3242 # https://docs.python.org/3/tutorial/modules.html
3243 --ignore-directory=is:__pycache__
3244 --ignore-directory=is:.pytest_cache
3246 # macOS Finder remnants
3247 --ignore-directory=is:__MACOSX
3248 --ignore-file=is:.DS_Store
3253 --ignore-file=ext:bak
3254 --ignore-file=match:/~$/
3257 --ignore-file=match:/^#.+#$/
3259 # vi/vim swap files https://www.vim.org/
3260 --ignore-file=match:/[._].*[.]swp$/
3263 --ignore-file=match:/core[.]\d+$/
3265 # minified Javascript
3266 --ignore-file=match:/[.-]min[.]js$/
3267 --ignore-file=match:/[.]js[.]min$/
3270 --ignore-file=match:/[.]min[.]css$/
3271 --ignore-file=match:/[.]css[.]min$/
3273 # JS and CSS source maps
3274 --ignore-file=match:/[.]js[.]map$/
3275 --ignore-file=match:/[.]css[.]map$/
3277 # PDFs, because they pass Perl's -T detection
3278 --ignore-file=ext:pdf
3280 # Common graphics, just as an optimization
3281 --ignore-file=ext:gif,jpg,jpeg,png
3283 # Common archives, as an optimization
3284 --ignore-file=ext:gz,tar,tgz,zip
3286 # Python compiles modules
3287 --ignore-file=ext:pyc,pyd,pyo
3290 --ignore-file=ext:so
3292 # Compiled gettext files
3293 --ignore-file=ext:mo
3295 ### Filetypes defined
3298 # https://www.gnu.org/s/make/
3299 --type-add=make:ext:mk
3300 --type-add=make:ext:mak
3301 --type-add=make:is:makefile
3302 --type-add=make:is:Makefile
3303 --type-add=make:is:Makefile.Debug
3304 --type-add=make:is:Makefile.Release
3305 --type-add=make:is:GNUmakefile
3308 # https://rake.rubyforge.org/
3309 --type-add=rake:is:Rakefile
3312 # https://cmake.org/
3313 --type-add=cmake:is:CMakeLists.txt
3314 --type-add=cmake:ext:cmake
3317 --type-add=actionscript:ext:as,mxml
3320 # https://www.adaic.org/
3321 --type-add=ada:ext:ada,adb,ads
3324 # https://docs.microsoft.com/en-us/previous-versions/office/developer/server-technologies/aa286483(v=msdn.10)
3325 --type-add=asp:ext:asp
3328 # https://dotnet.microsoft.com/apps/aspnet
3329 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
3332 --type-add=asm:ext:asm,s
3335 --type-add=batch:ext:bat,cmd
3338 # https://en.wikipedia.org/wiki/ColdFusion
3339 --type-add=cfmx:ext:cfc,cfm,cfml
3342 # https://clojure.org/
3343 --type-add=clojure:ext:clj,cljs,edn,cljc
3346 # .xs are Perl C files
3347 --type-add=cc:ext:c,h,xs
3353 # https://coffeescript.org/
3354 --type-add=coffeescript:ext:coffee
3357 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
3360 --type-add=hpp:ext:hpp,hh,h,hxx
3363 --type-add=csharp:ext:cs
3366 # https://www.w3.org/Style/CSS/
3367 --type-add=css:ext:css
3371 --type-add=dart:ext:dart
3374 # https://en.wikipedia.org/wiki/Embarcadero_Delphi
3375 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
3378 # https://elixir-lang.org/
3379 --type-add=elixir:ext:ex,exs
3382 # https://www.gnu.org/software/emacs
3383 --type-add=elisp:ext:el
3386 # https://www.erlang.org/
3387 --type-add=erlang:ext:erl,hrl
3390 # https://en.wikipedia.org/wiki/Fortran
3391 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
3394 # https://golang.org/
3395 --type-add=go:ext:go
3398 # https://www.groovy-lang.org/
3399 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
3402 # https://gsp.grails.org/
3403 --type-add=gsp:ext:gsp
3406 # https://www.haskell.org/
3407 --type-add=haskell:ext:hs,lhs
3410 --type-add=html:ext:htm,html,xhtml
3413 # http://jade-lang.com/
3414 --type-add=jade:ext:jade
3417 # https://www.oracle.com/technetwork/java/index.html
3418 --type-add=java:ext:java,properties
3421 --type-add=js:ext:js
3424 # https://www.oracle.com/technetwork/java/javaee/jsp/index.html
3425 --type-add=jsp:ext:jsp,jspx,jspf,jhtm,jhtml
3429 --type-add=json:ext:json
3432 # https://kotlinlang.org/
3433 --type-add=kotlin:ext:kt,kts
3436 # http://www.lesscss.org/
3437 --type-add=less:ext:less
3440 # https://common-lisp.net/
3441 --type-add=lisp:ext:lisp,lsp
3444 # https://www.lua.org/
3445 --type-add=lua:ext:lua
3446 --type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
3449 # https://en.wikipedia.org/wiki/Markdown
3450 --type-add=markdown:ext:md,markdown
3451 # We understand that there are many ad hoc extensions for markdown
3452 # that people use. .md and .markdown are the two that ack recognizes.
3453 # You are free to add your own in your ackrc file.
3456 # https://en.wikipedia.org/wiki/MATLAB
3457 --type-add=matlab:ext:m
3460 --type-add=objc:ext:m,h
3463 --type-add=objcpp:ext:mm,h
3466 # https://ocaml.org/
3467 --type-add=ocaml:ext:ml,mli,mll,mly
3471 --type-add=perl:ext:pl,pm,pod,t,psgi
3472 --type-add=perl:firstlinematch:/^#!.*\bperl/
3475 --type-add=perltest:ext:t
3477 # Perl's Plain Old Documentation format, POD
3478 --type-add=pod:ext:pod
3481 # https://www.php.net/
3482 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
3483 --type-add=php:firstlinematch:/^#!.*\bphp/
3486 # https://plone.org/
3487 --type-add=plone:ext:pt,cpt,metadata,cpy,py
3490 # https://www.python.org/
3491 --type-add=python:ext:py
3492 --type-add=python:firstlinematch:/^#!.*\bpython/
3495 # https://www.r-project.org/
3499 # https://docutils.sourceforge.io/rst.html
3500 --type-add=rst:ext:rst
3503 # https://www.ruby-lang.org/
3504 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
3505 --type-add=ruby:is:Rakefile
3506 --type-add=ruby:firstlinematch:/^#!.*\bruby/
3509 # https://www.rust-lang.org/
3510 --type-add=rust:ext:rs
3513 # https://sass-lang.com
3514 --type-add=sass:ext:sass,scss
3517 # https://www.scala-lang.org/
3518 --type-add=scala:ext:scala
3521 # https://groups.csail.mit.edu/mac/projects/scheme/
3522 --type-add=scheme:ext:scm,ss
3525 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
3526 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
3529 # http://www.smalltalk.org/
3530 --type-add=smalltalk:ext:st
3533 # https://www.smarty.net/
3534 --type-add=smarty:ext:tpl
3537 # https://www.iso.org/standard/45498.html
3538 --type-add=sql:ext:sql,ctl
3541 # http://stylus-lang.com/
3542 --type-add=stylus:ext:styl
3545 # https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
3546 --type-add=svg:ext:svg
3549 # https://developer.apple.com/swift/
3550 --type-add=swift:ext:swift
3551 --type-add=swift:firstlinematch:/^#!.*\bswift/
3554 # https://www.tcl.tk/
3555 --type-add=tcl:ext:tcl,itcl,itk
3558 # https://www.latex-project.org/
3559 --type-add=tex:ext:tex,cls,sty
3561 # Template Toolkit (Perl)
3562 # http//template-toolkit.org/
3563 --type-add=ttml:ext:tt,tt2,ttml
3566 # https://www.typescriptlang.org/
3567 --type-add=ts:ext:ts,tsx
3570 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
3573 --type-add=verilog:ext:v,vh,sv
3576 # http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
3577 --type-add=vhdl:ext:vhd,vhdl
3580 # https://www.vim.org/
3581 --type-add=vim:ext:vim
3584 # https://www.w3.org/TR/REC-xml/
3585 --type-add=xml:ext:xml,dtd,xsd,xsl,xslt,ent,wsdl
3586 --type-add=xml:firstlinematch:/<[?]xml/
3590 --type-add=yaml:ext:yaml,yml
3592 $lines =~ s/==VERSION==/$App::Ack::VERSION/sm;
3598 package App
::Ack
::ConfigFinder
;
3605 use File
::Spec
3.00 ();
3607 use if ($^O eq 'MSWin32'), 'Win32';
3613 return bless {}, $class;
3617 sub _remove_redundancies
{
3622 foreach my $config (@configs) {
3623 my $path = $config->{path
};
3624 my $key = -e
$path ? Cwd
::realpath
( $path ) : $path;
3625 if ( not $App::Ack
::is_windows
) {
3626 # On Unix, uniquify on inode.
3627 my ($dev, $inode) = (stat $key)[0, 1];
3628 $key = "$dev:$inode" if defined $dev;
3630 push( @uniq, $config ) unless $seen{$key}++;
3636 sub _check_for_ackrc
{
3637 return unless defined $_[0];
3639 my @files = grep { -f
}
3640 map { File
::Spec-
>catfile(@_, $_) }
3643 App
::Ack
::die( File
::Spec-
>catdir(@_) . ' contains both .ackrc and _ackrc. Please remove one of those files.' )
3646 return wantarray ? @files : $files[0];
3647 } # end _check_for_ackrc
3651 sub find_config_files
{
3654 if ( $App::Ack
::is_windows
) {
3655 push @config_files, map { +{ path
=> File
::Spec-
>catfile($_, 'ackrc') } } (
3656 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3657 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3661 push @config_files, { path
=> '/etc/ackrc' };
3665 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3666 push @config_files, { path
=> $ENV{'ACKRC'} };
3669 push @config_files, map { +{ path
=> $_ } } _check_for_ackrc
($ENV{'HOME'});
3672 my $cwd = Cwd
::getcwd
();
3673 return () unless defined $cwd;
3675 # XXX This should go through some untainted cwd-fetching function, and not get untainted brute-force like this.
3678 my @dirs = File
::Spec-
>splitdir( $cwd );
3680 my $ackrc = _check_for_ackrc
(@dirs);
3681 if ( defined $ackrc ) {
3682 push @config_files, { project
=> 1, path
=> $ackrc };
3688 # We only test for existence here, so if the file is deleted out from under us, this will fail later.
3689 return _remove_redundancies
( @config_files );
3693 package App
::Ack
::ConfigLoader
;
3699 use File
::Spec
3.00 ();
3700 use Getopt
::Long
2.39 ();
3701 use Text
::ParseWords
3.1 ();
3713 return Getopt
::Long
::Parser-
>new( config
=> [ @standard, @opts ] );
3716 sub _generate_ignore_dir
{
3717 my ( $option_name, $opt ) = @_;
3719 my $is_inverted = $option_name =~ /^--no/;
3722 my ( undef, $dir ) = @_;
3724 $dir = _remove_directory_separator
( $dir );
3725 if ( $dir !~ /:/ ) {
3726 $dir = 'is:' . $dir;
3729 my ( $filter_type, $args ) = split /:/, $dir, 2;
3731 if ( $filter_type eq 'firstlinematch' ) {
3732 App
::Ack
::die( qq{Invalid filter specification "$filter_type" for option '$option_name'} );
3735 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args));
3738 my $previous_inversion_matches = $opt->{idirs
} && !($is_inverted xor $opt->{idirs
}[-1]->is_inverted());
3740 if ( $previous_inversion_matches ) {
3741 $collection = $opt->{idirs
}[-1];
3743 if ( $is_inverted ) {
3744 # This relies on invert of an inverted filter to return the original.
3745 $collection = $collection->invert();
3749 $collection = App
::Ack
::Filter
::Collection-
>new();
3750 push @{ $opt->{idirs
} }, $is_inverted ? $collection->invert() : $collection;
3753 $collection->add($filter);
3755 if ( $filter_type eq 'is' ) {
3756 $collection->add(App
::Ack
::Filter
::IsPath-
>new($args));
3762 sub _remove_directory_separator
{
3765 state $dir_sep_chars = $App::Ack
::is_windows
? quotemeta( '\\/' ) : quotemeta( File
::Spec-
>catfile( '', '' ) );
3767 $path =~ s/[$dir_sep_chars]$//;
3773 sub _process_filter_spec
{
3776 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3777 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3779 return ( $type_name,
3780 App
::Ack
::Filter-
>create_filter($ext_type, split(/,/, $arguments)) );
3782 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3783 my ( $type_name, $extensions ) = ( $1, $2 );
3785 my @extensions = split(/,/, $extensions);
3786 foreach my $extension ( @extensions ) {
3787 $extension =~ s/^[.]//;
3790 return ( $type_name, App
::Ack
::Filter-
>create_filter('ext', @extensions) );
3793 App
::Ack
::die( "Invalid filter specification '$spec'" );
3798 sub _uninvert_filter
{
3799 my ( $opt, @filters ) = @_;
3801 return unless defined $opt->{filters
} && @filters;
3803 # Loop through all the registered filters. If we hit one that
3804 # matches this extension and it's inverted, we need to delete it from
3806 for ( my $i = 0; $i < @{ $opt->{filters
} }; $i++ ) {
3807 my $opt_filter = @{ $opt->{filters
} }[$i];
3809 # XXX Do a real list comparison? This just checks string equivalence.
3810 if ( $opt_filter->is_inverted() && "$opt_filter->{filter}" eq "@filters" ) {
3811 splice @{ $opt->{filters
} }, $i, 1;
3820 sub _process_filetypes
{
3821 my ( $opt, $arg_sources ) = @_;
3823 my %additional_specs;
3825 my $add_spec = sub {
3826 my ( undef, $spec ) = @_;
3828 my ( $name, $filter ) = _process_filter_spec
($spec);
3830 push @{ $App::Ack
::mappings
{$name} }, $filter;
3832 $additional_specs{$name . '!'} = sub {
3833 my ( undef, $value ) = @_;
3835 my @filters = @{ $App::Ack
::mappings
{$name} };
3837 @filters = map { $_->invert() } @filters;
3840 _uninvert_filter
( $opt, @filters );
3843 push @{ $opt->{'filters'} }, @filters;
3847 my $set_spec = sub {
3848 my ( undef, $spec ) = @_;
3850 my ( $name, $filter ) = _process_filter_spec
($spec);
3852 $App::Ack
::mappings
{$name} = [ $filter ];
3854 $additional_specs{$name . '!'} = sub {
3855 my ( undef, $value ) = @_;
3857 my @filters = @{ $App::Ack
::mappings
{$name} };
3859 @filters = map { $_->invert() } @filters;
3862 push @{ $opt->{'filters'} }, @filters;
3866 my $delete_spec = sub {
3867 my ( undef, $name ) = @_;
3869 delete $App::Ack
::mappings
{$name};
3870 delete $additional_specs{$name . '!'};
3873 my %type_arg_specs = (
3874 'type-add=s' => $add_spec,
3875 'type-set=s' => $set_spec,
3876 'type-del=s' => $delete_spec,
3879 my $p = opt_parser
( 'no_auto_abbrev', 'pass_through' );
3880 foreach my $source (@{$arg_sources}) {
3881 my $args = $source->{contents
};
3884 # $args are modified in place, so no need to munge $arg_sources
3885 $p->getoptionsfromarray( $args, %type_arg_specs );
3888 ( undef, $source->{contents
} ) =
3889 $p->getoptionsfromstring( $args, %type_arg_specs );
3893 $additional_specs{'k|known-types'} = sub {
3894 my @filters = map { @{$_} } values(%App::Ack
::mappings
);
3896 push @{ $opt->{'filters'} }, @filters;
3899 return \
%additional_specs;
3904 my ( $opt, $extra_specs ) = @_;
3908 my ( $getopt, $value ) = @_;
3911 if ( $value =~ s/^no// ) {
3918 $callback = $extra_specs->{ $value . '!' };
3922 $callback->( $getopt, $cb_value );
3925 App
::Ack
::die( "Unknown type '$value'" );
3932 1 => sub { $opt->{1} = $opt->{m
} = 1 },
3933 'A|after-context:-1' => sub { shift; $opt->{A
} = _context_value
(shift) },
3934 'B|before-context:-1' => sub { shift; $opt->{B
} = _context_value
(shift) },
3935 'C|context:-1' => sub { shift; $opt->{B
} = $opt->{A
} = _context_value
(shift) },
3936 'break!' => \
$opt->{break},
3937 'c|count' => \
$opt->{c
},
3938 'color|colour!' => \
$opt->{color
},
3939 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
3940 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
3941 'color-colno=s' => \
$ENV{ACK_COLOR_COLNO
},
3942 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
3943 'column!' => \
$opt->{column
},
3944 'create-ackrc' => sub { say for ( '--ignore-ack-defaults', App
::Ack
::ConfigDefault
::options
() ); exit; },
3945 'debug' => \
$opt->{debug
},
3947 my ( undef, $value ) = @_;
3950 $opt->{noenv_seen
} = 1;
3954 'files-from=s' => \
$opt->{files_from
},
3955 'filter!' => \
$App::Ack
::is_filter_mode
,
3956 flush
=> sub { $| = 1 },
3957 'follow!' => \
$opt->{follow
},
3959 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
3960 'heading!' => \
$opt->{heading
},
3961 'h|no-filename' => \
$opt->{h
},
3962 'H|with-filename' => \
$opt->{H
},
3963 'i|ignore-case' => sub { $opt->{i
} = 1; $opt->{S
} = 0; },
3964 'I|no-ignore-case' => sub { $opt->{i
} = 0; $opt->{S
} = 0; },
3965 'ignore-directory|ignore-dir=s' => _generate_ignore_dir
('--ignore-dir', $opt),
3966 'ignore-file=s' => sub {
3967 my ( undef, $file ) = @_;
3969 my ( $filter_type, $args ) = split /:/, $file, 2;
3971 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args//''));
3973 if ( !$opt->{ifiles
} ) {
3974 $opt->{ifiles
} = App
::Ack
::Filter
::Collection-
>new();
3976 $opt->{ifiles
}->add($filter);
3978 'l|files-with-matches'
3980 'L|files-without-matches'
3982 'm|max-count=i' => \
$opt->{m
},
3983 'match=s' => \
$opt->{regex
},
3984 'n|no-recurse' => \
$opt->{n
},
3985 o
=> sub { $opt->{output
} = '$&' },
3986 'output=s' => \
$opt->{output
},
3988 my ( undef, $value ) = @_;
3990 $opt->{pager
} = $value || $ENV{PAGER
};
3992 'noignore-directory|noignore-dir=s' => _generate_ignore_dir
('--noignore-dir', $opt),
3993 'nopager' => sub { $opt->{pager
} = undef },
3994 'passthru' => \
$opt->{passthru
},
3995 'print0' => \
$opt->{print0
},
3996 'p|proximate:1' => \
$opt->{p
},
3997 'P' => sub { $opt->{p
} = 0 },
3998 'Q|literal' => \
$opt->{Q
},
3999 'r|R|recurse' => sub { $opt->{n
} = 0 },
4000 'range-start=s' => \
$opt->{range_start
},
4001 'range-end=s' => \
$opt->{range_end
},
4002 'range-invert!' => \
$opt->{range_invert
},
4004 'show-types' => \
$opt->{show_types
},
4005 'S|smart-case!' => sub { my (undef,$value) = @_; $opt->{S
} = $value; $opt->{i
} = 0 if $value; },
4006 'sort-files' => \
$opt->{sort_files
},
4007 't|type=s' => \
&_type_handler
,
4008 'T=s' => sub { my ($getopt,$value) = @_; $value="no$value"; _type_handler
($getopt,$value); },
4009 'underline!' => \
$opt->{underline
},
4010 'v|invert-match' => \
$opt->{v
},
4011 'w|word-regexp' => \
$opt->{w
},
4012 'x' => sub { $opt->{files_from
} = '-' },
4014 'help' => sub { App
::Ack
::show_help
(); exit; },
4015 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
4016 'help-colors' => sub { App
::Ack
::show_help_colors
(); exit; },
4017 'help-rgb-colors' => sub { App
::Ack
::show_help_rgb
(); exit; },
4018 $extra_specs ? %{$extra_specs} : (),
4023 sub _context_value
{
4026 # Contexts default to 2.
4027 return (!defined($val) || ($val < 0)) ? 2 : $val;
4031 sub _process_other
{
4032 my ( $opt, $extra_specs, $arg_sources ) = @_;
4035 my $is_help_types_active;
4037 foreach my $source (@{$arg_sources}) {
4038 if ( $source->{name
} eq 'ARGV' ) {
4039 $argv_source = $source->{contents
};
4044 if ( $argv_source ) { # This *should* always be true, but you never know...
4045 my $p = opt_parser
( 'pass_through' );
4046 $p->getoptionsfromarray( [ @{$argv_source} ],
4047 'help-types' => \
$is_help_types_active,
4051 my $arg_specs = get_arg_spec
( $opt, $extra_specs );
4053 my $p = opt_parser
();
4054 foreach my $source (@{$arg_sources}) {
4055 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4057 my $args_for_source = { %{$arg_specs} };
4059 if ( $source->{is_ackrc
} ) {
4062 App
::Ack
::die( "Option --$name is forbidden in .ackrc files." );
4065 $args_for_source = {
4066 %{$args_for_source},
4067 'output=s' => $illegal,
4068 'match=s' => $illegal,
4071 if ( $source->{project
} ) {
4074 App
::Ack
::die( "Option --$name is forbidden in project .ackrc files." );
4077 $args_for_source = {
4078 %{$args_for_source},
4079 'pager:s' => $illegal,
4085 $ret = $p->getoptionsfromarray( $args, %{$args_for_source} );
4088 ( $ret, $source->{contents
} ) =
4089 $p->getoptionsfromstring( $args, %{$args_for_source} );
4092 if ( !$is_help_types_active ) {
4093 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
4094 App
::Ack
::die( "Invalid option $where" );
4097 if ( $opt->{noenv_seen
} ) {
4098 App
::Ack
::die( "--noenv found in $source_name" );
4102 # XXX We need to check on a -- in the middle of a non-ARGV source
4108 sub _explode_sources
{
4109 my ( $sources ) = @_;
4114 my $arg_spec = get_arg_spec
( \
%opt, {} );
4116 my $dummy_sub = sub {};
4117 my $add_type = sub {
4118 my ( undef, $arg ) = @_;
4120 if ( $arg =~ /(\w+)=/) {
4121 $arg_spec->{$1} = $dummy_sub;
4124 ( $arg ) = split /:/, $arg;
4125 $arg_spec->{$arg} = $dummy_sub;
4129 my $del_type = sub {
4130 my ( undef, $arg ) = @_;
4132 delete $arg_spec->{$arg};
4135 my $p = opt_parser
( 'pass_through' );
4136 foreach my $source (@{$sources}) {
4137 my ( $name, $options ) = @{$source}{qw
/name contents/};
4138 if ( ref($options) ne 'ARRAY' ) {
4139 $source->{contents
} = $options =
4140 [ Text
::ParseWords
::shellwords
($options) ];
4143 for my $j ( 0 .. @{$options}-1 ) {
4144 next unless $options->[$j] =~ /^-/;
4145 my @chunk = ( $options->[$j] );
4146 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
4150 $p->getoptionsfromarray( [@chunk],
4151 'type-add=s' => $add_type,
4152 'type-set=s' => $add_type,
4153 'type-del=s' => $del_type,
4157 push @new_sources, {
4164 return \
@new_sources;
4171 my $first_a = $a->[0];
4172 my $first_b = $b->[0];
4174 $first_a =~ s/^--?//;
4175 $first_b =~ s/^--?//;
4177 return $first_a cmp $first_b;
4182 my ( $sources ) = @_;
4184 $sources = _explode_sources
($sources);
4189 foreach my $source (@{$sources}) {
4190 my $name = $source->{name
};
4191 if ( not $opts_by_source{$name} ) {
4192 $opts_by_source{$name} = [];
4193 push @source_names, $name;
4195 push @{$opts_by_source{$name}}, $source->{contents
};
4198 foreach my $name (@source_names) {
4199 my $contents = $opts_by_source{$name};
4202 say '=' x
length($name);
4203 say ' ', join(' ', @{$_}) for sort { _compare_opts
($a, $b) } @{$contents};
4210 sub _remove_default_options_if_needed
{
4211 my ( $sources ) = @_;
4215 foreach my $index ( 0 .. $#{$sources} ) {
4216 if ( $sources->[$index]{'name'} eq 'Defaults' ) {
4217 $default_index = $index;
4222 return $sources unless defined $default_index;
4224 my $should_remove = 0;
4226 my $p = opt_parser
( 'no_auto_abbrev', 'pass_through' );
4228 foreach my $index ( $default_index + 1 .. $#{$sources} ) {
4229 my $args = $sources->[$index]->{contents
};
4232 $p->getoptionsfromarray( $args,
4233 'ignore-ack-defaults' => \
$should_remove,
4237 ( undef, $sources->[$index]{contents
} ) = $p->getoptionsfromstring( $args,
4238 'ignore-ack-defaults' => \
$should_remove,
4243 return $sources unless $should_remove;
4245 my @copy = @{$sources};
4246 splice @copy, $default_index, 1;
4252 my $arg_sources = \
@_;
4255 pager
=> $ENV{ACK_PAGER_COLOR
} || $ENV{ACK_PAGER
},
4258 $arg_sources = _remove_default_options_if_needed
($arg_sources);
4260 # Check for --dump early.
4261 foreach my $source (@{$arg_sources}) {
4262 if ( $source->{name
} eq 'ARGV' ) {
4264 my $p = opt_parser
( 'pass_through' );
4265 $p->getoptionsfromarray( $source->{contents
},
4269 _dump_options
($arg_sources);
4275 my $type_specs = _process_filetypes
(\
%opt, $arg_sources);
4277 _check_for_mutex_options
( $type_specs );
4279 _process_other
(\
%opt, $type_specs, $arg_sources);
4280 while ( @{$arg_sources} ) {
4281 my $source = shift @{$arg_sources};
4282 my $args = $source->{contents
};
4284 # All of our sources should be transformed into an array ref
4286 my $source_name = $source->{name
};
4287 if ( $source_name eq 'ARGV' ) {
4291 App
::Ack
::die( "Source '$source_name' has extra arguments!" );
4295 App
::Ack
::die( 'The impossible has occurred!' );
4298 my $filters = ($opt{filters
} ||= []);
4300 # Throw the default filter in if no others are selected.
4301 if ( not grep { !$_->is_inverted() } @{$filters} ) {
4302 push @{$filters}, App
::Ack
::Filter
::Default-
>new();
4308 sub retrieve_arg_sources
{
4314 my $p = opt_parser
( 'no_auto_abbrev', 'pass_through' );
4317 'ackrc=s' => \
$ackrc,
4323 my $finder = App
::Ack
::ConfigFinder-
>new;
4324 @files = $finder->find_config_files;
4327 # We explicitly use open so we get a nice error message.
4328 # XXX This is a potential race condition!.
4329 if ( open my $fh, '<', $ackrc ) {
4333 App
::Ack
::die( "Unable to load ackrc '$ackrc': $!" );
4335 push( @files, { path
=> $ackrc } );
4338 push @arg_sources, {
4340 contents
=> [ App
::Ack
::ConfigDefault
::options_clean
() ],
4343 foreach my $file ( @files) {
4344 my @lines = read_rcfile
($file->{path
});
4346 push @arg_sources, {
4347 name
=> $file->{path
},
4348 contents
=> \
@lines,
4349 project
=> $file->{project
},
4355 push @arg_sources, {
4357 contents
=> [ @ARGV ],
4360 return @arg_sources;
4367 return unless defined $file && -e
$file;
4371 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
4372 while ( defined( my $line = <$fh> ) ) {
4377 next if $line eq '';
4378 next if $line =~ /^\s*#/;
4380 push( @lines, $line );
4382 close $fh or App
::Ack
::die( "Unable to close $file: $!" );
4388 # Verifies no mutex options were passed. Dies if they were.
4389 sub _check_for_mutex_options
{
4390 my $type_specs = shift;
4392 my $mutex = mutex_options
();
4394 my ($raw,$used) = _options_used
( $type_specs );
4396 my @used = sort { lc $a cmp lc $b } keys %{$used};
4398 for my $i ( @used ) {
4399 for my $j ( @used ) {
4401 if ( $mutex->{$i}{$j} ) {
4402 my $x = $raw->[ $used->{$i} ];
4403 my $y = $raw->[ $used->{$j} ];
4404 App
::Ack
::die( "Options '$x' and '$y' can't be used together." );
4413 # Processes the command line option and returns a hash of the options that were
4414 # used on the command line, using their full name. "--prox" shows up in the hash as "--proximate".
4416 my $type_specs = shift;
4419 my $real_spec = get_arg_spec
( \
%dummy_opt, $type_specs );
4421 # The real argument parsing doesn't check for --type-add, --type-del or --type-set because
4422 # they get removed by the argument processing. We have to account for them here.
4423 my $sub_dummy = sub {};
4426 'type-add=s' => $sub_dummy,
4427 'type-del=s' => $sub_dummy,
4428 'type-set=s' => $sub_dummy,
4429 'ignore-ack-defaults' => $sub_dummy,
4434 my %spec_capture_parsed;
4435 my %spec_capture_raw;
4438 # Capture the %parsed hash.
4441 my $sub_count = sub {
4444 $parsed{$arg} = $parsed_pos++;
4446 %spec_capture_parsed = (
4447 '<>' => sub { $parsed_pos++ }, # Bump forward one pos for non-options.
4448 map { $_ => $sub_count } keys %{$real_spec}
4452 # Capture the @raw array.
4455 %spec_capture_raw = (
4456 '<>' => sub { $raw_pos++ }, # Bump forward one pos for non-options.
4459 my $sub_count = sub {
4463 $raw[$raw_pos] = length($arg) == 1 ? "-$arg" : "--$arg";
4467 for my $opt_spec ( keys %{$real_spec} ) {
4472 $negatable = ($opt_spec =~ s/!$//);
4474 if ( $opt_spec =~ s/(=[si])$// ) {
4477 if ( $opt_spec =~ s/(:.+)$// ) {
4481 my @aliases = split( /\|/, $opt_spec );
4482 for my $alias ( @aliases ) {
4483 $alias .= $type if defined $type;
4484 $alias .= $default if defined $default;
4485 $alias .= '!' if $negatable;
4487 $spec_capture_raw{$alias} = $sub_count;
4492 # Parse @ARGV twice, once with each capture spec.
4493 my $p = opt_parser
( 'pass_through' ); # Ignore invalid options.
4494 $p->getoptionsfromarray( [@ARGV], %spec_capture_raw );
4495 $p->getoptionsfromarray( [@ARGV], %spec_capture_parsed );
4497 return (\
@raw,\
%parsed);
4502 # This list is machine-generated by dev/crank-mutex. Do not modify it by hand.
4570 'with-filename' => 1,
4703 'with-filename' => 1,
4805 'with-filename' => {
4816 } # End of mutex_options()
4819 1; # End of App::Ack::ConfigLoader
4820 package App
::Ack
::File
;
4830 my $filename = shift;
4833 filename
=> $filename,
4837 if ( $self->{filename
} eq '-' ) {
4838 $self->{fh
} = *STDIN
;
4847 return $_[0]->{filename
};
4855 return $self->{basename
} //= (File
::Spec-
>splitpath($self->name))[2];
4863 if ( !$self->{fh
} ) {
4864 if ( open $self->{fh
}, '<', $self->{filename
} ) {
4868 $self->{fh
} = undef;
4876 sub may_be_present
{
4880 # Tells if the file needs a line-by-line scan. This is a big
4881 # optimization because if you can tell from the outset that the pattern
4882 # is not found in the file at all, then there's no need to do the
4883 # line-by-line iteration.
4885 # Slurp up an entire file up to 10M, see if there are any matches
4886 # in it, and if so, let us know so we can iterate over it directly.
4888 # The $regex may be undef if it had a "$" in it, and is therefore unsuitable for this heuristic.
4890 my $may_be_present = 1;
4891 if ( $regex && $self->open() && -f
$self->{fh
} ) {
4893 my $size = 10_000_000;
4894 my $rc = sysread( $self->{fh
}, $buffer, $size );
4895 if ( !defined($rc) ) {
4896 if ( $App::Ack
::report_bad_filenames
) {
4897 App
::Ack
::warn( $self->name . ": $!" );
4899 $may_be_present = 0;
4902 # If we read all 10M, then we need to scan the rest.
4903 # If there are any carriage returns, our results are flaky, so scan the rest.
4904 if ( ($rc == $size) || (index($buffer,"\r") >= 0) ) {
4905 $may_be_present = 1;
4908 if ( $buffer !~ /$regex/o ) {
4909 $may_be_present = 0;
4915 return $may_be_present;
4923 if ( defined($self->{fh
}) ) {
4924 return unless -f
$self->{fh
};
4926 if ( !seek( $self->{fh
}, 0, 0 ) && $App::Ack
::report_bad_filenames
) {
4927 App
::Ack
::warn( "$self->{filename}: $!" );
4939 if ( $self->{fh
} ) {
4940 if ( !close($self->{fh
}) && $App::Ack
::report_bad_filenames
) {
4941 App
::Ack
::warn( $self->name() . ": $!" );
4943 $self->{fh
} = undef;
4954 return __PACKAGE__-
>new($self->name);
4962 if ( !exists $self->{firstliney
} ) {
4963 my $fh = $self->open();
4965 if ( $App::Ack
::report_bad_filenames
) {
4966 App
::Ack
::warn( $self->name . ': ' . $! );
4968 $self->{firstliney
} = '';
4972 my $rc = sysread( $fh, $buffer, 250 );
4974 $buffer =~ s/[\r\n].*//s;
4977 if ( !defined($rc) ) {
4978 App
::Ack
::warn( $self->name . ': ' . $! );
4982 $self->{firstliney
} = $buffer;
4987 return $self->{firstliney
};
4991 package App
::Ack
::Files
;
5005 my $self = bless {}, $class;
5007 my $descend_filter = $opt->{descend_filter
};
5010 $descend_filter = sub {
5016 File
::Next
::files
( {
5017 file_filter
=> $opt->{file_filter
},
5018 descend_filter
=> $descend_filter,
5019 error_handler
=> _generate_error_handler
(),
5020 warning_handler
=> sub {},
5021 sort_files
=> $opt->{sort_files
},
5022 follow_symlinks
=> $opt->{follow
},
5034 my $error_handler = _generate_error_handler
();
5036 File
::Next
::from_file
( {
5037 error_handler
=> $error_handler,
5038 warning_handler
=> $error_handler,
5039 sort_files
=> $opt->{sort_files
},
5040 }, $file ) or return undef;
5053 my $self = bless {}, $class;
5055 $self->{iter
} = sub {
5056 state $has_been_called = 0;
5058 if ( !$has_been_called ) {
5059 $has_been_called = 1;
5072 my $file = $self->{iter
}->();
5074 return unless defined($file);
5076 return App
::Ack
::File-
>new( $file );
5080 sub _generate_error_handler
{
5081 if ( $App::Ack
::report_bad_filenames
) {
5084 App
::Ack
::warn( $msg );
5093 package App
::Ack
::Filter
;
5103 my ( undef, $type, @args ) = @_;
5105 if ( my $package = $filter_types{$type} ) {
5106 return $package->new(@args);
5108 my $allowed_types = join( ', ', sort keys %filter_types );
5109 App
::Ack
::die( "Unknown filter type '$type'. Type must be one of: $allowed_types." );
5113 sub register_filter
{
5114 my ( undef, $type, $package ) = @_;
5116 $filter_types{$type} = $package;
5125 return App
::Ack
::Filter
::Inverse-
>new( $self );
5135 return '(unimplemented to_string)';
5146 package App
::Ack
::Filter
::Collection
;
5152 our @ISA = 'App::Ack::Filter';
5165 my ( $self, $file ) = @_;
5167 for my $group (values %{$self->{groups
}}) {
5168 return 1 if $group->filter($file);
5171 for my $filter (@{$self->{ungrouped
}}) {
5172 return 1 if $filter->filter($file);
5179 my ( $self, $filter ) = @_;
5181 if (exists $filter->{'groupname'}) {
5182 my $group = ($self->{groups
}->{$filter->{groupname
}} ||= $filter->create_group());
5183 $group->add($filter);
5186 push @{$self->{'ungrouped'}}, $filter;
5195 return ref($self) . " - $self";
5201 return join(', ', map { "($_)" } @{$self->{ungrouped
}});
5205 package App
::Ack
::Filter
::Default
;
5211 our @ISA = 'App::Ack::Filter';
5217 return bless {}, $class;
5221 my ( undef, $file ) = @_;
5223 return -T
$file->name;
5227 package App
::Ack
::Filter
::Extension
;
5233 our @ISA = 'App::Ack::Filter';
5238 my ( $class, @extensions ) = @_;
5240 my $exts = join('|', map { "\Q$_\E"} @extensions);
5241 my $re = qr/[.](?:$exts)$/i;
5244 extensions
=> \
@extensions,
5246 groupname
=> 'ExtensionGroup',
5251 return App
::Ack
::Filter
::ExtensionGroup-
>new();
5255 my ( $self, $file ) = @_;
5257 return $file->name =~ /$self->{regex}/;
5263 return ref($self) . ' - ' . $self->{regex
};
5269 return join( ' ', map { ".$_" } @{$self->{extensions
}} );
5273 App
::Ack
::Filter-
>register_filter(ext
=> __PACKAGE__
);
5277 package App
::Ack
::Filter
::ExtensionGroup
;
5283 our @ISA = 'App::Ack::Filter';
5295 my ( $self, $filter ) = @_;
5297 foreach my $ext (@{$filter->{extensions
}}) {
5298 $self->{data
}->{lc $ext} = 1;
5305 my ( $self, $file ) = @_;
5307 if ($file->name =~ /[.]([^.]*)$/) {
5308 return exists $self->{'data'}->{lc $1};
5317 return ref($self) . " - $self";
5323 return join(' ', map { ".$_" } sort keys %{$self->{data
}});
5327 package App
::Ack
::Filter
::FirstLineMatch
;
5334 our @ISA = 'App::Ack::Filter';
5338 my ( $class, $re ) = @_;
5340 $re =~ s{^/|/$}{}g; # XXX validate?
5348 # This test reads the first 250 characters of a file, then just uses the
5349 # first line found in that. This prevents reading something like an entire
5350 # .min.js file (which might be only one "line" long) into memory.
5353 my ( $self, $file ) = @_;
5355 return $file->firstliney =~ /$self->{regex}/;
5362 return ref($self) . ' - ' . $self->{regex
};
5368 (my $re = $self->{regex
}) =~ s{\([^:]*:(.*)\)$}{$1};
5370 return "First line matches /$re/";
5374 App
::Ack
::Filter-
>register_filter(firstlinematch
=> __PACKAGE__
);
5378 package App
::Ack
::Filter
::Inverse
;
5385 our @ISA = 'App::Ack::Filter';
5389 my ( $class, $filter ) = @_;
5397 my ( $self, $file ) = @_;
5399 return !$self->{filter
}->filter( $file );
5405 return $self->{'filter'};
5415 my $filter = $self->{'filter'};
5421 package App
::Ack
::Filter
::Is
;
5427 our @ISA = 'App::Ack::Filter';
5430 use File
::Spec
3.00 ();
5433 my ( $class, $filename ) = @_;
5436 filename
=> $filename,
5437 groupname
=> 'IsGroup',
5442 return App
::Ack
::Filter
::IsGroup-
>new();
5446 my ( $self, $file ) = @_;
5448 return (File
::Spec-
>splitpath($file->name))[2] eq $self->{filename
};
5454 return ref($self) . ' - ' . $self->{filename
};
5460 return $self->{filename
};
5464 App
::Ack
::Filter-
>register_filter(is => __PACKAGE__
);
5468 package App
::Ack
::Filter
::IsGroup
;
5474 our @ISA = 'App::Ack::Filter';
5486 my ( $self, $filter ) = @_;
5488 $self->{data
}->{ $filter->{filename
} } = 1;
5494 my ( $self, $file ) = @_;
5496 return exists $self->{data
}->{ $file->basename };
5502 return ref($self) . " - $self";
5508 return join(' ', keys %{$self->{data
}});
5512 package App
::Ack
::Filter
::IsPath
;
5518 our @ISA = 'App::Ack::Filter';
5523 my ( $class, $filename ) = @_;
5526 filename
=> $filename,
5527 groupname
=> 'IsPathGroup',
5532 return App
::Ack
::Filter
::IsPathGroup-
>new();
5536 my ( $self, $file ) = @_;
5538 return $file->name eq $self->{filename
};
5544 return ref($self) . ' - ' . $self->{filename
};
5550 return $self->{filename
};
5554 package App
::Ack
::Filter
::IsPathGroup
;
5560 our @ISA = 'App::Ack::Filter';
5572 my ( $self, $filter ) = @_;
5574 $self->{data
}->{ $filter->{filename
} } = 1;
5580 my ( $self, $file ) = @_;
5582 return exists $self->{data
}->{$file->name};
5588 return ref($self) . " - $self";
5594 return join(' ', keys %{$self->{data
}});
5598 package App
::Ack
::Filter
::Match
;
5603 our @ISA = 'App::Ack::Filter';
5609 my ( $class, $re ) = @_;
5611 $re =~ s{^/|/$}{}g; # XXX validate?
5616 groupname
=> 'MatchGroup',
5621 return App
::Ack
::Filter
::MatchGroup-
>new;
5625 my ( $self, $file ) = @_;
5627 return $file->basename =~ /$self->{regex}/;
5633 return ref($self) . ' - ' . $self->{regex
};
5639 return "Filename matches $self->{regex}";
5643 App
::Ack
::Filter-
>register_filter(match
=> __PACKAGE__
);
5647 package App
::Ack
::Filter
::MatchGroup
;
5653 our @ISA = 'App::Ack::Filter';
5666 my ( $self, $filter ) = @_;
5668 push @{ $self->{matches
} }, $filter->{regex
};
5670 my $re = join('|', map { "(?:$_)" } @{ $self->{matches
} });
5671 $self->{big_re
} = qr/$re/;
5677 my ( $self, $file ) = @_;
5679 return $file->basename =~ /$self->{big_re}/;
5682 # This class has no inspect() or to_string() method.
5683 # It will just use the default one unless someone writes something useful.
5692 our $VERSION = '1.18';
5698 our $name; # name of the current file
5699 our $dir; # dir of the current file
5701 our %files_defaults;
5706 file_filter
=> undef,
5707 descend_filter
=> undef,
5708 error_handler
=> sub { CORE
::die $_[0] },
5709 warning_handler
=> sub { CORE
::warn @_ },
5710 sort_files
=> undef,
5711 follow_symlinks
=> 1,
5714 %skip_dirs = map {($_,1)} (File
::Spec-
>curdir, File
::Spec-
>updir);
5719 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5721 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5723 my $filter = $parms->{file_filter
};
5725 while ( my $entry = shift @queue ) {
5726 my ( $dirname, $file, $fullpath, $is_dir, $is_file, $is_fifo ) = @{$entry};
5727 if ( $is_file || $is_fifo ) {
5730 local $File::Next
::dir
= $dirname;
5731 local $File::Next
::name
= $fullpath;
5732 next if not $filter->();
5734 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5737 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
5752 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5754 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5755 my $err = $parms->{error_handler
};
5756 my $warn = $parms->{warning_handler
};
5758 my $filename = $queue[0]->[1];
5760 if ( !defined($filename) ) {
5761 $err->( 'Must pass a filename to from_file()' );
5766 if ( $filename eq '-' ) {
5770 if ( !open( $fh, '<', $filename ) ) {
5771 $err->( "Unable to open $filename: $!", $! + 0 );
5776 my $filter = $parms->{file_filter
};
5778 local $/ = $parms->{nul_separated
} ? "\x00" : $/;
5779 while ( my $fullpath = <$fh> ) {
5781 next unless $fullpath =~ /./;
5782 if ( not ( -f
$fullpath || -p _
) ) {
5783 $warn->( "$fullpath: No such file" );
5787 my ($volume,$dirname,$file) = File
::Spec-
>splitpath( $fullpath );
5790 local $File::Next
::dir
= $dirname;
5791 local $File::Next
::name
= $fullpath;
5792 next if not $filter->();
5794 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5802 sub _bad_invocation
{
5803 my $good = (caller(1))[3];
5805 $bad =~ s/(.+)::/$1->/;
5806 return "$good must not be invoked as $bad";
5809 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
5810 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
5815 my @parts = split( /\//, $path );
5817 return $path if @parts < 2;
5819 return File
::Spec-
>catfile( @parts );
5825 my $defaults = shift;
5826 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
5828 my %passed_parms = %{$passed_parms};
5831 for my $key ( keys %{$defaults} ) {
5833 exists $passed_parms{$key}
5834 ? delete $passed_parms{$key}
5835 : $defaults->{$key};
5838 # Any leftover keys are bogus
5839 for my $badkey ( sort keys %passed_parms ) {
5840 my $sub = (caller(1))[3];
5841 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
5844 # If it's not a code ref, assume standard sort
5845 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
5846 $parms->{sort_files
} = \
&sort_standard
;
5851 my $start = reslash
( $_ );
5852 my $is_dir = -d
$start;
5854 my $is_fifo = (-p _
) || ($start =~ m{^/dev/fd});
5857 ? [ $start, undef, $start, $is_dir, $is_file, $is_fifo ]
5858 : [ undef, $start, $start, $is_dir, $is_file, $is_fifo ];
5861 return ($parms,@queue);
5865 sub _candidate_files
{
5867 my $dirname = shift;
5870 if ( !opendir $dh, $dirname ) {
5871 $parms->{error_handler
}->( "$dirname: $!", $! + 0 );
5876 my $descend_filter = $parms->{descend_filter
};
5877 my $follow_symlinks = $parms->{follow_symlinks
};
5879 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
5880 my $fullpath = File
::Spec-
>catdir( $dirname, $file );
5881 if ( !$follow_symlinks ) {
5882 next if -l
$fullpath;
5889 my $is_fifo = (-p _
) || ($fullpath =~ m{^/dev/fd});
5891 # Only do directory checking if we have a descend_filter
5892 if ( $descend_filter ) {
5894 local $File::Next
::dir
= $fullpath;
5896 next if not $descend_filter->();
5899 push @newfiles, [ $dirname, $file, $fullpath, $is_dir, $is_file, $is_fifo ];
5903 my $sort_sub = $parms->{sort_files
};
5905 @newfiles = sort $sort_sub @newfiles;
5913 1; # End of File::Next