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