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.4.0'; # 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 my $display_filename = $file->name;
327 $display_filename = Term
::ANSIColor
::colored
($display_filename, $ENV{ACK_COLOR_FILENAME
});
329 App
::Ack
::say( $display_filename, ':', $matches_for_this_file );
332 App
::Ack
::say( $matches_for_this_file );
337 if ( !$opt_show_filename ) {
338 App
::Ack
::say( $total_count );
349 while ( defined( my $file = $files->next ) ) {
350 my $is_match = count_matches_in_file
( $file, 1 );
352 if ( $opt_L ? !$is_match : $is_match ) {
353 App
::Ack
::say( $file->name );
357 last if defined($opt_m) && ($nmatches >= $opt_m);
365 sub _compile_descend_filter
{
369 my $dont_ignore_dirs = 0;
371 for my $filter (@{$opt->{idirs
} || []}) {
372 if ($filter->is_inverted()) {
380 # If we have one or more --noignore-dir directives, we can't ignore
381 # entire subdirectory hierarchies, so we return an "accept all"
382 # filter and scrutinize the files more in _compile_file_filter.
383 return if $dont_ignore_dirs;
384 return unless $idirs;
386 $idirs = $opt->{idirs
};
389 my $file = App
::Ack
::File-
>new($File::Next
::dir
);
390 return !grep { $_->filter($file) } @{$idirs};
394 sub _compile_file_filter
{
395 my ( $opt, $start ) = @_;
397 my $ifiles_filters = $opt->{ifiles
};
399 my $filters = $opt->{'filters'} || [];
400 my $direct_filters = App
::Ack
::Filter
::Collection-
>new();
401 my $inverse_filters = App
::Ack
::Filter
::Collection-
>new();
403 foreach my $filter (@{$filters}) {
404 if ($filter->is_inverted()) {
405 # We want to check if files match the uninverted filters
406 $inverse_filters->add($filter->invert());
409 $direct_filters->add($filter);
413 my %is_member_of_starting_set = map { (get_file_id
($_) => 1) } @{$start};
415 my @ignore_dir_filter = @{$opt->{idirs
} || []};
416 my @is_inverted = map { $_->is_inverted() } @ignore_dir_filter;
417 # This depends on InverseFilter->invert returning the original filter (for optimization).
418 @ignore_dir_filter = map { $_->is_inverted() ? $_->invert() : $_ } @ignore_dir_filter;
419 my $dont_ignore_dir_filter = grep { $_ } @is_inverted;
420 my $previous_dir = '';
421 my $previous_dir_ignore_result;
425 if ( $File::Next
::name
=~ /$search_re/o ) {
432 # ack always selects files that are specified on the command
433 # line, regardless of filetype. If you want to ack a JPEG,
434 # and say "ack foo whatever.jpg" it will do it for you.
435 return 1 if $is_member_of_starting_set{ get_file_id
($File::Next
::name
) };
437 if ( $dont_ignore_dir_filter ) {
438 if ( $previous_dir eq $File::Next
::dir
) {
439 if ( $previous_dir_ignore_result ) {
444 my @dirs = File
::Spec-
>splitdir($File::Next
::dir
);
448 for ( my $i = 0; $i < @dirs; $i++) {
449 my $dir_rsrc = App
::Ack
::File-
>new(File
::Spec-
>catfile(@dirs[0 .. $i]));
452 for my $filter (@ignore_dir_filter) {
453 if ( $filter->filter($dir_rsrc) ) {
454 $is_ignoring = !$is_inverted[$j];
460 $previous_dir = $File::Next
::dir
;
461 $previous_dir_ignore_result = $is_ignoring;
463 if ( $is_ignoring ) {
469 # Ignore named pipes found in directory searching. Named
470 # pipes created by subprocesses get specified on the command
471 # line, so the rule of "always select whatever is on the
472 # command line" wins.
473 return 0 if -p
$File::Next
::name
;
475 # We can't handle unreadable filenames; report them.
477 use filetest
'access';
479 if ( not -R
$File::Next
::name
) {
480 if ( $App::Ack
::report_bad_filenames
) {
481 App
::Ack
::warn( "${File::Next::name}: cannot open file for reading" );
487 my $file = App
::Ack
::File-
>new($File::Next
::name
);
489 if ( $ifiles_filters && $ifiles_filters->filter($file) ) {
493 my $match_found = $direct_filters->filter($file);
495 # Don't bother invoking inverse filters unless we consider the current file a match.
496 if ( $match_found && $inverse_filters->filter( $file ) ) {
504 # Returns a (fairly) unique identifier for a file.
505 # Use this function to compare two files to see if they're
506 # equal (ie. the same file, but with a different path/links/etc).
508 my ( $filename ) = @_;
510 if ( $App::Ack
::is_windows
) {
511 return File
::Next
::reslash
( $filename );
514 # XXX Is this the best method? It always hits the FS.
515 if ( my ( $dev, $inode ) = (stat($filename))[0, 1] ) {
516 return join(':', $dev, $inode);
519 # XXX This could be better.
525 # Returns a regex object based on a string and command-line options.
526 # Dies when the regex $str is undefined (i.e. not given on command line).
532 defined $str or App
::Ack
::die( 'No regular expression found.' );
535 # Compile the regex to see if it dies or throws warnings.
536 local $SIG{__WARN__
} = sub { die @_ }; # Anything that warns becomes a die.
537 my $scratch_regex = eval { qr/$str/ };
538 if ( not $scratch_regex ) {
542 if ( $err =~ m{^(.+?); marked by <-- HERE in m/(.+?) <-- HERE} ) {
543 my ($why, $where) = ($1,$2);
544 my $pointy = ' ' x
(6+length($where)) . '^---HERE';
545 App
::Ack
::die( "Invalid regex '$str'\nRegex: $str\n$pointy $why" );
548 App
::Ack
::die( "Invalid regex '$str'\n$err" );
553 # Check for lowercaseness before we do any modifications.
554 my $regex_is_lc = App
::Ack
::is_lowercase
( $str );
556 $str = quotemeta( $str ) if $opt->{Q
};
564 if ( $str =~ /^\\[wd]/ ) {
565 # Explicit \w is good.
568 # Can start with \w, (, [ or dot.
569 if ( $str !~ /^[\w\(\[\.]/ ) {
574 # Can end with \w, }, ), ], +, *, or dot.
575 if ( $str !~ /[\w\}\)\]\+\*\?\.]$/ ) {
578 # ... unless it's escaped.
579 elsif ( $str =~ /\\[\}\)\]\+\*\?\.]$/ ) {
584 App
::Ack
::die( '-w will not do the right thing if your regex does not begin and end with a word character.' );
587 if ( $str =~ /^\w+$/ ) {
588 # No need for fancy regex if it's a simple word.
589 $str = sprintf( '\b(?:%s)\b', $str );
592 $str = sprintf( '(?:^|\b|\s)\K(?:%s)(?=\s|\b|$)', $str );
596 if ( $opt->{i
} || ($opt->{S
} && $regex_is_lc) ) {
597 $_ = "(?i)$_" for ( $str, $scan_str );
600 my $scan_regex = undef;
601 my $regex = eval { qr/$str/ };
603 if ( $scan_str !~ /\$/ ) {
604 # No line_scan is possible if there's a $ in the regex.
605 $scan_regex = eval { qr/$scan_str/m };
611 App
::Ack
::die( "Invalid regex '$str':\n $err" );
614 return ($regex, $scan_regex);
621 # Number of context lines
622 my $n_before_ctx_lines;
623 my $n_after_ctx_lines;
625 # Array to keep track of lines that might be required for a "before" context
626 my @before_context_buf;
627 # Position to insert next line in @before_context_buf
628 my $before_context_pos;
630 # Number of "after" context lines still pending
631 my $after_context_pending;
633 # Number of latest line that got printed
637 state $has_printed_from_any_file = 0;
640 sub file_loop_normal
{
643 $n_before_ctx_lines = $opt_output ? 0 : ($opt_B || 0);
644 $n_after_ctx_lines = $opt_output ? 0 : ($opt_A || 0);
646 @before_context_buf = (undef) x
$n_before_ctx_lines;
647 $before_context_pos = 0;
649 $is_tracking_context = $n_before_ctx_lines || $n_after_ctx_lines;
654 while ( defined( my $file = $files->next ) ) {
655 if ($is_tracking_context) {
657 $after_context_pending = 0;
658 if ( $opt_heading ) {
662 my $needs_line_scan = 1;
663 if ( !$opt_passthru && !$opt_v ) {
665 if ( $file->may_be_present( $scan_re ) ) {
669 $needs_line_scan = 0;
672 if ( $needs_line_scan ) {
674 $nmatches += print_matches_in_file
( $file );
676 last if $opt_1 && $nmatches;
683 sub print_matches_in_file
{
686 my $max_count = $opt_m || -1; # Go negative for no limit so it can never reduce to 0.
688 my $filename = $file->name;
690 my $has_printed_from_this_file = 0;
692 my $fh = $file->open;
694 if ( $App::Ack
::report_bad_filenames
) {
695 App
::Ack
::warn( "$filename: $!" );
700 my $display_filename = $filename;
701 if ( $opt_show_filename && $opt_heading && $opt_color ) {
702 $display_filename = Term
::ANSIColor
::colored
($display_filename, $ENV{ACK_COLOR_FILENAME
});
705 # Check for context before the main loop, so we don't pay for it if we don't need it.
706 if ( $is_tracking_context ) {
709 $after_context_pending = 0;
711 my $in_range = range_setup
();
715 $match_colno = undef;
717 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
722 $does_match = !/$search_re/o;
725 if ( $does_match = /$search_re/o ) {
726 # @- = @LAST_MATCH_START
727 # @+ = @LAST_MATCH_END
728 $match_colno = $-[0] + 1;
733 if ( $does_match && $max_count ) {
734 if ( !$has_printed_from_this_file ) {
735 $stats{filematches
}++;
736 if ( $opt_break && $has_printed_from_any_file ) {
737 App
::Ack
::print_blank_line
();
739 if ( $opt_show_filename && $opt_heading ) {
740 App
::Ack
::say( $display_filename );
743 print_line_with_context
( $filename, $_, $. );
744 $has_printed_from_this_file = 1;
745 $stats{linematches
}++;
750 if ( $after_context_pending ) {
751 # Disable $opt_column since there are no matches in the context lines.
752 local $opt_column = 0;
753 print_line_with_options
( $filename, $_, $., '-' );
754 --$after_context_pending;
756 elsif ( $n_before_ctx_lines ) {
757 # Save line for "before" context.
758 $before_context_buf[$before_context_pos] = $_;
759 $before_context_pos = ($before_context_pos+1) % $n_before_ctx_lines;
763 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
765 last if ($max_count == 0) && ($after_context_pending == 0);
768 elsif ( $opt_passthru ) {
771 my $in_range = range_setup
();
776 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
778 $match_colno = undef;
779 if ( $in_range && ($opt_v xor /$search_re/o) ) {
781 $match_colno = $-[0] + 1;
783 if ( !$has_printed_from_this_file ) {
784 if ( $opt_break && $has_printed_from_any_file ) {
785 App
::Ack
::print_blank_line
();
787 if ( $opt_show_filename && $opt_heading ) {
788 App
::Ack
::say( $display_filename );
791 print_line_with_options
( $filename, $_, $., ':' );
792 $has_printed_from_this_file = 1;
797 if ( $opt_break && !$has_printed_from_this_file && $has_printed_from_any_file ) {
798 App
::Ack
::print_blank_line
();
800 print_line_with_options
( $filename, $_, $., '-', 1 );
801 $has_printed_from_this_file = 1;
804 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
806 last if $max_count == 0;
812 $match_colno = undef;
813 my $in_range = range_setup
();
818 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
821 if ( !/$search_re/o ) {
822 if ( !$has_printed_from_this_file ) {
823 if ( $opt_break && $has_printed_from_any_file ) {
824 App
::Ack
::print_blank_line
();
826 if ( $opt_show_filename && $opt_heading ) {
827 App
::Ack
::say( $display_filename );
830 print_line_with_context
( $filename, $_, $. );
831 $has_printed_from_this_file = 1;
837 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
839 last if $max_count == 0;
842 else { # Normal search: No context, no -v, no --passthru
845 my $last_match_lineno;
846 my $in_range = range_setup
();
851 $in_range = 1 if ( $using_ranges && !$in_range && $opt_range_start && /$opt_range_start/o );
854 $match_colno = undef;
855 if ( /$search_re/o ) {
856 $match_colno = $-[0] + 1;
857 if ( !$has_printed_from_this_file ) {
858 $stats{filematches
}++;
859 if ( $opt_break && $has_printed_from_any_file ) {
860 App
::Ack
::print_blank_line
();
862 if ( $opt_show_filename && $opt_heading ) {
863 App
::Ack
::say( $display_filename );
867 if ( $last_match_lineno ) {
868 if ( $. > $last_match_lineno + $opt_p ) {
869 App
::Ack
::print_blank_line
();
872 elsif ( !$opt_break && $has_printed_from_any_file ) {
873 App
::Ack
::print_blank_line
();
877 print_line_with_options
( $filename, $_, $., ':' );
878 $has_printed_from_this_file = 1;
880 $stats{linematches
}++;
882 $last_match_lineno = $.;
886 $in_range = 0 if ( $using_ranges && $in_range && $opt_range_end && /$opt_range_end/o );
888 last if $max_count == 0;
896 sub print_line_with_options
{
897 my ( $filename, $line, $lineno, $separator, $skip_coloring ) = @_;
899 $has_printed_from_any_file = 1;
900 $printed_lineno = $lineno;
904 if ( $opt_show_filename && defined($filename) ) {
906 $colno = get_match_colno
() if $opt_column;
908 $filename = Term
::ANSIColor
::colored
( $filename, $ENV{ACK_COLOR_FILENAME
} );
909 $lineno = Term
::ANSIColor
::colored
( $lineno, $ENV{ACK_COLOR_LINENO
} );
910 $colno = Term
::ANSIColor
::colored
( $colno, $ENV{ACK_COLOR_COLNO
} ) if $opt_column;
912 if ( $opt_heading ) {
913 push @line_parts, $lineno;
916 push @line_parts, $filename, $lineno;
918 push @line_parts, $colno if $opt_column;
922 while ( $line =~ /$search_re/og ) {
923 my $output = $opt_output;
924 if ( @special_vars_used_by_opt_output ) {
927 # Stash copies of the special variables because we can't rely
928 # on them not changing in the process of doing the s///.
930 my %keep = map { ($_ => ${$_} // '') } @special_vars_used_by_opt_output;
931 $keep{_
} = $line if exists $keep{_
}; # Manually set it because $_ gets reset in a map.
932 $keep{f
} = $filename if exists $keep{f
};
933 my $special_vars_used_by_opt_output = join( '', @special_vars_used_by_opt_output );
934 $output =~ s/\$([$special_vars_used_by_opt_output])/$keep{$1}/ego;
936 App
::Ack
::say( join( $separator, @line_parts, $output ) );
942 # We have to do underlining before any highlighting because highlighting modifies string length.
943 if ( $opt_underline && !$skip_coloring ) {
944 while ( $line =~ /$search_re/og ) {
945 my $match_start = $-[0] // next;
946 my $match_end = $+[0];
947 my $match_length = $match_end - $match_start;
948 last if $match_length <= 0;
950 my $spaces_needed = $match_start - length $underline;
952 $underline .= (' ' x
$spaces_needed);
953 $underline .= ('^' x
$match_length);
956 if ( $opt_color && !$skip_coloring ) {
957 my $highlighted = 0; # If highlighted, need to escape afterwards.
959 while ( $line =~ /$search_re/og ) {
960 my $match_start = $-[0] // next;
961 my $match_end = $+[0];
962 my $match_length = $match_end - $match_start;
963 last if $match_length <= 0;
965 my $substring = substr( $line, $match_start, $match_length );
966 my $substitution = Term
::ANSIColor
::colored
( $substring, $ENV{ACK_COLOR_MATCH
} );
968 # Fourth argument replaces the string specified by the first three.
969 substr( $line, $match_start, $match_length, $substitution );
971 # Move the offset of where /g left off forward the number of spaces of highlighting.
972 pos($line) = $match_end + (length( $substitution ) - length( $substring ));
975 # Reset formatting and delete everything to the end of the line.
976 $line .= "\e[0m\e[K" if $highlighted;
979 push @line_parts, $line;
980 App
::Ack
::say( join( $separator, @line_parts ) );
982 # Print the underline, if appropriate.
983 if ( $underline ne '' ) {
984 # Figure out how many spaces are used per line for the ANSI coloring.
985 state $chars_used_by_coloring;
986 if ( !defined($chars_used_by_coloring) ) {
987 $chars_used_by_coloring = 0;
989 my $len_fn = sub { length( Term
::ANSIColor
::colored
( 'x', $ENV{$_[0]} ) ) - 1 };
990 $chars_used_by_coloring += $len_fn->('ACK_COLOR_FILENAME') unless $opt_heading;
991 $chars_used_by_coloring += $len_fn->('ACK_COLOR_LINENO');
992 $chars_used_by_coloring += $len_fn->('ACK_COLOR_COLNO') if $opt_column;
996 pop @line_parts; # Leave only the stuff on the left.
998 my $stuff_on_the_left = join( $separator, @line_parts );
999 my $spaces_needed = length($stuff_on_the_left) - $chars_used_by_coloring + 1;
1001 App
::Ack
::print( ' ' x
$spaces_needed );
1003 App
::Ack
::say( $underline );
1010 sub print_line_with_context
{
1011 my ( $filename, $matching_line, $lineno ) = @_;
1013 $matching_line =~ s/[\r\n]+$//;
1015 # Check if we need to print context lines first.
1016 if ( $opt_A || $opt_B ) {
1017 my $before_unprinted = $lineno - $printed_lineno - 1;
1018 if ( !$is_first_match && ( !$printed_lineno || $before_unprinted > $n_before_ctx_lines ) ) {
1019 App
::Ack
::say( '--' );
1022 # We want at most $n_before_ctx_lines of context.
1023 if ( $before_unprinted > $n_before_ctx_lines ) {
1024 $before_unprinted = $n_before_ctx_lines;
1027 while ( $before_unprinted > 0 ) {
1028 my $line = $before_context_buf[($before_context_pos - $before_unprinted + $n_before_ctx_lines) % $n_before_ctx_lines];
1032 # Disable $opt->{column} since there are no matches in the context lines.
1033 local $opt_column = 0;
1035 print_line_with_options
( $filename, $line, $lineno-$before_unprinted, '-' );
1036 $before_unprinted--;
1040 print_line_with_options
( $filename, $matching_line, $lineno, ':' );
1042 # We want to get the next $n_after_ctx_lines printed.
1043 $after_context_pending = $n_after_ctx_lines;
1045 $is_first_match = 0;
1052 sub get_match_colno
{
1053 return $match_colno;
1056 sub count_matches_in_file
{
1058 my $bail = shift; # True if we're just checking for existence.
1063 if ( !$file->open() ) {
1065 if ( $App::Ack
::report_bad_filenames
) {
1066 App
::Ack
::warn( $file->name . ": $!" );
1071 if ( !$file->may_be_present( $scan_re ) ) {
1080 my $in_range = range_setup
();
1082 my $fh = $file->{fh
};
1083 if ( $using_ranges ) {
1086 $in_range = 1 if ( !$in_range && $opt_range_start && /$opt_range_start/o );
1088 if ( /$search_re/o xor $opt_v ) {
1093 $in_range = 0 if ( $in_range && $opt_range_end && /$opt_range_end/o );
1099 if ( /$search_re/o xor $opt_v ) {
1113 return !$using_ranges || (!$opt_range_start && $opt_range_end);
1123 ack - grep-like text finder
1127 ack [options] PATTERN [FILE...]
1128 ack -f [options] [DIRECTORY...]
1132 ack is designed as an alternative to F<grep> for programmers.
1134 ack searches the named input FILEs or DIRECTORYs for lines containing a
1135 match to the given PATTERN. By default, ack prints the matching lines.
1136 If no FILE or DIRECTORY is given, the current directory will be searched.
1138 PATTERN is a Perl regular expression. Perl regular expressions
1139 are commonly found in other programming languages, but for the particulars
1140 of their behavior, please consult
1141 L<perlreref|https://perldoc.perl.org/perlreref.html>. If you don't know
1142 how to use regular expression but are interested in learning, you may
1143 consult L<perlretut|https://perldoc.perl.org/perlretut.html>. If you do not
1144 need or want ack to use regular expressions, please see the
1145 C<-Q>/C<--literal> option.
1147 Ack can also list files that would be searched, without actually
1148 searching them, to let you take advantage of ack's file-type filtering
1151 =head1 FILE SELECTION
1153 If files are not specified for searching, either on the command
1154 line or piped in with the C<-x> option, I<ack> delves into
1155 subdirectories selecting files for searching.
1157 I<ack> is intelligent about the files it searches. It knows about
1158 certain file types, based on both the extension on the file and,
1159 in some cases, the contents of the file. These selections can be
1160 made with the B<--type> option.
1162 With no file selection, I<ack> searches through regular files that
1163 are not explicitly excluded by B<--ignore-dir> and B<--ignore-file>
1164 options, either present in F<ackrc> files or on the command line.
1166 The default options for I<ack> ignore certain files and directories. These
1171 =item * Backup files: Files matching F<#*#> or ending with F<~>.
1173 =item * Coredumps: Files matching F<core.\d+>
1175 =item * Version control directories like F<.svn> and F<.git>.
1179 Run I<ack> with the C<--dump> option to see what settings are set.
1181 However, I<ack> always searches the files given on the command line,
1182 no matter what type. If you tell I<ack> to search in a coredump,
1183 it will search in a coredump.
1185 =head1 DIRECTORY SELECTION
1187 I<ack> descends through the directory tree of the starting directories
1188 specified. If no directories are specified, the current working directory is
1189 used. However, it will ignore the shadow directories used by
1190 many version control systems, and the build directories used by the
1191 Perl MakeMaker system. You may add or remove a directory from this
1192 list with the B<--[no]ignore-dir> option. The option may be repeated
1193 to add/remove multiple directories from the ignore list.
1195 For a complete list of directories that do not get searched, run
1198 =head1 MATCHING IN A RANGE OF LINES
1200 The C<--range-start> and C<--range-end> options let you specify ranges of
1201 lines to search within each file.
1203 Say you had the following file, called F<testfile>:
1205 # This function calls print on "foo".
1215 Calling C<ack print> will give us five matches:
1217 $ ack print testfile
1218 # This function calls print on "foo".
1224 What if we only want to search for C<print> within the subroutines? We can
1225 specify ranges of lines that we want ack to search. The range starts with
1226 any line that matches the pattern C<^sub \w+>, and stops with any line that
1229 $ ack --range-start='^sub \w+' --range-end='^}' print testfile
1233 Note that ack searched two ranges of lines. The listing below shows which
1234 lines were in a range and which were out of the range.
1236 Out # This function calls print on "foo".
1244 Out my $task = 'print';
1246 You don't have to specify both C<--range-start> and C<--range-end>. IF
1247 C<--range-start> is omitted, then the range runs from the first line in the
1248 file unitl the first line that matches C<--range-end>. Similarly, if
1249 C<--range-end> is omitted, the range runs from the first line matching
1250 C<--range-start> to the end of the file.
1252 For example, if you wanted to search all HTML files up until the first
1253 instance of the C<< <body> >>, you could do
1255 ack foo --range-end='<body>'
1257 Or to search after Perl's `__DATA__` or `__END__` markers, you would do
1259 ack pattern --range-end='^__(END|DATA)__'
1261 It's possible for a range to start and stop on the same line. For example
1263 --range-start='<title>' --range-end='</title>'
1265 would match this line as both the start and end of the range, making a
1268 <title>Page title</title>
1270 Note that the patterns in C<--range-start> and C<--range-end> are not
1271 affected by options like C<-i>, C<-w> and C<-Q> that modify the behavior of
1272 the main pattern being matched.
1274 Again, ranges only affect where matches are looked for. Everything else in
1275 ack works the same way. Using C<-c> option with a range will give a count
1276 of all the matches that appear within those ranges. The C<-l> shows those
1277 files that have a match within a range, and the C<-L> option shows files
1278 that do not have a match within a range.
1280 The C<-v> option for negating a match works inside the range, too.
1281 To see lines that don't match "google" within the "<head>" section of
1282 your HTML files, you could do:
1284 ack google -v --html --range-start='<head' --range-end='</head>'
1286 Specifying a range to search does not affect how matches are displayed.
1287 The context for a match will still be the same, and
1289 Using the context options work the same way, and will show context
1290 lines for matches even if the context lines fall outside the range.
1291 Similarly, C<--passthru> will show all lines in the file, but only show
1292 matches for lines within the range.
1300 Specifies an ackrc file to load after all others; see L</"ACKRC LOCATION SEMANTICS">.
1302 =item B<-A I<NUM>>, B<--after-context=I<NUM>>
1304 Print I<NUM> lines of trailing context after matching lines.
1306 =item B<-B I<NUM>>, B<--before-context=I<NUM>>
1308 Print I<NUM> lines of leading context before matching lines.
1310 =item B<--[no]break>
1312 Print a break between results from different files. On by default
1313 when used interactively.
1315 =item B<-C [I<NUM>]>, B<--context[=I<NUM>]>
1317 Print I<NUM> lines (default 2) of context around matching lines.
1318 You can specify zero lines of context to override another context
1319 specified in an ackrc.
1321 =item B<-c>, B<--count>
1323 Suppress normal output; instead print a count of matching lines for
1324 each input file. If B<-l> is in effect, it will only show the
1325 number of lines for each file that has lines matching. Without
1326 B<-l>, some line counts may be zeroes.
1328 If combined with B<-h> (B<--no-filename>) ack outputs only one total
1331 =item B<--[no]color>, B<--[no]colour>
1333 B<--color> highlights the matching text. B<--nocolor> suppresses
1334 the color. This is on by default unless the output is redirected.
1336 On Windows, this option is off by default unless the
1337 L<Win32::Console::ANSI> module is installed or the C<ACK_PAGER_COLOR>
1338 environment variable is used.
1340 =item B<--color-filename=I<color>>
1342 Sets the color to be used for filenames.
1344 =item B<--color-match=I<color>>
1346 Sets the color to be used for matches.
1348 =item B<--color-colno=I<color>>
1350 Sets the color to be used for column numbers.
1352 =item B<--color-lineno=I<color>>
1354 Sets the color to be used for line numbers.
1356 =item B<--[no]column>
1358 Show the column number of the first match. This is helpful for
1359 editors that can place your cursor at a given position.
1361 =item B<--create-ackrc>
1363 Dumps the default ack options to standard output. This is useful for
1364 when you want to customize the defaults.
1368 Writes the list of options loaded and where they came from to standard
1369 output. Handy for debugging.
1373 B<--noenv> disables all environment processing. No F<.ackrc> is
1374 read and all environment variables are ignored. By default, F<ack>
1375 considers F<.ackrc> and settings in the environment.
1379 B<--flush> flushes output immediately. This is off by default
1380 unless ack is running interactively (when output goes to a pipe or
1385 Only print the files that would be searched, without actually doing
1386 any searching. PATTERN must not be specified, or it will be taken
1387 as a path to search.
1389 =item B<--files-from=I<FILE>>
1391 The list of files to be searched is specified in I<FILE>. The list of
1392 files are separated by newlines. If I<FILE> is C<->, the list is loaded
1393 from standard input.
1395 Note that the list of files is B<not> filtered in any way. If you
1396 add C<--type=html> in addition to C<--files-from>, the C<--type> will
1400 =item B<--[no]filter>
1402 Forces ack to act as if it were receiving input via a pipe.
1404 =item B<--[no]follow>
1406 Follow or don't follow symlinks, other than whatever starting files
1407 or directories were specified on the command line.
1409 This is off by default.
1411 =item B<-g I<PATTERN>>
1413 Print searchable files where the relative path + filename matches
1420 is exactly the same as
1424 This means that just as ack will not search, for example, F<.jpg>
1425 files, C<-g> will not list F<.jpg> files either. ack is not intended
1426 to be a general-purpose file finder.
1428 Note also that if you have C<-i> in your .ackrc that the filenames
1429 to be matched will be case-insensitive as well.
1431 This option can be combined with B<--color> to make it easier to
1434 =item B<--[no]group>
1436 B<--group> groups matches by file name. This is the default
1437 when used interactively.
1439 B<--nogroup> prints one result per line, like grep. This is the
1440 default when output is redirected.
1442 =item B<-H>, B<--with-filename>
1444 Print the filename for each match. This is the default unless searching
1445 a single explicitly specified file.
1447 =item B<-h>, B<--no-filename>
1449 Suppress the prefixing of filenames on output when multiple files are
1452 =item B<--[no]heading>
1454 Print a filename heading above each file's results. This is the default
1455 when used interactively.
1459 Print a short help statement.
1461 =item B<--help-types>
1463 Print all known types.
1465 =item B<--help-colors>
1467 Print a chart of various color combinations.
1469 =item B<--help-rgb-colors>
1471 Like B<--help-colors> but with more precise RGB colors.
1473 =item B<-i>, B<--ignore-case>
1475 Ignore case distinctions in PATTERN. Overrides B<--smart-case> and B<-I>.
1477 =item B<-I>, B<--no-ignore-case>
1479 Turns on case distinctions in PATTERN. Overrides B<--smart-case> and B<-i>.
1481 =item B<--ignore-ack-defaults>
1483 Tells ack to completely ignore the default definitions provided with ack.
1484 This is useful in combination with B<--create-ackrc> if you I<really> want
1487 =item B<--[no]ignore-dir=I<DIRNAME>>, B<--[no]ignore-directory=I<DIRNAME>>
1489 Ignore directory (as CVS, .svn, etc are ignored). May be used
1490 multiple times to ignore multiple directories. For example, mason
1491 users may wish to include B<--ignore-dir=data>. The B<--noignore-dir>
1492 option allows users to search directories which would normally be
1493 ignored (perhaps to research the contents of F<.svn/props> directories).
1495 The I<DIRNAME> must always be a simple directory name. Nested
1496 directories like F<foo/bar> are NOT supported. You would need to
1497 specify B<--ignore-dir=foo> and then no files from any foo directory
1498 are taken into account by ack unless given explicitly on the command
1501 =item B<--ignore-file=I<FILTER:ARGS>>
1503 Ignore files matching I<FILTER:ARGS>. The filters are specified
1504 identically to file type filters as seen in L</"Defining your own types">.
1506 =item B<-k>, B<--known-types>
1508 Limit selected files to those with types that ack knows about.
1510 =item B<-l>, B<--files-with-matches>
1512 Only print the filenames of matching files, instead of the matching text.
1514 =item B<-L>, B<--files-without-matches>
1516 Only print the filenames of files that do I<NOT> match.
1518 =item B<--match I<PATTERN>>
1520 Specify the I<PATTERN> explicitly. This is helpful if you don't want to put the
1521 regex as your first argument, e.g. when executing multiple searches over the
1524 # search for foo and bar in given files
1525 ack file1 t/file* --match foo
1526 ack file1 t/file* --match bar
1528 =item B<-m=I<NUM>>, B<--max-count=I<NUM>>
1530 Print only I<NUM> matches out of each file. If you want to stop ack
1531 after printing the first match of any kind, use the B<-1> options.
1535 Print this manual page.
1537 =item B<-n>, B<--no-recurse>
1539 No descending into subdirectories.
1543 Show only the part of each line matching PATTERN (turns off text
1544 highlighting). This is exactly the same as C<--output=$&>.
1546 =item B<--output=I<expr>>
1548 Output the evaluation of I<expr> for each line (turns off text
1549 highlighting). If PATTERN matches more than once then a line is
1550 output for each non-overlapping match.
1552 I<expr> may contain the strings "\n", "\r" and "\t", which will be
1553 expanded to their corresponding characters line feed, carriage return
1554 and tab, respectively.
1556 I<expr> may also contain the following Perl special variables:
1560 =item C<$1> through C<$9>
1562 The subpattern from the corresponding set of capturing parentheses.
1563 If your pattern is C<(.+) and (.+)>, and the string is "this and
1564 that', then C<$1> is "this" and C<$2> is "that".
1568 The contents of the line in the file.
1572 The number of the line in the file.
1574 =item C<$&>, C<$`> and C<$'>
1576 C<$&> is the the string matched by the pattern, C<$`> is what
1577 precedes the match, and C<$'> is what follows it. If the pattern
1578 is C<gra(ph|nd)> and the string is "lexicographic", then C<$&> is
1579 "graph", C<$`> is "lexico" and C<$'> is "ic".
1581 Use of these variables in your output will slow down the pattern
1586 The match made by the last parentheses that matched in the pattern.
1587 For example, if your pattern is C<Version: (.+)|Revision: (.+)>,
1588 then C<$+> will contain whichever set of parentheses matched.
1592 C<$f> is available, in C<--output> only, to insert the filename.
1593 This is a stand-in for the discovered C<$filename> usage in old C<< ack2 --output >>,
1594 which is disallowed with C<ack3> improved security.
1596 The intended usage is to provide the grep or compile-error syntax needed for editor/IDE go-to-line integration,
1597 e.g. C<--output=$f:$.:$_> or C<--output=$f\t$.\t$&>
1601 =item B<--pager=I<program>>, B<--nopager>
1603 B<--pager> directs ack's output through I<program>. This can also be specified
1604 via the C<ACK_PAGER> and C<ACK_PAGER_COLOR> environment variables.
1606 Using --pager does not suppress grouping and coloring like piping
1607 output on the command-line does.
1609 B<--nopager> cancels any setting in F<~/.ackrc>, C<ACK_PAGER> or C<ACK_PAGER_COLOR>.
1610 No output will be sent through a pager.
1614 Prints all lines, whether or not they match the expression. Highlighting
1615 will still work, though, so it can be used to highlight matches while
1616 still seeing the entire file, as in:
1618 # Watch a log file, and highlight a certain IP address.
1619 $ tail -f ~/access.log | ack --passthru 123.45.67.89
1623 Only works in conjunction with B<-f>, B<-g>, B<-l> or B<-c>, options
1624 that only list filenames. The filenames are output separated with a
1625 null byte instead of the usual newline. This is helpful when dealing
1626 with filenames that contain whitespace, e.g.
1628 # Remove all files of type HTML.
1629 ack -f --html --print0 | xargs -0 rm -f
1631 =item B<-p[N]>, B<--proximate[=N]>
1633 Groups together match lines that are within N lines of each other.
1634 This is useful for visually picking out matches that appear close
1637 For example, if you got these results without the C<--proximate> option,
1644 they would look like this with C<--proximate=1>
1653 and this with C<--proximate=3>.
1661 If N is omitted, N is set to 1.
1665 Negates the effect of the B<--proximate> option. Shortcut for B<--proximate=0>.
1667 =item B<-Q>, B<--literal>
1669 Quote all metacharacters in PATTERN, it is treated as a literal.
1671 =item B<-r>, B<-R>, B<--recurse>
1673 Recurse into sub-directories. This is the default and just here for
1674 compatibility with grep. You can also use it for turning B<--no-recurse> off.
1676 =item B<--range-start=PATTERN>, B<--range-end=PATTERN>
1678 Specifies patterns that mark the start and end of a range. See
1679 L<MATCHING IN A RANGE OF LINES> for details.
1683 Suppress error messages about nonexistent or unreadable files. This is taken
1686 =item B<-S>, B<--[no]smart-case>, B<--no-smart-case>
1688 Ignore case in the search strings if PATTERN contains no uppercase
1689 characters. This is similar to C<smartcase> in the vim text editor.
1690 The options overrides B<-i> and B<-I>.
1692 B<-S> is a synonym for B<--smart-case>.
1694 B<-i> always overrides this option.
1696 =item B<--sort-files>
1698 Sorts the found files lexicographically. Use this if you want your file
1699 listings to be deterministic between runs of I<ack>.
1701 =item B<--show-types>
1703 Outputs the filetypes that ack associates with each file.
1705 Works with B<-f> and B<-g> options.
1707 =item B<-t TYPE>, B<--type=TYPE>, B<--TYPE>
1709 Specify the types of files to include in the search.
1710 TYPE is a filetype, like I<perl> or I<xml>. B<--type=perl> can
1711 also be specified as B<--perl>, although this is deprecated.
1713 Type inclusions can be repeated and are ORed together.
1715 See I<ack --help-types> for a list of valid types.
1717 =item B<-T TYPE>, B<--type=noTYPE>, B<--noTYPE>
1719 Specifies the type of files to exclude from the search. B<--type=noperl>
1720 can be done as B<--noperl>, although this is deprecated.
1722 If a file is of both type "foo" and "bar", specifying both B<--type=foo>
1723 and B<--type=nobar> will exclude the file, because an exclusion takes
1724 precedence over an inclusion.
1726 =item B<--type-add I<TYPE>:I<FILTER>:I<ARGS>>
1728 Files with the given ARGS applied to the given FILTER
1729 are recognized as being of (the existing) type TYPE.
1730 See also L</"Defining your own types">.
1732 =item B<--type-set I<TYPE>:I<FILTER>:I<ARGS>>
1734 Files with the given ARGS applied to the given FILTER are recognized as
1735 being of type TYPE. This replaces an existing definition for type TYPE. See
1736 also L</"Defining your own types">.
1738 =item B<--type-del I<TYPE>>
1740 The filters associated with TYPE are removed from Ack, and are no longer considered
1743 =item B<--[no]underline>
1745 Turns on underlining of matches, where "underlining" is printing a line of
1746 carets under the match.
1750 17: Come kick the football you fool
1752 623: Price per square foot
1755 This is useful if you're dumping the results of an ack run into a text
1756 file or printer that doesn't support ANSI color codes.
1758 The setting of underline does not affect highlighting of matches.
1760 =item B<-v>, B<--invert-match>
1762 Invert match: select non-matching lines.
1766 Display version and copyright information.
1768 =item B<-w>, B<--word-regexp>
1770 Force PATTERN to match only whole words.
1774 An abbreviation for B<--files-from=->. The list of files to search are read
1775 from standard input, with one line per file.
1777 Note that the list of files is B<not> filtered in any way. If you add
1778 C<--type=html> in addition to C<-x>, the C<--type> will be ignored.
1782 Stops after reporting first match of any kind. This is different
1783 from B<--max-count=1> or B<-m1>, where only one match per file is
1784 shown. Also, B<-1> works with B<-f> and B<-g>, where B<-m> does
1789 Display the all-important Bill The Cat logo. Note that the exact
1790 spelling of B<--thpppppt> is not important. It's checked against
1791 a regular expression.
1795 Check with the admiral for traps.
1799 Chocolate, Chocolate, Chocolate!
1803 =head1 THE .ackrc FILE
1805 The F<.ackrc> file contains command-line options that are prepended
1806 to the command line before processing. Multiple options may live
1807 on multiple lines. Lines beginning with a # are ignored. A F<.ackrc>
1808 might look like this:
1810 # Always sort the files
1813 # Always color, even if piping to another program
1816 # Use "less -r" as my pager
1819 Note that arguments with spaces in them do not need to be quoted,
1820 as they are not interpreted by the shell. Basically, each I<line>
1821 in the F<.ackrc> file is interpreted as one element of C<@ARGV>.
1823 F<ack> looks in several locations for F<.ackrc> files; the searching
1824 process is detailed in L</"ACKRC LOCATION SEMANTICS">. These
1825 files are not considered if B<--noenv> is specified on the command line.
1827 =head1 Defining your own types
1829 ack allows you to define your own types in addition to the predefined
1830 types. This is done with command line options that are best put into
1831 an F<.ackrc> file - then you do not have to define your types over and
1832 over again. In the following examples the options will always be shown
1833 on one command line so that they can be easily copy & pasted.
1835 File types can be specified both with the the I<--type=xxx> option,
1836 or the file type as an option itself. For example, if you create
1837 a filetype of "cobol", you can specify I<--type=cobol> or simply
1838 I<--cobol>. File types must be at least two characters long. This
1839 is why the C language is I<--cc> and the R language is I<--rr>.
1841 I<ack --perl foo> searches for foo in all perl files. I<ack --help-types>
1842 tells you, that perl files are files ending
1843 in .pl, .pm, .pod or .t. So what if you would like to include .xs
1844 files as well when searching for --perl files? I<ack --type-add perl:ext:xs --perl foo>
1845 does this for you. B<--type-add> appends
1846 additional extensions to an existing type.
1848 If you want to define a new type, or completely redefine an existing
1849 type, then use B<--type-set>. I<ack --type-set eiffel:ext:e,eiffel> defines
1850 the type I<eiffel> to include files with
1851 the extensions .e or .eiffel. So to search for all eiffel files
1852 containing the word Bertrand use I<ack --type-set eiffel:ext:e,eiffel --eiffel Bertrand>.
1853 As usual, you can also write B<--type=eiffel>
1854 instead of B<--eiffel>. Negation also works, so B<--noeiffel> excludes
1855 all eiffel files from a search. Redefining also works: I<ack --type-set cc:ext:c,h>
1856 and I<.xs> files no longer belong to the type I<cc>.
1858 When defining your own types in the F<.ackrc> file you have to use
1861 --type-set=eiffel:ext:e,eiffel
1863 or writing on separate lines
1868 The following does B<NOT> work in the F<.ackrc> file:
1870 --type-set eiffel:ext:e,eiffel
1872 In order to see all currently defined types, use I<--help-types>, e.g.
1873 I<ack --type-set backup:ext:bak --type-add perl:ext:perl --help-types>
1875 In addition to filtering based on extension, ack offers additional
1876 filter types. The generic syntax is
1877 I<--type-set TYPE:FILTER:ARGS>; I<ARGS> depends on the value
1882 =item is:I<FILENAME>
1884 I<is> filters match the target filename exactly. It takes exactly one
1885 argument, which is the name of the file to match.
1889 --type-set make:is:Makefile
1891 =item ext:I<EXTENSION>[,I<EXTENSION2>[,...]]
1893 I<ext> filters match the extension of the target file against a list
1894 of extensions. No leading dot is needed for the extensions.
1898 --type-set perl:ext:pl,pm,t
1900 =item match:I<PATTERN>
1902 I<match> filters match the target filename against a regular expression.
1903 The regular expression is made case-insensitive for the search.
1907 --type-set make:match:/(gnu)?makefile/
1909 =item firstlinematch:I<PATTERN>
1911 I<firstlinematch> matches the first line of the target file against a
1912 regular expression. Like I<match>, the regular expression is made
1917 --type-add perl:firstlinematch:/perl/
1923 ack allows customization of the colors it uses when presenting matches
1924 onscreen. It uses the colors available in Perl's L<Term::ANSIColor>
1925 module, which provides the following listed values. Note that case does not
1926 matter when using these values.
1928 There are four different colors ack uses:
1930 Aspect Option Env. variable Default
1931 -------- ----------------- ------------------ ---------------
1932 filename --color-filename ACK_COLOR_FILENAME black on_yellow
1933 match --color-match ACK_COLOR_MATCH bold green
1934 line no. --color-lineno ACK COLOR_LINENO bold yellow
1935 column no. --color-colno ACK COLOR_COLNO bold yellow
1937 The column number column is only used if the column number is shown because
1938 of the --column option.
1940 Colors may be specified by command-line option, such as
1941 C<ack --color-filename='red on_white'>, or by setting an environment
1942 variable, such as C<ACK_COLOR_FILENAME='red on_white'>. Options for colors
1943 can be set in your ACKRC file (See "THE .ackrc FILE").
1945 ack can understand the following colors for the foreground:
1947 black red green yellow blue magenta cyan white
1949 The optional background color is specified by prepending "on_" to one of
1950 the foreground colors:
1952 on_black on_red on_green on_yellow on_blue on_magenta on_cyan on_white
1954 Each of the foreground colors can be modified with the following
1955 attributes, which may or may not be supported by your terminal:
1957 bold faint italic underline blink reverse concealed
1959 Any combinations of modifiers can be added to the foreground color. If your
1960 terminal supports it, and you enjoy visual punishment, you can specify:
1962 ack --color-filename="blink italic underline bold red on_yellow"
1964 For charts of the colors and what they look like, run C<ack --help-colors>
1965 and C<ack --help-rgb-colors>.
1967 If the eight standard colors, in their bold, faint and unmodified states,
1968 aren't enough for you to choose from, you can also specify colors by their
1969 RGB values. They are specified as "rgbXYZ" where X, Y, and Z are values
1970 between 0 and 5 giving the intensity of red, green and blue, respectively.
1971 Therefore, "rgb500" is pure red, "rgb505" is purple, and so on.
1973 Background colors can be specified with the "on_" prefix prepended on an
1974 RGB color, so that "on_rgb505" would be a purple background.
1976 The modifier attributes of blink, italic, underscore and so on may or may
1977 not work on the RGB colors.
1979 For a chart of the 216 possible RGB colors, run C<ack --help-rgb-colors>.
1981 =head1 ENVIRONMENT VARIABLES
1983 For commonly-used ack options, environment variables can make life
1984 much easier. These variables are ignored if B<--noenv> is specified
1985 on the command line.
1991 Specifies the location of the user's F<.ackrc> file. If this file doesn't
1992 exist, F<ack> looks in the default location.
1994 =item ACK_COLOR_COLNO
1996 Color specification for the column number in ack's output. By default, the
1997 column number is not shown. You have to enable it with the B<--column>
1998 option. See the section "ack Colors" above.
2000 =item ACK_COLOR_FILENAME
2002 Color specification for the filename in ack's output. See the section "ack
2005 =item ACK_COLOR_LINENO
2007 Color specification for the line number in ack's output. See the section
2010 =item ACK_COLOR_MATCH
2012 Color specification for the matched text in ack's output. See the section
2017 Specifies a pager program, such as C<more>, C<less> or C<most>, to which
2018 ack will send its output.
2020 Using C<ACK_PAGER> does not suppress grouping and coloring like
2021 piping output on the command-line does, except that on Windows
2022 ack will assume that C<ACK_PAGER> does not support color.
2024 C<ACK_PAGER_COLOR> overrides C<ACK_PAGER> if both are specified.
2026 =item ACK_PAGER_COLOR
2028 Specifies a pager program that understands ANSI color sequences.
2029 Using C<ACK_PAGER_COLOR> does not suppress grouping and coloring
2030 like piping output on the command-line does.
2032 If you are not on Windows, you never need to use C<ACK_PAGER_COLOR>.
2036 =head1 ACK & OTHER TOOLS
2038 =head2 Simple vim integration
2040 F<ack> integrates easily with the Vim text editor. Set this in your
2041 F<.vimrc> to use F<ack> instead of F<grep>:
2045 That example uses C<-k> to search through only files of the types ack
2046 knows about, but you may use other default flags. Now you can search
2047 with F<ack> and easily step through the results in Vim:
2049 :grep Dumper perllib
2051 =head2 Editor integration
2053 Many users have integrated ack into their preferred text editors.
2054 For details and links, see L<https://beyondgrep.com/more-tools/>.
2056 =head2 Shell and Return Code
2058 For greater compatibility with I<grep>, I<ack> in normal use returns
2059 shell return or exit code of 0 only if something is found and 1 if
2062 (Shell exit code 1 is C<$?=256> in perl with C<system> or backticks.)
2064 The I<grep> code 2 for errors is not used.
2066 If C<-f> or C<-g> are specified, then 0 is returned if at least one
2067 file is found. If no files are found, then 1 is returned.
2071 =head1 DEBUGGING ACK PROBLEMS
2073 If ack gives you output you're not expecting, start with a few simple steps.
2075 =head2 Try it with B<--noenv>
2077 Your environment variables and F<.ackrc> may be doing things you're
2078 not expecting, or forgotten you specified. Use B<--noenv> to ignore
2079 your environment and F<.ackrc>.
2081 =head2 Use B<-f> to see what files have been selected for searching
2083 Ack's B<-f> was originally added as a debugging tool. If ack is
2084 not finding matches you think it should find, run F<ack -f> to see
2085 what files have been selected. You can also add the C<--show-types>
2086 options to show the type of each file selected.
2088 =head2 Use B<--dump>
2090 This lists the ackrc files that are loaded and the options loaded
2091 from them. You may be loading an F<.ackrc> file that you didn't know
2094 =head1 ACKRC LOCATION SEMANTICS
2096 Ack can load its configuration from many sources. The following list
2097 specifies the sources Ack looks for configuration files; each one
2098 that is found is loaded in the order specified here, and
2099 each one overrides options set in any of the sources preceding
2100 it. (For example, if I set --sort-files in my user ackrc, and
2101 --nosort-files on the command line, the command line takes
2108 Defaults are loaded from App::Ack::ConfigDefaults. This can be omitted
2109 using C<--ignore-ack-defaults>.
2111 =item * Global ackrc
2113 Options are then loaded from the global ackrc. This is located at
2114 C</etc/ackrc> on Unix-like systems.
2116 Under Windows XP and earlier, the global ackrc is at
2117 C<C:\Documents and Settings\All Users\Application Data\ackrc>
2119 Under Windows Vista/7, the global ackrc is at
2120 C<C:\ProgramData\ackrc>
2122 The C<--noenv> option prevents all ackrc files from being loaded.
2126 Options are then loaded from the user's ackrc. This is located at
2127 C<$HOME/.ackrc> on Unix-like systems.
2129 Under Windows XP and earlier, the user's ackrc is at
2130 C<C:\Documents and Settings\$USER\Application Data\ackrc>.
2132 Under Windows Vista/7, the user's ackrc is at
2133 C<C:\Users\$USER\AppData\Roaming\ackrc>.
2135 If you want to load a different user-level ackrc, it may be specified
2136 with the C<$ACKRC> environment variable.
2138 The C<--noenv> option prevents all ackrc files from being loaded.
2140 =item * Project ackrc
2142 Options are then loaded from the project ackrc. The project ackrc is
2143 the first ackrc file with the name C<.ackrc> or C<_ackrc>, first searching
2144 in the current directory, then the parent directory, then the grandparent
2145 directory, etc. This can be omitted using C<--noenv>.
2149 The C<--ackrc> option may be included on the command line to specify an
2150 ackrc file that can override all others. It is consulted even if C<--noenv>
2153 =item * Command line
2155 Options are then loaded from the command line.
2159 =head1 BUGS & ENHANCEMENTS
2161 ack is based at GitHub at L<https://github.com/beyondgrep/ack3>
2163 Please report any bugs or feature requests to the issues list at
2164 Github: L<https://github.com/beyondgrep/ack3/issues>.
2166 Please include the operating system that you're using; the output of
2167 the command C<ack --version>; and any customizations in your F<.ackrc>
2170 To suggest enhancements, please submit an issue at
2171 L<https://github.com/beyondgrep/ack3/issues>. Also read the
2172 F<DEVELOPERS.md> file in the ack code repository.
2174 Also, feel free to discuss your issues on the ack mailing
2175 list at L<https://groups.google.com/group/ack-users>.
2179 Support for and information about F<ack> can be found at:
2183 =item * The ack homepage
2185 L<https://beyondgrep.com/>
2187 =item * Source repository
2189 L<https://github.com/beyondgrep/ack3>
2191 =item * The ack issues list at Github
2193 L<https://github.com/beyondgrep/ack3/issues>
2195 =item * The ack announcements mailing list
2197 L<https://groups.google.com/group/ack-announcement>
2199 =item * The ack users' mailing list
2201 L<https://groups.google.com/group/ack-users>
2203 =item * The ack development mailing list
2205 L<https://groups.google.com/group/ack-users>
2211 There are ack mailing lists and a Slack channel for ack. See
2212 L<https://beyondgrep.com/community/> for details.
2216 This is the Frequently Asked Questions list for ack.
2218 =head2 Can I stop using grep now?
2220 Many people find I<ack> to be better than I<grep> as an everyday tool
2221 99% of the time, but don't throw I<grep> away, because there are times
2222 you'll still need it. For example, you might be looking through huge
2223 log files and not using regular expressions. In that case, I<grep>
2224 will probably perform better.
2226 =head2 Why isn't ack finding a match in (some file)?
2228 First, take a look and see if ack is even looking at the file. ack is
2229 intelligent in what files it will search and which ones it won't, but
2230 sometimes that can be surprising.
2232 Use the C<-f> switch, with no regex, to see a list of files that ack
2233 will search for you. If your file doesn't show up in the list of files
2234 that C<ack -f> shows, then ack never looks in it.
2236 =head2 Wouldn't it be great if F<ack> did search & replace?
2238 No, ack will always be read-only. Perl has a perfectly good way
2239 to do search & replace in files, using the C<-i>, C<-p> and C<-n>
2242 You can certainly use ack to select your files to update. For
2243 example, to change all "foo" to "bar" in all PHP files, you can do
2244 this from the Unix shell:
2246 $ perl -i -p -e's/foo/bar/g' $(ack -f --php)
2248 =head2 Can I make ack recognize F<.xyz> files?
2250 Yes! Please see L</"Defining your own types"> in the ack manual.
2252 =head2 Will you make ack recognize F<.xyz> files by default?
2254 We might, depending on how widely-used the file format is.
2256 Submit an issue at in the GitHub issue queue at
2257 L<https://github.com/beyondgrep/ack3/issues>. Explain what the file format
2258 is, where we can find out more about it, and what you have been using
2259 in your F<.ackrc> to support it.
2261 Please do not bother creating a pull request. The code for filetypes
2262 is trivial compared to the rest of the process we go through.
2264 =head2 Why is it called ack if it's called ack-grep?
2266 The name of the program is "ack". Some packagers have called it
2267 "ack-grep" when creating packages because there's already a package
2268 out there called "ack" that has nothing to do with this ack.
2270 I suggest you make a symlink named F<ack> that points to F<ack-grep>
2271 because one of the crucial benefits of ack is having a name that's
2272 so short and simple to type.
2274 To do that, run this with F<sudo> or as root:
2276 ln -s /usr/bin/ack-grep /usr/bin/ack
2278 Alternatively, you could use a shell alias:
2286 =head2 What does F<ack> mean?
2288 Nothing. I wanted a name that was easy to type and that you could
2289 pronounce as a single syllable.
2291 =head2 Can I do multi-line regexes?
2293 No, ack does not support regexes that match multiple lines. Doing
2294 so would require reading in the entire file at a time.
2296 If you want to see lines near your match, use the C<--A>, C<--B>
2297 and C<--C> switches for displaying context.
2299 =head2 Why is ack telling me I have an invalid option when searching for C<+foo>?
2301 ack treats command line options beginning with C<+> or C<-> as options; if you
2302 would like to search for these, you may prefix your search term with C<--> or
2303 use the C<--match> option. (However, don't forget that C<+> is a regular
2304 expression metacharacter!)
2306 =head2 Why does C<"ack '.{40000,}'"> fail? Isn't that a valid regex?
2308 The Perl language limits the repetition quantifier to 32K. You
2309 can search for C<.{32767}> but not C<.{32768}>.
2311 =head2 Ack does "X" and shouldn't, should it?
2313 We try to remain as close to grep's behavior as possible, so when in
2314 doubt, see what grep does! If there's a mismatch in functionality there,
2315 please submit an issue to GitHub, and/or bring it up on the ack-users
2320 =head1 ACKNOWLEDGEMENTS
2322 How appropriate to have I<ack>nowledgements!
2324 Thanks to everyone who has contributed to ack in any way, including
2341 SE<eacute>bastien FeugE<egrave>re,
2348 RaE<uacute>l GundE<iacute>n,
2354 RaE<aacute>l GundE<aacute>n,
2390 Eric Van Dewoestine,
2399 Christopher J. Madsen,
2411 GE<aacute>bor SzabE<oacute>,
2414 E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason,
2418 Mark Leighton Fisher,
2424 Nilson Santos F. Jr,
2429 Ask BjE<oslash>rn Hansen,
2433 Slaven ReziE<0x107>,
2445 Andy Lester, C<< <andy at petdance.com> >>
2447 =head1 COPYRIGHT & LICENSE
2449 Copyright 2005-2020 Andy Lester.
2451 This program is free software; you can redistribute it and/or modify
2452 it under the terms of the Artistic License v2.0.
2454 See https://www.perlfoundation.org/artistic-license-20.html or the LICENSE.md
2455 file that comes with the ack distribution.
2469 $VERSION = 'v3.4.0'; # Check https://beyondgrep.com/ for updates
2470 $COPYRIGHT = 'Copyright 2005-2020 Andy Lester.';
2472 our $STANDALONE = 0;
2473 our $ORIGINAL_PROGRAM_NAME;
2487 our $is_filter_mode;
2488 our $output_to_pipe;
2492 our $debug_nopens = 0;
2494 # Line ending, changes to "\0" if --print0.
2498 # These have to be checked before any filehandle diddling.
2499 $output_to_pipe = not -t
*STDOUT
;
2500 $is_filter_mode = -p STDIN
;
2502 $is_windows = ($^O eq 'MSWin32');
2507 return CORE
::warn( _my_program
(), ': ', @_, "\n" );
2512 return CORE
::die( _my_program
(), ': ', @_, "\n" );
2516 require File
::Basename
;
2517 return File
::Basename
::basename
( $0 );
2522 my $y = q{_ /|,\\'!.x',=(www)=, U };
2523 $y =~ tr/,x!w/\nOo_/;
2525 App
::Ack
::print( "$y ack $_[0]!\n" );
2533 3~!I#7#I"7#I!?!+!="+"="+!:!
2534 2?#I!7!I!?#I!7!I"+"=%+"=#
2535 1?"+!?*+!=#~"=!+#?"="+!
2536 0?"+!?"I"?&+!="~!=!~"=!+%="+"
2537 /I!+!?)+!?!+!=$~!=!~!="+!="+"?!="?!
2539 ,,!?%I"?(+$=$~!=#:"~$:!~!
2540 ,I!?!I!?"I"?!+#?"+!?!+#="~$:!~!:!~!:!,!:!,":#~!
2541 +I!?&+!="+!?#+$=!~":!~!:!~!:!,!:#,!:!,%:"
2542 *+!I!?!+$=!+!=!+!?$+#=!~":!~":#,$:",#:!,!:!
2543 *I!?"+!?!+!=$+!?#+#=#~":$,!:",!:!,&:"
2544 )I!?$=!~!=#+"?!+!=!+!=!~!="~!:!~":!,'.!,%:!~!
2545 (=!?"+!?!=!~$?"+!?!+!=#~"=",!="~$,$.",#.!:!=!
2546 (I"+"="~"=!+&=!~"=!~!,!~!+!=!?!+!?!=!I!?!+"=!.",!.!,":!
2547 %I$?!+!?!=%+!~!+#~!=!~#:#=!~!+!~!=#:!,%.!,!.!:"
2548 $I!?!=!?!I!+!?"+!=!~!=!~!?!I!?!=!+!=!~#:",!~"=!~!:"~!=!:",&:" '-/
2549 $?!+!I!?"+"=!+"~!,!:"+#~#:#,"=!~"=!,!~!,!.",!:".!:! */! !I!t!'!s! !a! !g!r!e!p!!! !/!
2550 $+"=!+!?!+"~!=!:!~!:"I!+!,!~!=!:!~!,!:!,$:!~".&:"~!,# (-/
2551 %~!=!~!=!:!.!+"~!:!,!.!,!~!=!:$.!,":!,!.!:!~!,!:!=!.#="~!,!:" ./!
2552 %=!~!?!+"?"+!=!~",!.!:!?!~!.!:!,!:!,#.!,!:","~!:!=!~!=!:",!~! ./!
2553 %+"~":!~!=#~!:!~!,!.!~!:",!~!=!~!.!:!,!.",!:!,":!=":!.!,!:!7! -/!
2554 %~",!:".#:!=!:!,!:"+!:!~!:!.!,!~!,!.#,!.!,$:"~!,":"~!=! */!
2555 &=!~!=#+!=!~",!.!:",#:#,!.",+:!,!.",!=!+!?!
2556 &~!=!~!=!~!:"~#:",!.!,#~!:!.!+!,!.",$.",$.#,!+!I!?!
2557 &~!="~!:!~":!~",!~!=!~":!,!:!~!,!:!,&.$,#."+!?!I!?!I!
2558 &~!=!~!=!+!,!:!~!:!=!,!:!~&:$,!.!,".!,".!,#."~!+!?$I!
2559 &~!=!~!="~!=!:!~":!,!~%:#,!:",!.!,#.",#I!7"I!?!+!?"I"
2560 &+!I!7!:#~"=!~!:!,!:"~$.!=!.!,!~!,$.#,!~!7!I#?!+!?"I"7!
2561 %7#?!+!~!:!=!~!=!~":!,!:"~":#.!,)7#I"?"I!7&
2562 %7#I!=":!=!~!:"~$:"~!:#,!:!,!:!~!:#,!7#I!?#7)
2563 $7$+!,!~!=#~!:!~!:!~$:#,!.!~!:!=!,":!7#I"?#7+=!?!
2564 $7#I!~!,!~#=!~!:"~!:!,!:!,#:!=!~",":!7$I!?#I!7*+!=!+"
2565 "I!7$I!,":!,!.!=":$,!:!,$:$7$I!+!?"I!7+?"I!7!I!7!,!
2566 !,!7%I!:",!."~":!,&.!,!:!~!I!7$I!+!?"I!7,?!I!7',!
2567 !7(,!.#~":!,%.!,!7%I!7!?#I"7,+!?!7*
2568 7+:!,!~#,"=!7'I!?#I"7/+!7+
2569 77I!+!7!?!7!I"71+!7,
2572 return _pic_decode
($x);
2578 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2579 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2580 0|! "C!H!O!C!O!L!A!T!E!!! !|!
2586 4.! $\! /M!~!.!8! +.!M# 4
2587 0,!.! (\! .~!M!N! ,+!I!.!M!.! 3
2588 /?!O!.!M!:! '\! .O!.! +~!Z!=!N!.! 4
2589 ..! !D!Z!.!Z!.! '\! 9=!M".! 6
2590 /.! !.!~!M".! '\! 8~! 9
2592 4.! &:!M! !N"M# !M"N!M! #D!M&=! =
2593 :M!7!M#:! !~!M!7!,!$!M!:! #.! !O!N!.!M!:!M# ;
2594 8Z!M"~!N!$!D!.!N!?! !I!N!.! (?!M! !M!,!D!M".! 9
2595 (?!Z!M!N!:! )=!M!O!8!.!M!+!M! !M!,! !O!M! +,!M!.!M!~!Z!N!M!:! &:!~! 0
2596 &8!7!.!~!M"D!M!,! &M!?!=!8! !M!,!O! !M!+! !+!O!.!M! $M#~! !.!8!M!Z!.!M! !O!M"Z! %:!~!M!Z!M!Z!.! +
2597 &:!M!7!,! *M!.!Z!M! !8"M!.!M!~! !.!M!.!=! #~!8!.!M! !7!M! "N!Z#I! !D!M!,!M!.! $."M!,! !M!.! *
2598 2$!O! "N! !.!M!I! !7" "M! "+!O! !~!M! !d!O!.!7!I!M!.! !.!O!=!M!.! !M",!M!.! %.!$!O!D! +
2599 1~!O! "M!+! !8!$! "M! "?!O! %Z!8!D!M!?!8!I!O!7!M! #M!.!M! "M",!M! 4
2600 07!~! ".!8! !.!M! "I!+! !.!M! &Z!D!.!7!=!M! !:!.!M! #:!8"+! !.!+!8! !8! 3
2601 /~!M! #N! !~!M!$! !.!M! !.!M" &~!M! "~!M!O! "D! $M! !8! "M!,!M!+!D!.! 1
2602 #.! #?!M!N!.! #~!O! $M!.!7!$! "?" !?!~!M! '7!8!?!M!.!+!M"O! $?"$!D! !.!O! !$!7!I!.! 0
2603 $,!M!:!O!?! ".! !?!=! $=!:!O! !M! "M! !M! !+!$! (.! +.!M! !M!.! !8! !+"Z!~! $:!M!$! !.! '
2604 #.!8!.!I!$! $7!I! %M" !=!M! !~!M!D! "7!I! .I!O! %?!=!,!D! !,!M! !D!~!8!~! %D!M! (
2605 #.!M"?! $=!O! %=!N! "8!.! !Z!M! #M!~! (M!:! #.!M" &O! !M!.! !?!,! !8!.!N!~! $8!N!M!,!.! %
2606 *$!O! &M!,! "O! !.!M!.! #M! (~!M( &O!.! !7! "M! !.!M!.!M!,! #.!M! !M! &
2607 )=!8!.! $.!M!O!.! "$!.!I!N! !I!M# (7!M(I! %D"Z!M! "=!I! "M! !M!:! #~!D! '
2608 )D! &8!N!:! ".!O! !M!="M! "M! (7!M) %." !M!D!."M!.! !$!=! !M!,! +
2609 (M! &+!.!M! #Z!7!O!M!.!~!8! +,!M#D!?!M#D! #.!Z!M#,!Z!?! !~!N! "N!.! !M! +
2610 'D!:! %$!D! !?! #M!Z! !8!.! !M"?!7!?!7! '+!I!D! !?!O!:!M!:! ":!M!:! !M!7".!M! "8!+! !:!D! !.!M! *
2611 %.!O!:! $.!O!+! !D!.! #M! "M!.!+!N!I!Z! "7!M!N!M!N!?!I!7!Z!=!M'D"~! #M!.!8!$! !:! !.!M! "N!?! !,!O! )
2612 !.!?!M!:!M!I! %8!,! "M!.! #M! "N! !M!.! !M!.! !+!~! !.!M!.! ':!M! $M! $M!Z!$! !M!.! "D! "M! "?!M! (
2613 !7!8! !+!I! ".! "$!=! ":!$! "+! !M!.! !O! !M!I!M".! !=!~! ",!O! '=!M! $$!,! #N!:! ":!8!.! !D!~! !,!M!.! !:!M!.! &
2614 !:!,!.! &Z" #D! !.!8!."M!.! !8!?!Z!M!.!M! #Z!~! !?!M!Z!.! %~!O!.!8!$!N!8!O!I!:!~! !+! #M!.! !.!M!.! !+!M! ".!~!M!+! $
2615 !.! 'D!I! #?!M!.!M!,! !.!Z! !.!8! #M&O!I!?! (~!I!M"." !M!Z!.! !M!N!.! "+!$!.! "M!.! !M!?!.! "8!M! $
2616 (O!8! $M! !M!.! ".!:! !+!=! #M! #.!M! !+" *$!M":!.! !M!~! "M!7! #M! #7!Z! "M"$!M!.! !.! #
2617 '$!Z! #.!7!+!M! $.!,! !+!:! #N! #.!M!.!+!M! +D!M! #=!N! ":!O! #=!M! #Z!D! $M!I! %
2618 $,! ".! $.!M" %$!.! !?!~! "+!7!." !.!M!,! !M! *,!N!M!.$M!?! "D!,! #M!.! #N! +
2619 ,M!Z! &M! "I!,! "M! %I!M! !?!=!.! (Z!8!M! $:!M!.! !,!M! $D! #.!M!.! )
2620 +8!O! &.!8! "I!,! !~!M! &N!M! !M!D! '?!N!O!." $?!7! "?!~! #M!.! #I!D!.! (
2621 3M!,! "N!.! !D" &.!+!M!.! !M":!.":!M!7!M!D! 'M!.! "M!.! "M!,! $I! )
2622 3I! #M! "M!,! !:! &.!M" ".!,! !.!$!M!I! #.! !:! !.!M!?! "N!+! ".! /
2623 1M!,! #.!M!8!M!=!.! +~!N"O!Z"~! *+!M!.! "M! 2
2624 0.!M! &M!.! 8:! %.!M!Z! "M!=! *O!,! %
2625 0?!$! &N! )." .,! %."M! ":!M!.! 0
2626 0N!:! %?!O! #.! ..! &,! &.!D!,! "N!I! 0
2628 return _pic_decode
($x);
2632 my($compressed) = @_;
2633 $compressed =~ s/(.)(.)/$1x(ord($2)-32)/eg;
2634 App
::Ack
::print( $compressed );
2640 App
::Ack
::print( <<"END_OF_HELP" );
2641 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2643 Search for PATTERN in each source file in the tree from the current
2644 directory on down. If any files or directories are specified, then
2645 only those files and directories are checked. ack may also search
2646 STDIN, but only if no file or directory arguments are specified,
2647 or if one of them is "-".
2649 Default switches may be specified in an .ackrc file. If you want no dependency
2650 on the environment, turn it off with --noenv.
2652 File select actions:
2653 -f Only print the files selected, without
2654 searching. The PATTERN must not be specified.
2655 -g Same as -f, but only select files matching
2658 File listing actions:
2659 -l, --files-with-matches Print filenames with at least one match
2660 -L, --files-without-matches Print filenames with no matches
2661 -c, --count Print filenames and count of matching lines
2664 -i, --ignore-case Ignore case distinctions in PATTERN
2665 -S, --[no]smart-case Ignore case distinctions in PATTERN,
2666 only if PATTERN contains no upper case.
2667 Ignored if -i or -I are specified.
2668 -I, --no-ignore-case Turns on case-sensitivity in PATTERN.
2669 Negates -i and --smart-case.
2670 -v, --invert-match Invert match: select non-matching lines
2671 -w, --word-regexp Force PATTERN to match only whole words
2672 -Q, --literal Quote all metacharacters; PATTERN is literal
2673 --range-start PATTERN Specify PATTERN as the start of a match range.
2674 --range-end PATTERN Specify PATTERN as the end of a match range.
2675 --match PATTERN Specify PATTERN explicitly. Typically omitted.
2678 --output=expr Output the evaluation of expr for each line
2679 (turns off text highlighting)
2680 -o Show only the part of a line matching PATTERN
2681 Same as --output='\$&'
2682 --passthru Print all lines, whether matching or not
2683 -m, --max-count=NUM Stop searching in each file after NUM matches
2684 -1 Stop searching after one match of any kind
2685 -H, --with-filename Print the filename for each match (default:
2686 on unless explicitly searching a single file)
2687 -h, --no-filename Suppress the prefixing filename on output
2688 --[no]column Show the column number of the first match
2690 -A NUM, --after-context=NUM Print NUM lines of trailing context after
2692 -B NUM, --before-context=NUM Print NUM lines of leading context before
2694 -C [NUM], --context[=NUM] Print NUM lines (default 2) of output context.
2696 --print0 Print null byte as separator between filenames,
2697 only works with -f, -g, -l, -L or -c.
2699 -s Suppress error messages about nonexistent or
2704 --pager=COMMAND Pipes all ack output through COMMAND. For
2705 example, --pager="less -R". Ignored if output
2707 --nopager Do not send output through a pager. Cancels
2708 any setting in ~/.ackrc, ACK_PAGER or
2710 --[no]heading Print a filename heading above each file's
2711 results. (default: on when used interactively)
2712 --[no]break Print a break between results from different
2713 files. (default: on when used interactively)
2714 --group Same as --heading --break
2715 --nogroup Same as --noheading --nobreak
2716 -p, --proximate=LINES Separate match output with blank lines unless
2717 they are within LINES lines from each other.
2718 -P, --proximate=0 Negates --proximate.
2719 --[no]underline Print a line of carets under the matched text.
2720 --[no]color, --[no]colour Highlight the matching text (default: on unless
2721 output is redirected, or on Windows)
2722 --color-filename=COLOR
2725 --color-lineno=COLOR Set the color for filenames, matches, line and
2727 --help-colors Show a list of possible color combinations.
2728 --help-rgb-colors Show a list of advanced RGB colors.
2729 --flush Flush output immediately, even when ack is used
2730 non-interactively (when output goes to a pipe or
2735 --sort-files Sort the found files lexically.
2736 --show-types Show which types each file has.
2737 --files-from=FILE Read the list of files to search from FILE.
2738 -x Read the list of files to search from STDIN.
2740 File inclusion/exclusion:
2741 --[no]ignore-dir=name Add/remove directory from list of ignored dirs
2742 --[no]ignore-directory=name Synonym for ignore-dir
2743 --ignore-file=FILTER:ARGS Add filter for ignoring files.
2744 -r, -R, --recurse Recurse into subdirectories (default: on)
2745 -n, --no-recurse No descending into subdirectories
2746 --[no]follow Follow symlinks. Default is off.
2748 File type inclusion/exclusion:
2749 -t X, --type=X Include only X files, where X is a filetype,
2750 e.g. python, html, markdown, etc
2751 -T X, --type=noX Exclude X files, where X is a filetype.
2752 -k, --known-types Include only files of types that ack recognizes.
2753 --help-types Display all known types, and how they're defined.
2755 File type specification:
2756 --type-set=TYPE:FILTER:ARGS Files with the given ARGS applied to the given
2757 FILTER are recognized as being of type TYPE.
2758 This replaces an existing definition for TYPE.
2759 --type-add=TYPE:FILTER:ARGS Files with the given ARGS applied to the given
2760 FILTER are recognized as being type TYPE.
2761 --type-del=TYPE Removes all filters associated with TYPE.
2764 --version Display version & copyright
2765 --[no]env Ignore environment variables and global ackrc
2766 files. --env is legal but redundant.
2767 --ackrc=filename Specify an ackrc file to use
2768 --ignore-ack-defaults Ignore default definitions included with ack.
2769 --create-ackrc Outputs a default ackrc for your customization
2771 --dump Dump information on which options are loaded
2772 and where they're defined.
2773 --[no]filter Force ack to treat standard input as a pipe
2774 (--filter) or tty (--nofilter)
2776 --man Print the manual.
2777 --help-types Display all known types, and how they're defined.
2778 --help-colors Show a list of possible color combinations.
2779 --help-rgb-colors Show a list of advanced RGB colors.
2780 --thpppt Bill the Cat
2781 --bar The warning admiral
2782 --cathy Chocolate! Chocolate! Chocolate!
2784 Filter specifications:
2785 If FILTER is "ext", ARGS is a list of extensions checked against the
2787 If FILTER is "is", ARGS must match the file's name exactly.
2788 If FILTER is "match", ARGS is matched as a case-insensitive regex
2789 against the filename.
2790 If FILTER is "firstlinematch", ARGS is matched as a regex the first
2791 line of the file's contents.
2793 Exit status is 0 if match, 1 if no match.
2795 ack's home page is at https://beyondgrep.com/
2797 The full ack manual is available by running "ack --man".
2799 This is version $App::Ack::VERSION of ack. Run "ack --version" for full version info.
2807 sub show_help_types
{
2808 App
::Ack
::print( <<'END_OF_HELP' );
2809 Usage: ack [OPTION]... PATTERN [FILES OR DIRECTORIES]
2811 The following is the list of filetypes supported by ack. You can specify a
2812 filetype to include with -t TYPE or --type=TYPE. You can exclude a
2813 filetype with -T TYPE or --type=noTYPE.
2815 Note that some files may appear in multiple types. For example, a file
2816 called Rakefile is both Ruby (--type=ruby) and Rakefile (--type=rakefile).
2820 my @types = keys %App::Ack
::mappings
;
2823 $maxlen = length if $maxlen < length;
2825 for my $type ( sort @types ) {
2826 next if $type =~ /^-/; # Stuff to not show
2827 my $ext_list = $mappings{$type};
2829 if ( ref $ext_list ) {
2830 $ext_list = join( '; ', map { $_->to_string } @{$ext_list} );
2832 App
::Ack
::print( sprintf( " %-*.*s %s\n", $maxlen, $maxlen, $type, $ext_list ) );
2840 sub show_help_colors
{
2841 App
::Ack
::print( <<'END_OF_HELP' );
2842 ack allows customization of the colors it uses when presenting matches
2843 onscreen. See the "ACK COLORS" section of the ack manual (ack --man).
2845 Here is a chart of how various color combinations appear: Each of the eight
2846 foreground colors, on each of the eight background colors or no background
2847 color, with and without the bold modifier.
2849 Run ack --help-rgb-colors for a chart of the RGB colors.
2861 App
::Ack
::print( <<'END_OF_HELP' );
2862 ack allows customization of the colors it uses when presenting matches
2863 onscreen. See the "ACK COLORS" section of the ack manual (ack --man).
2865 Colors may be specified as "rggNNN" where "NNN" is a triplet of digits
2866 from 0 to 5 specifying the intensity of red, green and blue, respectively.
2868 Here is a grid of the 216 possible values for NNN.
2874 App
::Ack
::say( 'Here are the 216 possible colors with the "reverse" modifier applied.', "\n" );
2876 _show_rgb_grid
( 'reverse' );
2882 sub _show_color_grid
{
2885 my @fg_colors = qw( black red green yellow blue magenta cyan white );
2886 my @bg_colors = map { "on_$_" } @fg_colors;
2890 map { _color_cell
( $_ ) } @fg_colors
2895 map { _color_cell
( '-' x
$cell_width ) } @fg_colors
2898 for my $bg ( '', @bg_colors ) {
2901 ( map { _color_cell
( $_, "$_ $bg" ) } @fg_colors ),
2906 _color_cell
( 'bold' ),
2907 ( map { _color_cell
( $_, "bold $_ $bg" ) } @fg_colors ),
2922 $text = sprintf( '%-*s', $cell_width, $text );
2924 return ($color ? Term
::ANSIColor
::colored
( $text, $color ) : $text) . ' ';
2928 sub _show_rgb_grid
{
2929 my $modifier = shift // '';
2931 my $grid = <<'HERE';
2932 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
2933 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
2934 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
2935 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
2936 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
2937 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
2938 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
2939 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
2941 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
2943 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
2945 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
2947 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
2949 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
2950 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
2952 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
2954 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
2955 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
2956 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
2957 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
2958 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
2959 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
2962 $grid =~ s/(\d\d\d)/Term::ANSIColor::colored( "$1", "$modifier rgb$1" )/eg;
2964 App
::Ack
::say( $grid );
2972 Pod
::Usage
::pod2usage
({
2973 -input
=> $App::Ack
::ORIGINAL_PROGRAM_NAME
,
2983 sub get_version_statement
{
2986 my $copyright = $App::Ack
::COPYRIGHT
;
2987 my $this_perl = $Config::Config
{perlpath
};
2989 my $ext = $Config::Config
{_exe
};
2990 $this_perl .= $ext unless $this_perl =~ m/$ext$/i;
2992 my $perl_ver = sprintf( 'v%vd', $^V );
2994 my $build_type = $App::Ack
::STANDALONE
? 'standalone version' : 'standard build';
2996 return <<"END_OF_VERSION";
2997 ack $App::Ack::VERSION ($build_type)
2998 Running under Perl $perl_ver at $this_perl
3002 This program is free software. You may modify or distribute it
3003 under the terms of the Artistic License v2.0.
3008 sub print { print {$fh} @_; return; }
3009 sub say { print {$fh} @_, $ors; return; }
3010 sub print_blank_line
{ print {$fh} "\n"; return; }
3013 my $command = shift;
3015 return if App
::Ack
::output_to_pipe
();
3018 if ( not open( $pager, '|-', $command ) ) {
3019 App
::Ack
::die( qq{Unable to pipe to pager "$command": $!} );
3027 sub output_to_pipe
{
3028 return $output_to_pipe;
3033 my $nmatches = shift;
3035 my $rc = $nmatches ? 0 : 1;
3043 my @types = filetypes
( $file );
3044 my $arrow = @types ? ' => ' : ' =>';
3045 App
::Ack
::say( $file->name, $arrow, join( ',', @types ) );
3056 foreach my $k (keys %App::Ack
::mappings
) {
3057 my $filters = $App::Ack
::mappings
{$k};
3059 foreach my $filter (@{$filters}) {
3061 my $clone = $file->clone;
3062 if ( $filter->filter($clone) ) {
3069 # https://metacpan.org/pod/distribution/Perl-Critic/lib/Perl/Critic/Policy/Subroutines/ProhibitReturnSort.pm
3070 @matches = sort @matches;
3078 # The simplest case.
3079 return 1 if lc($pat) eq $pat;
3081 # If we have capitals, then go clean up any metacharacters that might have capitals.
3083 # Get rid of any literal backslashes first to avoid confusion.
3086 my $metacharacter = qr
/
3087 |\\A
# Beginning of string
3088 |\\B
# Not word boundary
3089 |\\c
[a-zA-Z
] # Control characters
3090 |\\D
# Non-digit character
3091 |\\G
# End-of-match position of prior match
3092 |\\H
# Not horizontal whitespace
3093 |\\K
# Keep to the left
3094 |\\N
(\
{.+?\
})? # Anything but \n, OR Unicode sequence
3095 |\\[pP
]\
{.+?\
} # Named property and negation
3096 |\\[pP
][A-Z
] # Named property and negation, single-character shorthand
3098 |\\S
# Non-space character
3099 |\\V
# Not vertical whitespace
3100 |\\W
# Non-word character
3102 |\\x
[0-9A-Fa-f
]{2} # Hex sequence
3103 |\\Z
# End of string
3105 $pat =~ s/$metacharacter//g;
3107 my $name = qr/[_A-Za-z][_A-Za-z0-9]*?/;
3108 # Eliminate named captures.
3109 $pat =~ s/\(\?'$name'//g;
3110 $pat =~ s/\(\?<$name>//g;
3112 # Eliminate named backreferences.
3113 $pat =~ s/\\k'$name'//g;
3114 $pat =~ s/\\k<$name>//g;
3115 $pat =~ s/\\k\{$name\}//g;
3117 # Now with those metacharacters and named things removed, now see if it's lowercase.
3118 return 1 if lc($pat) eq $pat;
3124 1; # End of App::Ack
3125 package App
::Ack
::ConfigDefault
;
3134 return split( /\n/, _options_block
() );
3139 return grep { /./ && !/^#/ } options
();
3143 sub _options_block
{
3144 my $lines = <<'HERE';
3145 # This is the default ackrc for ack version ==VERSION==.
3147 # There are four different ways to match
3149 # is: Match the filename exactly
3151 # ext: Match the extension of the filename exactly
3153 # match: Match the filename against a Perl regular expression
3155 # firstlinematch: Match the first 250 characters of the first line
3156 # of text against a Perl regular expression. This is only for
3157 # the --type-add option.
3160 ### Directories to ignore
3163 # https://bazaar.canonical.com/
3164 --ignore-directory=is:.bzr
3167 # http://freshmeat.sourceforge.net/projects/codeville
3168 --ignore-directory=is:.cdv
3170 # Interface Builder (Xcode)
3171 # https://en.wikipedia.org/wiki/Interface_Builder
3172 --ignore-directory=is:~.dep
3173 --ignore-directory=is:~.dot
3174 --ignore-directory=is:~.nib
3175 --ignore-directory=is:~.plst
3178 # https://git-scm.com/
3179 --ignore-directory=is:.git
3180 # When submodules are used, .git is a file.
3181 --ignore-file=is:.git
3184 # https://www.mercurial-scm.org/
3185 --ignore-directory=is:.hg
3188 # https://directory.fsf.org/wiki/Quilt
3189 --ignore-directory=is:.pc
3192 # https://subversion.apache.org/
3193 --ignore-directory=is:.svn
3196 # https://www.monotone.ca/
3197 --ignore-directory=is:_MTN
3200 # https://savannah.nongnu.org/projects/cvs
3201 --ignore-directory=is:CVS
3204 # https://www.gnu.org/software/rcs/
3205 --ignore-directory=is:RCS
3208 # https://en.wikipedia.org/wiki/Source_Code_Control_System
3209 --ignore-directory=is:SCCS
3213 --ignore-directory=is:_darcs
3216 --ignore-directory=is:_sgbak
3219 # https://www.gnu.org/software/autoconf/
3220 --ignore-directory=is:autom4te.cache
3222 # Perl module building
3223 --ignore-directory=is:blib
3224 --ignore-directory=is:_build
3226 # Perl Devel::Cover module's output directory
3227 # https://metacpan.org/release/Devel-Cover
3228 --ignore-directory=is:cover_db
3230 # Node modules created by npm
3231 --ignore-directory=is:node_modules
3234 # https://www.cmake.org/
3235 --ignore-directory=is:CMakeFiles
3237 # Eclipse workspace folder
3238 # https://eclipse.org/
3239 --ignore-directory=is:.metadata
3241 # Cabal (Haskell) sandboxes
3242 # https://www.haskell.org/cabal/users-guide/installing-packages.html
3243 --ignore-directory=is:.cabal-sandbox
3246 # https://docs.python.org/3/tutorial/modules.html
3247 --ignore-directory=is:__pycache__
3248 --ignore-directory=is:.pytest_cache
3250 # macOS Finder remnants
3251 --ignore-directory=is:__MACOSX
3252 --ignore-file=is:.DS_Store
3257 --ignore-file=ext:bak
3258 --ignore-file=match:/~$/
3261 --ignore-file=match:/^#.+#$/
3263 # vi/vim swap files https://www.vim.org/
3264 --ignore-file=match:/[._].*[.]swp$/
3267 --ignore-file=match:/core[.]\d+$/
3269 # minified Javascript
3270 --ignore-file=match:/[.-]min[.]js$/
3271 --ignore-file=match:/[.]js[.]min$/
3274 --ignore-file=match:/[.]min[.]css$/
3275 --ignore-file=match:/[.]css[.]min$/
3277 # JS and CSS source maps
3278 --ignore-file=match:/[.]js[.]map$/
3279 --ignore-file=match:/[.]css[.]map$/
3281 # PDFs, because they pass Perl's -T detection
3282 --ignore-file=ext:pdf
3284 # Common graphics, just as an optimization
3285 --ignore-file=ext:gif,jpg,jpeg,png
3287 # Common archives, as an optimization
3288 --ignore-file=ext:gz,tar,tgz,zip
3290 # Python compiles modules
3291 --ignore-file=ext:pyc,pyd,pyo
3294 --ignore-file=ext:so
3296 # Compiled gettext files
3297 --ignore-file=ext:mo
3299 ### Filetypes defined
3302 # https://www.gnu.org/s/make/
3303 --type-add=make:ext:mk
3304 --type-add=make:ext:mak
3305 --type-add=make:is:makefile
3306 --type-add=make:is:Makefile
3307 --type-add=make:is:Makefile.Debug
3308 --type-add=make:is:Makefile.Release
3309 --type-add=make:is:GNUmakefile
3312 # https://rake.rubyforge.org/
3313 --type-add=rake:is:Rakefile
3316 # https://cmake.org/
3317 --type-add=cmake:is:CMakeLists.txt
3318 --type-add=cmake:ext:cmake
3321 --type-add=actionscript:ext:as,mxml
3324 # https://www.adaic.org/
3325 --type-add=ada:ext:ada,adb,ads
3328 # https://docs.microsoft.com/en-us/previous-versions/office/developer/server-technologies/aa286483(v=msdn.10)
3329 --type-add=asp:ext:asp
3332 # https://dotnet.microsoft.com/apps/aspnet
3333 --type-add=aspx:ext:master,ascx,asmx,aspx,svc
3336 --type-add=asm:ext:asm,s
3339 --type-add=batch:ext:bat,cmd
3342 # https://en.wikipedia.org/wiki/ColdFusion
3343 --type-add=cfmx:ext:cfc,cfm,cfml
3346 # https://clojure.org/
3347 --type-add=clojure:ext:clj,cljs,edn,cljc
3350 # .xs are Perl C files
3351 --type-add=cc:ext:c,h,xs
3357 # https://coffeescript.org/
3358 --type-add=coffeescript:ext:coffee
3361 --type-add=cpp:ext:cpp,cc,cxx,m,hpp,hh,h,hxx
3364 --type-add=hpp:ext:hpp,hh,h,hxx
3367 --type-add=csharp:ext:cs
3370 # https://www.w3.org/Style/CSS/
3371 --type-add=css:ext:css
3375 --type-add=dart:ext:dart
3378 # https://en.wikipedia.org/wiki/Embarcadero_Delphi
3379 --type-add=delphi:ext:pas,int,dfm,nfm,dof,dpk,dproj,groupproj,bdsgroup,bdsproj
3382 # https://elixir-lang.org/
3383 --type-add=elixir:ext:ex,exs
3386 # https://www.gnu.org/software/emacs
3387 --type-add=elisp:ext:el
3390 # https://www.erlang.org/
3391 --type-add=erlang:ext:erl,hrl
3394 # https://en.wikipedia.org/wiki/Fortran
3395 --type-add=fortran:ext:f,f77,f90,f95,f03,for,ftn,fpp
3398 # https://golang.org/
3399 --type-add=go:ext:go
3402 # https://www.groovy-lang.org/
3403 --type-add=groovy:ext:groovy,gtmpl,gpp,grunit,gradle
3406 # https://gsp.grails.org/
3407 --type-add=gsp:ext:gsp
3410 # https://www.haskell.org/
3411 --type-add=haskell:ext:hs,lhs
3414 --type-add=html:ext:htm,html,xhtml
3417 # http://jade-lang.com/
3418 --type-add=jade:ext:jade
3421 # https://www.oracle.com/technetwork/java/index.html
3422 --type-add=java:ext:java,properties
3425 --type-add=js:ext:js
3428 # https://www.oracle.com/technetwork/java/javaee/jsp/index.html
3429 --type-add=jsp:ext:jsp,jspx,jspf,jhtm,jhtml
3433 --type-add=json:ext:json
3436 # https://kotlinlang.org/
3437 --type-add=kotlin:ext:kt,kts
3440 # http://www.lesscss.org/
3441 --type-add=less:ext:less
3444 # https://common-lisp.net/
3445 --type-add=lisp:ext:lisp,lsp
3448 # https://www.lua.org/
3449 --type-add=lua:ext:lua
3450 --type-add=lua:firstlinematch:/^#!.*\blua(jit)?/
3453 # https://en.wikipedia.org/wiki/Markdown
3454 --type-add=markdown:ext:md,markdown
3455 # We understand that there are many ad hoc extensions for markdown
3456 # that people use. .md and .markdown are the two that ack recognizes.
3457 # You are free to add your own in your ackrc file.
3460 # https://en.wikipedia.org/wiki/MATLAB
3461 --type-add=matlab:ext:m
3464 --type-add=objc:ext:m,h
3467 --type-add=objcpp:ext:mm,h
3470 # https://ocaml.org/
3471 --type-add=ocaml:ext:ml,mli,mll,mly
3475 --type-add=perl:ext:pl,pm,pod,t,psgi
3476 --type-add=perl:firstlinematch:/^#!.*\bperl/
3479 --type-add=perltest:ext:t
3481 # Perl's Plain Old Documentation format, POD
3482 --type-add=pod:ext:pod
3485 # https://www.php.net/
3486 --type-add=php:ext:php,phpt,php3,php4,php5,phtml
3487 --type-add=php:firstlinematch:/^#!.*\bphp/
3490 # https://plone.org/
3491 --type-add=plone:ext:pt,cpt,metadata,cpy,py
3494 # https://www.python.org/
3495 --type-add=python:ext:py
3496 --type-add=python:firstlinematch:/^#!.*\bpython/
3499 # https://www.r-project.org/
3503 # https://docutils.sourceforge.io/rst.html
3504 --type-add=rst:ext:rst
3507 # https://www.ruby-lang.org/
3508 --type-add=ruby:ext:rb,rhtml,rjs,rxml,erb,rake,spec
3509 --type-add=ruby:is:Rakefile
3510 --type-add=ruby:firstlinematch:/^#!.*\bruby/
3513 # https://www.rust-lang.org/
3514 --type-add=rust:ext:rs
3517 # https://sass-lang.com
3518 --type-add=sass:ext:sass,scss
3521 # https://www.scala-lang.org/
3522 --type-add=scala:ext:scala
3525 # https://groups.csail.mit.edu/mac/projects/scheme/
3526 --type-add=scheme:ext:scm,ss
3529 --type-add=shell:ext:sh,bash,csh,tcsh,ksh,zsh,fish
3530 --type-add=shell:firstlinematch:/^#!.*\b(?:ba|t?c|k|z|fi)?sh\b/
3533 # http://www.smalltalk.org/
3534 --type-add=smalltalk:ext:st
3537 # https://www.smarty.net/
3538 --type-add=smarty:ext:tpl
3541 # https://www.iso.org/standard/45498.html
3542 --type-add=sql:ext:sql,ctl
3545 # http://stylus-lang.com/
3546 --type-add=stylus:ext:styl
3549 # https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
3550 --type-add=svg:ext:svg
3553 # https://developer.apple.com/swift/
3554 --type-add=swift:ext:swift
3555 --type-add=swift:firstlinematch:/^#!.*\bswift/
3558 # https://www.tcl.tk/
3559 --type-add=tcl:ext:tcl,itcl,itk
3562 # https://www.latex-project.org/
3563 --type-add=tex:ext:tex,cls,sty
3565 # Template Toolkit (Perl)
3566 # http//template-toolkit.org/
3567 --type-add=ttml:ext:tt,tt2,ttml
3571 --type-add=toml:ext:toml
3574 # https://www.typescriptlang.org/
3575 --type-add=ts:ext:ts,tsx
3578 --type-add=vb:ext:bas,cls,frm,ctl,vb,resx
3581 --type-add=verilog:ext:v,vh,sv
3584 # http://www.eda.org/twiki/bin/view.cgi/P1076/WebHome
3585 --type-add=vhdl:ext:vhd,vhdl
3588 # https://www.vim.org/
3589 --type-add=vim:ext:vim
3592 # https://www.w3.org/TR/REC-xml/
3593 --type-add=xml:ext:xml,dtd,xsd,xsl,xslt,ent,wsdl
3594 --type-add=xml:firstlinematch:/<[?]xml/
3598 --type-add=yaml:ext:yaml,yml
3600 $lines =~ s/==VERSION==/$App::Ack::VERSION/sm;
3606 package App
::Ack
::ConfigFinder
;
3613 use File
::Spec
3.00 ();
3615 use if ($^O eq 'MSWin32'), 'Win32';
3621 return bless {}, $class;
3625 sub _remove_redundancies
{
3630 foreach my $config (@configs) {
3631 my $path = $config->{path
};
3632 my $key = -e
$path ? Cwd
::realpath
( $path ) : $path;
3633 if ( not $App::Ack
::is_windows
) {
3634 # On Unix, uniquify on inode.
3635 my ($dev, $inode) = (stat $key)[0, 1];
3636 $key = "$dev:$inode" if defined $dev;
3638 push( @uniq, $config ) unless $seen{$key}++;
3644 sub _check_for_ackrc
{
3645 return unless defined $_[0];
3647 my @files = grep { -f
}
3648 map { File
::Spec-
>catfile(@_, $_) }
3651 App
::Ack
::die( File
::Spec-
>catdir(@_) . ' contains both .ackrc and _ackrc. Please remove one of those files.' )
3654 return wantarray ? @files : $files[0];
3655 } # end _check_for_ackrc
3659 sub find_config_files
{
3662 if ( $App::Ack
::is_windows
) {
3663 push @config_files, map { +{ path
=> File
::Spec-
>catfile($_, 'ackrc') } } (
3664 Win32
::GetFolderPath
(Win32
::CSIDL_COMMON_APPDATA
()),
3665 Win32
::GetFolderPath
(Win32
::CSIDL_APPDATA
()),
3669 push @config_files, { path
=> '/etc/ackrc' };
3673 if ( $ENV{'ACKRC'} && -f
$ENV{'ACKRC'} ) {
3674 push @config_files, { path
=> $ENV{'ACKRC'} };
3677 push @config_files, map { +{ path
=> $_ } } _check_for_ackrc
($ENV{'HOME'});
3680 my $cwd = Cwd
::getcwd
();
3681 return () unless defined $cwd;
3683 # XXX This should go through some untainted cwd-fetching function, and not get untainted brute-force like this.
3686 my @dirs = File
::Spec-
>splitdir( $cwd );
3688 my $ackrc = _check_for_ackrc
(@dirs);
3689 if ( defined $ackrc ) {
3690 push @config_files, { project
=> 1, path
=> $ackrc };
3696 # We only test for existence here, so if the file is deleted out from under us, this will fail later.
3697 return _remove_redundancies
( @config_files );
3701 package App
::Ack
::ConfigLoader
;
3707 use File
::Spec
3.00 ();
3708 use Getopt
::Long
2.39 ();
3709 use Text
::ParseWords
3.1 ();
3721 return Getopt
::Long
::Parser-
>new( config
=> [ @standard, @opts ] );
3724 sub _generate_ignore_dir
{
3725 my ( $option_name, $opt ) = @_;
3727 my $is_inverted = $option_name =~ /^--no/;
3730 my ( undef, $dir ) = @_;
3732 $dir = _remove_directory_separator
( $dir );
3733 if ( $dir !~ /:/ ) {
3734 $dir = 'is:' . $dir;
3737 my ( $filter_type, $args ) = split /:/, $dir, 2;
3739 if ( $filter_type eq 'firstlinematch' ) {
3740 App
::Ack
::die( qq{Invalid filter specification "$filter_type" for option '$option_name'} );
3743 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args));
3746 my $previous_inversion_matches = $opt->{idirs
} && !($is_inverted xor $opt->{idirs
}[-1]->is_inverted());
3748 if ( $previous_inversion_matches ) {
3749 $collection = $opt->{idirs
}[-1];
3751 if ( $is_inverted ) {
3752 # This relies on invert of an inverted filter to return the original.
3753 $collection = $collection->invert();
3757 $collection = App
::Ack
::Filter
::Collection-
>new();
3758 push @{ $opt->{idirs
} }, $is_inverted ? $collection->invert() : $collection;
3761 $collection->add($filter);
3763 if ( $filter_type eq 'is' ) {
3764 $collection->add(App
::Ack
::Filter
::IsPath-
>new($args));
3770 sub _remove_directory_separator
{
3773 state $dir_sep_chars = $App::Ack
::is_windows
? quotemeta( '\\/' ) : quotemeta( File
::Spec-
>catfile( '', '' ) );
3775 $path =~ s/[$dir_sep_chars]$//;
3781 sub _process_filter_spec
{
3784 if ( $spec =~ /^(\w+):(\w+):(.*)/ ) {
3785 my ( $type_name, $ext_type, $arguments ) = ( $1, $2, $3 );
3787 return ( $type_name,
3788 App
::Ack
::Filter-
>create_filter($ext_type, split(/,/, $arguments)) );
3790 elsif ( $spec =~ /^(\w+)=(.*)/ ) { # Check to see if we have ack1-style argument specification.
3791 my ( $type_name, $extensions ) = ( $1, $2 );
3793 my @extensions = split(/,/, $extensions);
3794 foreach my $extension ( @extensions ) {
3795 $extension =~ s/^[.]//;
3798 return ( $type_name, App
::Ack
::Filter-
>create_filter('ext', @extensions) );
3801 App
::Ack
::die( "Invalid filter specification '$spec'" );
3806 sub _uninvert_filter
{
3807 my ( $opt, @filters ) = @_;
3809 return unless defined $opt->{filters
} && @filters;
3811 # Loop through all the registered filters. If we hit one that
3812 # matches this extension and it's inverted, we need to delete it from
3814 for ( my $i = 0; $i < @{ $opt->{filters
} }; $i++ ) {
3815 my $opt_filter = @{ $opt->{filters
} }[$i];
3817 # XXX Do a real list comparison? This just checks string equivalence.
3818 if ( $opt_filter->is_inverted() && "$opt_filter->{filter}" eq "@filters" ) {
3819 splice @{ $opt->{filters
} }, $i, 1;
3828 sub _process_filetypes
{
3829 my ( $opt, $arg_sources ) = @_;
3831 my %additional_specs;
3833 my $add_spec = sub {
3834 my ( undef, $spec ) = @_;
3836 my ( $name, $filter ) = _process_filter_spec
($spec);
3838 push @{ $App::Ack
::mappings
{$name} }, $filter;
3840 $additional_specs{$name . '!'} = sub {
3841 my ( undef, $value ) = @_;
3843 my @filters = @{ $App::Ack
::mappings
{$name} };
3845 @filters = map { $_->invert() } @filters;
3848 _uninvert_filter
( $opt, @filters );
3851 push @{ $opt->{'filters'} }, @filters;
3855 my $set_spec = sub {
3856 my ( undef, $spec ) = @_;
3858 my ( $name, $filter ) = _process_filter_spec
($spec);
3860 $App::Ack
::mappings
{$name} = [ $filter ];
3862 $additional_specs{$name . '!'} = sub {
3863 my ( undef, $value ) = @_;
3865 my @filters = @{ $App::Ack
::mappings
{$name} };
3867 @filters = map { $_->invert() } @filters;
3870 push @{ $opt->{'filters'} }, @filters;
3874 my $delete_spec = sub {
3875 my ( undef, $name ) = @_;
3877 delete $App::Ack
::mappings
{$name};
3878 delete $additional_specs{$name . '!'};
3881 my %type_arg_specs = (
3882 'type-add=s' => $add_spec,
3883 'type-set=s' => $set_spec,
3884 'type-del=s' => $delete_spec,
3887 my $p = opt_parser
( 'no_auto_abbrev', 'pass_through' );
3888 foreach my $source (@{$arg_sources}) {
3889 my $args = $source->{contents
};
3892 # $args are modified in place, so no need to munge $arg_sources
3893 $p->getoptionsfromarray( $args, %type_arg_specs );
3896 ( undef, $source->{contents
} ) =
3897 $p->getoptionsfromstring( $args, %type_arg_specs );
3901 $additional_specs{'k|known-types'} = sub {
3902 my @filters = map { @{$_} } values(%App::Ack
::mappings
);
3904 push @{ $opt->{'filters'} }, @filters;
3907 return \
%additional_specs;
3912 my ( $opt, $extra_specs ) = @_;
3916 my ( $getopt, $value ) = @_;
3919 if ( $value =~ s/^no// ) {
3926 $callback = $extra_specs->{ $value . '!' };
3930 $callback->( $getopt, $cb_value );
3933 App
::Ack
::die( "Unknown type '$value'" );
3940 1 => sub { $opt->{1} = $opt->{m
} = 1 },
3941 'A|after-context:-1' => sub { shift; $opt->{A
} = _context_value
(shift) },
3942 'B|before-context:-1' => sub { shift; $opt->{B
} = _context_value
(shift) },
3943 'C|context:-1' => sub { shift; $opt->{B
} = $opt->{A
} = _context_value
(shift) },
3944 'break!' => \
$opt->{break},
3945 'c|count' => \
$opt->{c
},
3946 'color|colour!' => \
$opt->{color
},
3947 'color-match=s' => \
$ENV{ACK_COLOR_MATCH
},
3948 'color-filename=s' => \
$ENV{ACK_COLOR_FILENAME
},
3949 'color-colno=s' => \
$ENV{ACK_COLOR_COLNO
},
3950 'color-lineno=s' => \
$ENV{ACK_COLOR_LINENO
},
3951 'column!' => \
$opt->{column
},
3952 'create-ackrc' => sub { say for ( '--ignore-ack-defaults', App
::Ack
::ConfigDefault
::options
() ); exit; },
3953 'debug' => \
$opt->{debug
},
3955 my ( undef, $value ) = @_;
3958 $opt->{noenv_seen
} = 1;
3962 'files-from=s' => \
$opt->{files_from
},
3963 'filter!' => \
$App::Ack
::is_filter_mode
,
3964 flush
=> sub { $| = 1 },
3965 'follow!' => \
$opt->{follow
},
3967 'group!' => sub { shift; $opt->{heading
} = $opt->{break} = shift },
3968 'heading!' => \
$opt->{heading
},
3969 'h|no-filename' => \
$opt->{h
},
3970 'H|with-filename' => \
$opt->{H
},
3971 'i|ignore-case' => sub { $opt->{i
} = 1; $opt->{S
} = 0; },
3972 'I|no-ignore-case' => sub { $opt->{i
} = 0; $opt->{S
} = 0; },
3973 'ignore-directory|ignore-dir=s' => _generate_ignore_dir
('--ignore-dir', $opt),
3974 'ignore-file=s' => sub {
3975 my ( undef, $file ) = @_;
3977 my ( $filter_type, $args ) = split /:/, $file, 2;
3979 my $filter = App
::Ack
::Filter-
>create_filter($filter_type, split(/,/, $args//''));
3981 if ( !$opt->{ifiles
} ) {
3982 $opt->{ifiles
} = App
::Ack
::Filter
::Collection-
>new();
3984 $opt->{ifiles
}->add($filter);
3986 'l|files-with-matches'
3988 'L|files-without-matches'
3990 'm|max-count=i' => \
$opt->{m
},
3991 'match=s' => \
$opt->{regex
},
3992 'n|no-recurse' => \
$opt->{n
},
3993 o
=> sub { $opt->{output
} = '$&' },
3994 'output=s' => \
$opt->{output
},
3996 my ( undef, $value ) = @_;
3998 $opt->{pager
} = $value || $ENV{PAGER
};
4000 'noignore-directory|noignore-dir=s' => _generate_ignore_dir
('--noignore-dir', $opt),
4001 'nopager' => sub { $opt->{pager
} = undef },
4002 'passthru' => \
$opt->{passthru
},
4003 'print0' => \
$opt->{print0
},
4004 'p|proximate:1' => \
$opt->{p
},
4005 'P' => sub { $opt->{p
} = 0 },
4006 'Q|literal' => \
$opt->{Q
},
4007 'r|R|recurse' => sub { $opt->{n
} = 0 },
4008 'range-start=s' => \
$opt->{range_start
},
4009 'range-end=s' => \
$opt->{range_end
},
4010 'range-invert!' => \
$opt->{range_invert
},
4012 'show-types' => \
$opt->{show_types
},
4013 'S|smart-case!' => sub { my (undef,$value) = @_; $opt->{S
} = $value; $opt->{i
} = 0 if $value; },
4014 'sort-files' => \
$opt->{sort_files
},
4015 't|type=s' => \
&_type_handler
,
4016 'T=s' => sub { my ($getopt,$value) = @_; $value="no$value"; _type_handler
($getopt,$value); },
4017 'underline!' => \
$opt->{underline
},
4018 'v|invert-match' => \
$opt->{v
},
4019 'w|word-regexp' => \
$opt->{w
},
4020 'x' => sub { $opt->{files_from
} = '-' },
4022 'help' => sub { App
::Ack
::show_help
(); exit; },
4023 'help-types' => sub { App
::Ack
::show_help_types
(); exit; },
4024 'help-colors' => sub { App
::Ack
::show_help_colors
(); exit; },
4025 'help-rgb-colors' => sub { App
::Ack
::show_help_rgb
(); exit; },
4026 $extra_specs ? %{$extra_specs} : (),
4031 sub _context_value
{
4034 # Contexts default to 2.
4035 return (!defined($val) || ($val < 0)) ? 2 : $val;
4039 sub _process_other
{
4040 my ( $opt, $extra_specs, $arg_sources ) = @_;
4043 my $is_help_types_active;
4045 foreach my $source (@{$arg_sources}) {
4046 if ( $source->{name
} eq 'ARGV' ) {
4047 $argv_source = $source->{contents
};
4052 if ( $argv_source ) { # This *should* always be true, but you never know...
4053 my $p = opt_parser
( 'pass_through' );
4054 $p->getoptionsfromarray( [ @{$argv_source} ],
4055 'help-types' => \
$is_help_types_active,
4059 my $arg_specs = get_arg_spec
( $opt, $extra_specs );
4061 my $p = opt_parser
();
4062 foreach my $source (@{$arg_sources}) {
4063 my ( $source_name, $args ) = @{$source}{qw
/name contents/};
4065 my $args_for_source = { %{$arg_specs} };
4067 if ( $source->{is_ackrc
} ) {
4070 App
::Ack
::die( "Option --$name is forbidden in .ackrc files." );
4073 $args_for_source = {
4074 %{$args_for_source},
4075 'output=s' => $illegal,
4076 'match=s' => $illegal,
4079 if ( $source->{project
} ) {
4082 App
::Ack
::die( "Option --$name is forbidden in project .ackrc files." );
4085 $args_for_source = {
4086 %{$args_for_source},
4087 'pager:s' => $illegal,
4093 $ret = $p->getoptionsfromarray( $args, %{$args_for_source} );
4096 ( $ret, $source->{contents
} ) =
4097 $p->getoptionsfromstring( $args, %{$args_for_source} );
4100 if ( !$is_help_types_active ) {
4101 my $where = $source_name eq 'ARGV' ? 'on command line' : "in $source_name";
4102 App
::Ack
::die( "Invalid option $where" );
4105 if ( $opt->{noenv_seen
} ) {
4106 App
::Ack
::die( "--noenv found in $source_name" );
4110 # XXX We need to check on a -- in the middle of a non-ARGV source
4116 sub _explode_sources
{
4117 my ( $sources ) = @_;
4122 my $arg_spec = get_arg_spec
( \
%opt, {} );
4124 my $dummy_sub = sub {};
4125 my $add_type = sub {
4126 my ( undef, $arg ) = @_;
4128 if ( $arg =~ /(\w+)=/) {
4129 $arg_spec->{$1} = $dummy_sub;
4132 ( $arg ) = split /:/, $arg;
4133 $arg_spec->{$arg} = $dummy_sub;
4137 my $del_type = sub {
4138 my ( undef, $arg ) = @_;
4140 delete $arg_spec->{$arg};
4143 my $p = opt_parser
( 'pass_through' );
4144 foreach my $source (@{$sources}) {
4145 my ( $name, $options ) = @{$source}{qw
/name contents/};
4146 if ( ref($options) ne 'ARRAY' ) {
4147 $source->{contents
} = $options =
4148 [ Text
::ParseWords
::shellwords
($options) ];
4151 for my $j ( 0 .. @{$options}-1 ) {
4152 next unless $options->[$j] =~ /^-/;
4153 my @chunk = ( $options->[$j] );
4154 push @chunk, $options->[$j] while ++$j < @{$options} && $options->[$j] !~ /^-/;
4158 $p->getoptionsfromarray( [@chunk],
4159 'type-add=s' => $add_type,
4160 'type-set=s' => $add_type,
4161 'type-del=s' => $del_type,
4165 push @new_sources, {
4172 return \
@new_sources;
4179 my $first_a = $a->[0];
4180 my $first_b = $b->[0];
4182 $first_a =~ s/^--?//;
4183 $first_b =~ s/^--?//;
4185 return $first_a cmp $first_b;
4190 my ( $sources ) = @_;
4192 $sources = _explode_sources
($sources);
4197 foreach my $source (@{$sources}) {
4198 my $name = $source->{name
};
4199 if ( not $opts_by_source{$name} ) {
4200 $opts_by_source{$name} = [];
4201 push @source_names, $name;
4203 push @{$opts_by_source{$name}}, $source->{contents
};
4206 foreach my $name (@source_names) {
4207 my $contents = $opts_by_source{$name};
4210 say '=' x
length($name);
4211 say ' ', join(' ', @{$_}) for sort { _compare_opts
($a, $b) } @{$contents};
4218 sub _remove_default_options_if_needed
{
4219 my ( $sources ) = @_;
4223 foreach my $index ( 0 .. $#{$sources} ) {
4224 if ( $sources->[$index]{'name'} eq 'Defaults' ) {
4225 $default_index = $index;
4230 return $sources unless defined $default_index;
4232 my $should_remove = 0;
4234 my $p = opt_parser
( 'no_auto_abbrev', 'pass_through' );
4236 foreach my $index ( $default_index + 1 .. $#{$sources} ) {
4237 my $args = $sources->[$index]->{contents
};
4240 $p->getoptionsfromarray( $args,
4241 'ignore-ack-defaults' => \
$should_remove,
4245 ( undef, $sources->[$index]{contents
} ) = $p->getoptionsfromstring( $args,
4246 'ignore-ack-defaults' => \
$should_remove,
4251 return $sources unless $should_remove;
4253 my @copy = @{$sources};
4254 splice @copy, $default_index, 1;
4260 my $arg_sources = \
@_;
4263 pager
=> $ENV{ACK_PAGER_COLOR
} || $ENV{ACK_PAGER
},
4266 $arg_sources = _remove_default_options_if_needed
($arg_sources);
4268 # Check for --dump early.
4269 foreach my $source (@{$arg_sources}) {
4270 if ( $source->{name
} eq 'ARGV' ) {
4272 my $p = opt_parser
( 'pass_through' );
4273 $p->getoptionsfromarray( $source->{contents
},
4277 _dump_options
($arg_sources);
4283 my $type_specs = _process_filetypes
(\
%opt, $arg_sources);
4285 _check_for_mutex_options
( $type_specs );
4287 _process_other
(\
%opt, $type_specs, $arg_sources);
4288 while ( @{$arg_sources} ) {
4289 my $source = shift @{$arg_sources};
4290 my $args = $source->{contents
};
4292 # All of our sources should be transformed into an array ref
4294 my $source_name = $source->{name
};
4295 if ( $source_name eq 'ARGV' ) {
4299 App
::Ack
::die( "Source '$source_name' has extra arguments!" );
4303 App
::Ack
::die( 'The impossible has occurred!' );
4306 my $filters = ($opt{filters
} ||= []);
4308 # Throw the default filter in if no others are selected.
4309 if ( not grep { !$_->is_inverted() } @{$filters} ) {
4310 push @{$filters}, App
::Ack
::Filter
::Default-
>new();
4316 sub retrieve_arg_sources
{
4322 my $p = opt_parser
( 'no_auto_abbrev', 'pass_through' );
4325 'ackrc=s' => \
$ackrc,
4331 my $finder = App
::Ack
::ConfigFinder-
>new;
4332 @files = $finder->find_config_files;
4335 # We explicitly use open so we get a nice error message.
4336 # XXX This is a potential race condition!.
4337 if ( open my $fh, '<', $ackrc ) {
4341 App
::Ack
::die( "Unable to load ackrc '$ackrc': $!" );
4343 push( @files, { path
=> $ackrc } );
4346 push @arg_sources, {
4348 contents
=> [ App
::Ack
::ConfigDefault
::options_clean
() ],
4351 foreach my $file ( @files) {
4352 my @lines = read_rcfile
($file->{path
});
4354 push @arg_sources, {
4355 name
=> $file->{path
},
4356 contents
=> \
@lines,
4357 project
=> $file->{project
},
4363 push @arg_sources, {
4365 contents
=> [ @ARGV ],
4368 return @arg_sources;
4375 return unless defined $file && -e
$file;
4379 open( my $fh, '<', $file ) or App
::Ack
::die( "Unable to read $file: $!" );
4380 while ( defined( my $line = <$fh> ) ) {
4385 next if $line eq '';
4386 next if $line =~ /^\s*#/;
4388 push( @lines, $line );
4390 close $fh or App
::Ack
::die( "Unable to close $file: $!" );
4396 # Verifies no mutex options were passed. Dies if they were.
4397 sub _check_for_mutex_options
{
4398 my $type_specs = shift;
4400 my $mutex = mutex_options
();
4402 my ($raw,$used) = _options_used
( $type_specs );
4404 my @used = sort { lc $a cmp lc $b } keys %{$used};
4406 for my $i ( @used ) {
4407 for my $j ( @used ) {
4409 if ( $mutex->{$i}{$j} ) {
4410 my $x = $raw->[ $used->{$i} ];
4411 my $y = $raw->[ $used->{$j} ];
4412 App
::Ack
::die( "Options '$x' and '$y' can't be used together." );
4421 # Processes the command line option and returns a hash of the options that were
4422 # used on the command line, using their full name. "--prox" shows up in the hash as "--proximate".
4424 my $type_specs = shift;
4427 my $real_spec = get_arg_spec
( \
%dummy_opt, $type_specs );
4429 # The real argument parsing doesn't check for --type-add, --type-del or --type-set because
4430 # they get removed by the argument processing. We have to account for them here.
4431 my $sub_dummy = sub {};
4434 'type-add=s' => $sub_dummy,
4435 'type-del=s' => $sub_dummy,
4436 'type-set=s' => $sub_dummy,
4437 'ignore-ack-defaults' => $sub_dummy,
4442 my %spec_capture_parsed;
4443 my %spec_capture_raw;
4446 # Capture the %parsed hash.
4449 my $sub_count = sub {
4452 $parsed{$arg} = $parsed_pos++;
4454 %spec_capture_parsed = (
4455 '<>' => sub { $parsed_pos++ }, # Bump forward one pos for non-options.
4456 map { $_ => $sub_count } keys %{$real_spec}
4460 # Capture the @raw array.
4463 %spec_capture_raw = (
4464 '<>' => sub { $raw_pos++ }, # Bump forward one pos for non-options.
4467 my $sub_count = sub {
4471 $raw[$raw_pos] = length($arg) == 1 ? "-$arg" : "--$arg";
4475 for my $opt_spec ( keys %{$real_spec} ) {
4480 $negatable = ($opt_spec =~ s/!$//);
4482 if ( $opt_spec =~ s/(=[si])$// ) {
4485 if ( $opt_spec =~ s/(:.+)$// ) {
4489 my @aliases = split( /\|/, $opt_spec );
4490 for my $alias ( @aliases ) {
4491 $alias .= $type if defined $type;
4492 $alias .= $default if defined $default;
4493 $alias .= '!' if $negatable;
4495 $spec_capture_raw{$alias} = $sub_count;
4500 # Parse @ARGV twice, once with each capture spec.
4501 my $p = opt_parser
( 'pass_through' ); # Ignore invalid options.
4502 $p->getoptionsfromarray( [@ARGV], %spec_capture_raw );
4503 $p->getoptionsfromarray( [@ARGV], %spec_capture_parsed );
4505 return (\
@raw,\
%parsed);
4510 # This list is machine-generated by dev/crank-mutex. Do not modify it by hand.
4578 'with-filename' => 1,
4711 'with-filename' => 1,
4813 'with-filename' => {
4824 } # End of mutex_options()
4827 1; # End of App::Ack::ConfigLoader
4828 package App
::Ack
::File
;
4838 my $filename = shift;
4841 filename
=> $filename,
4845 if ( $self->{filename
} eq '-' ) {
4846 $self->{fh
} = *STDIN
;
4855 return $_[0]->{filename
};
4863 return $self->{basename
} //= (File
::Spec-
>splitpath($self->name))[2];
4871 if ( !$self->{fh
} ) {
4872 if ( open $self->{fh
}, '<', $self->{filename
} ) {
4876 $self->{fh
} = undef;
4884 sub may_be_present
{
4888 # Tells if the file needs a line-by-line scan. This is a big
4889 # optimization because if you can tell from the outset that the pattern
4890 # is not found in the file at all, then there's no need to do the
4891 # line-by-line iteration.
4893 # Slurp up an entire file up to 10M, see if there are any matches
4894 # in it, and if so, let us know so we can iterate over it directly.
4896 # The $regex may be undef if it had a "$" in it, and is therefore unsuitable for this heuristic.
4898 my $may_be_present = 1;
4899 if ( $regex && $self->open() && -f
$self->{fh
} ) {
4901 my $size = 10_000_000;
4902 my $rc = sysread( $self->{fh
}, $buffer, $size );
4903 if ( !defined($rc) ) {
4904 if ( $App::Ack
::report_bad_filenames
) {
4905 App
::Ack
::warn( $self->name . ": $!" );
4907 $may_be_present = 0;
4910 # If we read all 10M, then we need to scan the rest.
4911 # If there are any carriage returns, our results are flaky, so scan the rest.
4912 if ( ($rc == $size) || (index($buffer,"\r") >= 0) ) {
4913 $may_be_present = 1;
4916 if ( $buffer !~ /$regex/o ) {
4917 $may_be_present = 0;
4923 return $may_be_present;
4931 if ( defined($self->{fh
}) ) {
4932 return unless -f
$self->{fh
};
4934 if ( !seek( $self->{fh
}, 0, 0 ) && $App::Ack
::report_bad_filenames
) {
4935 App
::Ack
::warn( "$self->{filename}: $!" );
4947 if ( $self->{fh
} ) {
4948 if ( !close($self->{fh
}) && $App::Ack
::report_bad_filenames
) {
4949 App
::Ack
::warn( $self->name() . ": $!" );
4951 $self->{fh
} = undef;
4962 return __PACKAGE__-
>new($self->name);
4970 if ( !exists $self->{firstliney
} ) {
4971 my $fh = $self->open();
4973 if ( $App::Ack
::report_bad_filenames
) {
4974 App
::Ack
::warn( $self->name . ': ' . $! );
4976 $self->{firstliney
} = '';
4980 my $rc = sysread( $fh, $buffer, 250 );
4982 $buffer =~ s/[\r\n].*//s;
4985 if ( !defined($rc) ) {
4986 App
::Ack
::warn( $self->name . ': ' . $! );
4990 $self->{firstliney
} = $buffer;
4995 return $self->{firstliney
};
4999 package App
::Ack
::Files
;
5013 my $self = bless {}, $class;
5015 my $descend_filter = $opt->{descend_filter
};
5018 $descend_filter = sub {
5024 File
::Next
::files
( {
5025 file_filter
=> $opt->{file_filter
},
5026 descend_filter
=> $descend_filter,
5027 error_handler
=> _generate_error_handler
(),
5028 warning_handler
=> sub {},
5029 sort_files
=> $opt->{sort_files
},
5030 follow_symlinks
=> $opt->{follow
},
5042 my $error_handler = _generate_error_handler
();
5044 File
::Next
::from_file
( {
5045 error_handler
=> $error_handler,
5046 warning_handler
=> $error_handler,
5047 sort_files
=> $opt->{sort_files
},
5048 }, $file ) or return undef;
5061 my $self = bless {}, $class;
5063 $self->{iter
} = sub {
5064 state $has_been_called = 0;
5066 if ( !$has_been_called ) {
5067 $has_been_called = 1;
5080 my $file = $self->{iter
}->();
5082 return unless defined($file);
5084 return App
::Ack
::File-
>new( $file );
5088 sub _generate_error_handler
{
5089 if ( $App::Ack
::report_bad_filenames
) {
5092 App
::Ack
::warn( $msg );
5101 package App
::Ack
::Filter
;
5111 my ( undef, $type, @args ) = @_;
5113 if ( my $package = $filter_types{$type} ) {
5114 return $package->new(@args);
5116 my $allowed_types = join( ', ', sort keys %filter_types );
5117 App
::Ack
::die( "Unknown filter type '$type'. Type must be one of: $allowed_types." );
5121 sub register_filter
{
5122 my ( undef, $type, $package ) = @_;
5124 $filter_types{$type} = $package;
5133 return App
::Ack
::Filter
::Inverse-
>new( $self );
5143 return '(unimplemented to_string)';
5154 package App
::Ack
::Filter
::Collection
;
5160 our @ISA = 'App::Ack::Filter';
5173 my ( $self, $file ) = @_;
5175 for my $group (values %{$self->{groups
}}) {
5176 return 1 if $group->filter($file);
5179 for my $filter (@{$self->{ungrouped
}}) {
5180 return 1 if $filter->filter($file);
5187 my ( $self, $filter ) = @_;
5189 if (exists $filter->{'groupname'}) {
5190 my $group = ($self->{groups
}->{$filter->{groupname
}} ||= $filter->create_group());
5191 $group->add($filter);
5194 push @{$self->{'ungrouped'}}, $filter;
5203 return ref($self) . " - $self";
5209 return join(', ', map { "($_)" } @{$self->{ungrouped
}});
5213 package App
::Ack
::Filter
::Default
;
5219 our @ISA = 'App::Ack::Filter';
5225 return bless {}, $class;
5229 my ( undef, $file ) = @_;
5231 return -T
$file->name;
5235 package App
::Ack
::Filter
::Extension
;
5241 our @ISA = 'App::Ack::Filter';
5246 my ( $class, @extensions ) = @_;
5248 my $exts = join('|', map { "\Q$_\E"} @extensions);
5249 my $re = qr/[.](?:$exts)$/i;
5252 extensions
=> \
@extensions,
5254 groupname
=> 'ExtensionGroup',
5259 return App
::Ack
::Filter
::ExtensionGroup-
>new();
5263 my ( $self, $file ) = @_;
5265 return $file->name =~ /$self->{regex}/;
5271 return ref($self) . ' - ' . $self->{regex
};
5277 return join( ' ', map { ".$_" } @{$self->{extensions
}} );
5281 App
::Ack
::Filter-
>register_filter(ext
=> __PACKAGE__
);
5285 package App
::Ack
::Filter
::ExtensionGroup
;
5291 our @ISA = 'App::Ack::Filter';
5303 my ( $self, $filter ) = @_;
5305 foreach my $ext (@{$filter->{extensions
}}) {
5306 $self->{data
}->{lc $ext} = 1;
5313 my ( $self, $file ) = @_;
5315 if ($file->name =~ /[.]([^.]*)$/) {
5316 return exists $self->{'data'}->{lc $1};
5325 return ref($self) . " - $self";
5331 return join(' ', map { ".$_" } sort keys %{$self->{data
}});
5335 package App
::Ack
::Filter
::FirstLineMatch
;
5342 our @ISA = 'App::Ack::Filter';
5346 my ( $class, $re ) = @_;
5348 $re =~ s{^/|/$}{}g; # XXX validate?
5356 # This test reads the first 250 characters of a file, then just uses the
5357 # first line found in that. This prevents reading something like an entire
5358 # .min.js file (which might be only one "line" long) into memory.
5361 my ( $self, $file ) = @_;
5363 return $file->firstliney =~ /$self->{regex}/;
5370 return ref($self) . ' - ' . $self->{regex
};
5376 (my $re = $self->{regex
}) =~ s{\([^:]*:(.*)\)$}{$1};
5378 return "First line matches /$re/";
5382 App
::Ack
::Filter-
>register_filter(firstlinematch
=> __PACKAGE__
);
5386 package App
::Ack
::Filter
::Inverse
;
5393 our @ISA = 'App::Ack::Filter';
5397 my ( $class, $filter ) = @_;
5405 my ( $self, $file ) = @_;
5407 return !$self->{filter
}->filter( $file );
5413 return $self->{'filter'};
5423 my $filter = $self->{'filter'};
5429 package App
::Ack
::Filter
::Is
;
5435 our @ISA = 'App::Ack::Filter';
5438 use File
::Spec
3.00 ();
5441 my ( $class, $filename ) = @_;
5444 filename
=> $filename,
5445 groupname
=> 'IsGroup',
5450 return App
::Ack
::Filter
::IsGroup-
>new();
5454 my ( $self, $file ) = @_;
5456 return (File
::Spec-
>splitpath($file->name))[2] eq $self->{filename
};
5462 return ref($self) . ' - ' . $self->{filename
};
5468 return $self->{filename
};
5472 App
::Ack
::Filter-
>register_filter(is => __PACKAGE__
);
5476 package App
::Ack
::Filter
::IsGroup
;
5482 our @ISA = 'App::Ack::Filter';
5494 my ( $self, $filter ) = @_;
5496 $self->{data
}->{ $filter->{filename
} } = 1;
5502 my ( $self, $file ) = @_;
5504 return exists $self->{data
}->{ $file->basename };
5510 return ref($self) . " - $self";
5516 return join(' ', keys %{$self->{data
}});
5520 package App
::Ack
::Filter
::IsPath
;
5526 our @ISA = 'App::Ack::Filter';
5531 my ( $class, $filename ) = @_;
5534 filename
=> $filename,
5535 groupname
=> 'IsPathGroup',
5540 return App
::Ack
::Filter
::IsPathGroup-
>new();
5544 my ( $self, $file ) = @_;
5546 return $file->name eq $self->{filename
};
5552 return ref($self) . ' - ' . $self->{filename
};
5558 return $self->{filename
};
5562 package App
::Ack
::Filter
::IsPathGroup
;
5568 our @ISA = 'App::Ack::Filter';
5580 my ( $self, $filter ) = @_;
5582 $self->{data
}->{ $filter->{filename
} } = 1;
5588 my ( $self, $file ) = @_;
5590 return exists $self->{data
}->{$file->name};
5596 return ref($self) . " - $self";
5602 return join(' ', keys %{$self->{data
}});
5606 package App
::Ack
::Filter
::Match
;
5611 our @ISA = 'App::Ack::Filter';
5617 my ( $class, $re ) = @_;
5619 $re =~ s{^/|/$}{}g; # XXX validate?
5624 groupname
=> 'MatchGroup',
5629 return App
::Ack
::Filter
::MatchGroup-
>new;
5633 my ( $self, $file ) = @_;
5635 return $file->basename =~ /$self->{regex}/;
5641 return ref($self) . ' - ' . $self->{regex
};
5647 return "Filename matches $self->{regex}";
5651 App
::Ack
::Filter-
>register_filter(match
=> __PACKAGE__
);
5655 package App
::Ack
::Filter
::MatchGroup
;
5661 our @ISA = 'App::Ack::Filter';
5674 my ( $self, $filter ) = @_;
5676 push @{ $self->{matches
} }, $filter->{regex
};
5678 my $re = join('|', map { "(?:$_)" } @{ $self->{matches
} });
5679 $self->{big_re
} = qr/$re/;
5685 my ( $self, $file ) = @_;
5687 return $file->basename =~ /$self->{big_re}/;
5690 # This class has no inspect() or to_string() method.
5691 # It will just use the default one unless someone writes something useful.
5700 our $VERSION = '1.18';
5706 our $name; # name of the current file
5707 our $dir; # dir of the current file
5709 our %files_defaults;
5714 file_filter
=> undef,
5715 descend_filter
=> undef,
5716 error_handler
=> sub { CORE
::die $_[0] },
5717 warning_handler
=> sub { CORE
::warn @_ },
5718 sort_files
=> undef,
5719 follow_symlinks
=> 1,
5722 %skip_dirs = map {($_,1)} (File
::Spec-
>curdir, File
::Spec-
>updir);
5727 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5729 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5731 my $filter = $parms->{file_filter
};
5733 while ( my $entry = shift @queue ) {
5734 my ( $dirname, $file, $fullpath, $is_dir, $is_file, $is_fifo ) = @{$entry};
5735 if ( $is_file || $is_fifo ) {
5738 local $File::Next
::dir
= $dirname;
5739 local $File::Next
::name
= $fullpath;
5740 next if not $filter->();
5742 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5745 unshift( @queue, _candidate_files
( $parms, $fullpath ) );
5760 die _bad_invocation
() if @_ && defined($_[0]) && ($_[0] eq __PACKAGE__
);
5762 my ($parms,@queue) = _setup
( \
%files_defaults, @_ );
5763 my $err = $parms->{error_handler
};
5764 my $warn = $parms->{warning_handler
};
5766 my $filename = $queue[0]->[1];
5768 if ( !defined($filename) ) {
5769 $err->( 'Must pass a filename to from_file()' );
5774 if ( $filename eq '-' ) {
5778 if ( !open( $fh, '<', $filename ) ) {
5779 $err->( "Unable to open $filename: $!", $! + 0 );
5784 my $filter = $parms->{file_filter
};
5786 local $/ = $parms->{nul_separated
} ? "\x00" : $/;
5787 while ( my $fullpath = <$fh> ) {
5789 next unless $fullpath =~ /./;
5790 if ( not ( -f
$fullpath || -p _
) ) {
5791 $warn->( "$fullpath: No such file" );
5795 my ($volume,$dirname,$file) = File
::Spec-
>splitpath( $fullpath );
5798 local $File::Next
::dir
= $dirname;
5799 local $File::Next
::name
= $fullpath;
5800 next if not $filter->();
5802 return wantarray ? ($dirname,$file,$fullpath) : $fullpath;
5810 sub _bad_invocation
{
5811 my $good = (caller(1))[3];
5813 $bad =~ s/(.+)::/$1->/;
5814 return "$good must not be invoked as $bad";
5817 sub sort_standard
($$) { return $_[0]->[1] cmp $_[1]->[1] }
5818 sub sort_reverse
($$) { return $_[1]->[1] cmp $_[0]->[1] }
5823 my @parts = split( /\//, $path );
5825 return $path if @parts < 2;
5827 return File
::Spec-
>catfile( @parts );
5833 my $defaults = shift;
5834 my $passed_parms = ref $_[0] eq 'HASH' ? {%{+shift}} : {}; # copy parm hash
5836 my %passed_parms = %{$passed_parms};
5839 for my $key ( keys %{$defaults} ) {
5841 exists $passed_parms{$key}
5842 ? delete $passed_parms{$key}
5843 : $defaults->{$key};
5846 # Any leftover keys are bogus
5847 for my $badkey ( sort keys %passed_parms ) {
5848 my $sub = (caller(1))[3];
5849 $parms->{error_handler
}->( "Invalid option passed to $sub(): $badkey" );
5852 # If it's not a code ref, assume standard sort
5853 if ( $parms->{sort_files
} && ( ref($parms->{sort_files
}) ne 'CODE' ) ) {
5854 $parms->{sort_files
} = \
&sort_standard
;
5859 my $start = reslash
( $_ );
5860 my $is_dir = -d
$start;
5862 my $is_fifo = (-p _
) || ($start =~ m{^/dev/fd});
5865 ? [ $start, undef, $start, $is_dir, $is_file, $is_fifo ]
5866 : [ undef, $start, $start, $is_dir, $is_file, $is_fifo ];
5869 return ($parms,@queue);
5873 sub _candidate_files
{
5875 my $dirname = shift;
5878 if ( !opendir $dh, $dirname ) {
5879 $parms->{error_handler
}->( "$dirname: $!", $! + 0 );
5884 my $descend_filter = $parms->{descend_filter
};
5885 my $follow_symlinks = $parms->{follow_symlinks
};
5887 for my $file ( grep { !exists $skip_dirs{$_} } readdir $dh ) {
5888 my $fullpath = File
::Spec-
>catdir( $dirname, $file );
5889 if ( !$follow_symlinks ) {
5890 next if -l
$fullpath;
5897 my $is_fifo = (-p _
) || ($fullpath =~ m{^/dev/fd});
5899 # Only do directory checking if we have a descend_filter
5900 if ( $descend_filter ) {
5902 local $File::Next
::dir
= $fullpath;
5904 next if not $descend_filter->();
5907 push @newfiles, [ $dirname, $file, $fullpath, $is_dir, $is_file, $is_fifo ];
5911 my $sort_sub = $parms->{sort_files
};
5913 @newfiles = sort $sort_sub @newfiles;
5921 1; # End of File::Next