=begin pod

=head1 NAME

App::Rak - 21st century grep / find / ack / ag / rg on steroids

=head1 SYNOPSIS

=begin code :lang<bash>
# look for "foo" in current directory recursively
$ rak foo

# look for "foo" in directory "bar" recursively
$ rak foo bar

# look for "foo" as word in current directory
$ rak '/ << foo >> /'

# look for "foo", only produce filenames
$ rak foo --files-with-matches

# also produce 2 lines before and after
$ rak foo --before=2 --after=2

# lines with foo AND bar
$ rak foo --and=bar
=end code

=head1 DESCRIPTION

App::Rak provides a CLI called C<rak> that allows you to look for a pattern
in (a selection of files) from one or more directories recursively.  It has
been modelled after utilities such as C<grep>, C<ack>, C<ag> and C<rg>, with
a little bit of C<find> mixed in, and C<-n> and C<-p> parameters of many
programming languages.

Note: this project is now in beta-development phase.  Comments, suggestions
and bug reports continue to be more than welcome!

=head1 PATTERN SPECIFICATION

Patterns will be interpreted in the following ways if B<no> C<--type>
has been specified, or C<--type=auto> has been specified.

=head3 / regex /

If the pattern starts and ends with C</>, then it indicates a Raku
L<regex|https://docs.raku.org/language/regexes>.  B<No> special processing
of the given string between slashes will be done: the given pattern will be
parsed as a regex verbatim.  During the search process, each item will be
matched against this regex.  Any C<--ignorecase> or C<--ignoremark> arguments
will be honoured.

One can also specify the regex type with C<--type=regex>, so that C</ foo />
can be considered a shortcut for C<--type=regex foo>.

=head3 { code }

If the pattern starts with C<{> and ends with C<}>, then it indicates
Raku code to be executed.  B<No> special processing of the given string
between the curly braces will be done: the given code will be compiled as
Raku code.  During the search process, this code will be run for each item,
available in C<$_>.  To facilitate the use of libraries that wish to access
that topic, it is also available as the C<$*_> dynamic variable.

The dynamic variable C<$*SOURCE> will contain the C<IO::Path> object of the
file being processed.  Note that the Raku code will be called in a thread
B<unsafe> manner.

The dynamic variable C<$*_> will contain the topic with which the code was
called.  This to allow custom libraries to easily obtain the topic without
the user needing to specify that again.

One can also specify the code type with C<--type=code>, so that C<{ .uc }>
can be considered a shortcut for C<--type=code .uc>.

=head3 *code

If the pattern starts with C<*>, then this is a short way of specifying Raku
code as a pattern, using
L<Whatever-currying|https://docs.raku.org/type/Whatever#index-entry-Whatever-currying>
semantics.  Otherwise the same as C<{ code }>.

=head3 ^string

If the pattern starts with C<^>, then it indicates the string should be at
the B<start> of each item.  Basically a shortcut to specifying
C<--type=starts-with string>.  Any C<--smartcase>, C<--smartmark>,
C<--ignorecase> or C<--ignoremark> arguments will be honoured.

=head3 string$

If the pattern ends with C<$>, then it indicates the string should be at
the B<end> of each item.  Basically a shortcut to specifying
C<--type=ends-with string>.  Any C<--smartcase>, C<--smartmark>,
C<--ignorecase> or C<--ignoremark> arguments will be honoured.

=head3 ^string$

If the pattern starts with C<^> and ends with C<$>, then it indicates that
the string should be equal to the item.  Basically a shortcut to specifying
C<--type=equal string>.  Any C<--smartcase>, C<--ignorecase> or C<--ignoremark>
arguments will be honoured.

=head3 §string

If the pattern starts with C<§>, then it indicates that the string should
occur as a word (with word-boundaries on both ends) in the item.  Basically a
shortcut to specifying C<--type=words string>.  Any C<--smartcase>,
C<--smartmark>, C<--ignorecase> or C<--ignoremark> arguments will be honoured.

=head3 !specification

If the pattern starts with C<!>, then it indicates that the result of the
pattern specification should be negated.

=head3 &specification

If the pattern starts with C<&>, then it indicates that the result of the
pattern specification should be true B<as well as> the result of the
previous pattern specification.

=head3 s:string

If the pattern starts with 's:', then it indicates that the string should be
split on whitespace, and each part should be considered a separate pattern
specification.  Basically a shortcut to specifying C<--type=split string>.

=head3 jp:path

If the pattern start with 'jp:', then interpret the rest of the pattern as
a C<JSON path>.  Only makes sense when used together with C<--json-per-file>,
C<--json-per-line> or C<--json-per-elem>.  Requires that the
L<C<JSON::Path>|https://raku.land/cpan:JNTHN/JSON::Path> module is installed.
Basically a shortcut to specifying C<path --type=json-path>.

=head3 string

If there are no special start or end markers, then it indicates that the
string should occur somewhere in the item.  Basically a shortcut to
specifying C<string --type=contains>.  Any C<--smartcase>, C<--smartmark>,
C<--ignorecase> or C<--ignoremark> arguments will be honoured.

=head1 POSITIONAL ARGUMENTS

=head2 pattern

The pattern to search for, if no pattern was specified any other way.

Patterns can also be specified with the C<--pattern>, C<--not> and
C<--patterns-from> options, in which case B<all> other positional
arguments are considered to be path specifications.

=head2 path(s)

Optional.  Either indicates the path of the directory (and its
sub-directories), or the file that will be searched, or a URL that will
produce a file to be searched.  By default, all directories that do not
start with a period, and which are not symbolic links, will be recursed
into (but this can be changed with the C<--dir> option).

By default, all files with known extensions will be searched in the
directories.  This can be changed with the C<--file> option, or specialized
version of that like C<--extensions>.

Paths can also be specified with the C<--paths> option, in which case there
should only be a positional argument for the pattern, or none if C<--pattern>
option was used for the pattern specification.

=head1 ON CALLABLES AS PATTERN

C<Callables> can be specified by a string starting with C<*.> (so-called
L<Whatever currying|https://docs.raku.org/type/Whatever>, or as a string
starting with C<{> and ending with C<}>.

Note that if a C<Callable> is specified as a pattern, then no highlighting
can be performed as it cannot signal why or where a match occurred.

The return value of the pattern C<Callable> match is interpreted in the
following way:

=head2 True

If the C<Bool>ean True value is returned, assume the pattern is found.
Produce the item unless C<--invert-match> was specified.

=head2 False

If the C<Bool>ean False value is returned, assume the pattern is B<not>
found.  Do B<not> produce the item unless C<--invert-match> was specified.

=head2 Nil

If C<Nil> is returned, assume the pattern is B<not> found.

This typically happens when a C<try> is used in a pattern, and an execution
error occurred.  Do B<not> produce the item unless C<--invert-match> was
specified.

=head2 Empty

If the empty C<Slip> is returned, assume the pattern is B<not> found.
Do B<not> produce the item unless C<--invert-match> was specified.  Shown
in stats as a C<passthru>.

=head2 any other Slip

If a non-empty C<Slip> is returned, produce the values of the C<Slip>
separately for the given item (each with the same item number).

=head3 any other value

Produce that value.

=head1 PHASERS IN CALLABLE PATTERNS

The Raku Programming Language has a number of unique features that can
be used with patterns that are executable code.  One of them is the use
of so-called L<phasers|https://docs.raku.org/language/phasers> (pieces
of code that will be executed automatically when a certain condition has
been met.

C<App::Rak> currently supports all of Raku's
L<loop phasers|https://docs.raku.org/language/phasers#FIRST>:

=table
  phaser   event
  --------------
  FIRST    code to run when searching starts
  NEXT     code to run when searching a file is done
  LAST     code to run when searching is done

These phasers will be called in a B<thread-safe> manner.

=begin code :lang<bash>
# show number of files inspected before the search result
$ rak '{ state $s = 0; NEXT $s++; LAST say "$s files"; .contains("foo")}'

# show number of files inspected after of the search result
$ rak '{ state $s = 0; NEXT $s++; END say "$s files"; .contains("foo")}'
=end code

Note that the use of the C<LAST> phaser will make the search run eagerly,
meaning that no results will be shown until the search has been completed.

Any other phasers that do not require special attention by C<App::Rak>
are also supported in any code specified (such as C<BEGIN> and C<END>).

=head1 ON THE INTERPRETATION OF OPTIONS

All options when using App::Rak, start with either one dash C<-> or two
dashes C<-->.

If an option starts with two dashes, it is a so-called "long option".
Any characters after the dashes are considered to be the single name of
the option.

If an option starts with a single dash, then it is considered to be a
collection of "short options", each of 1 letter.  If the number of short
options is 1, then it can be followed by a numerical value (without equal
sign).

If the specification of the option does B<not> contain an equal sign C<=>,
then the option is interpreted as a boolean option.  By default, such a flag
is considered to represent C<True>.  The value can be negated in two ways:

=item a slash before the name
=item the string "no-" before the name

Some examples:

=item -i

Option "i" is True.

=item -j5

Option "j" has the value 5.

=item -im

Options "i" and "m" are True.

=item -/i

Option "i" is False.

=item -/im

Options "i" and "m" are False.

=item -no-i

Option "i" is False.

=item --foo

Option "foo" is True.

=item --/foo

Option "foo" is False.

=item --no-foo

Option "foo" is False.

If the specification of an option contains an equal sign after the name,
then whatever follows that, is considered the value of that option.  Whether
or not that value needs to be quoted, and how they are to be quoted, really
depends on the shell that you use to access `rak`.  Generally, if the value
consists of alphanumeric characters only, no quoting is necessary.  Otherwise
it's better to quote your values.

Some examples:

=item -s=foo

Option "s" has the value "foo".

=item -t='foo bar'

Option "t" has the value "foo bar".

=item --frobnicate=yes

Option "frobnicate" has the value "yes".

=head1 CREATING YOUR OWN OPTIONS

App::Rak provides B<many> options.  If you are happy with a set of options
for a certain workflow, You can use the C<--save> option to save that set
of options and than later access them with the given name:

=begin code :lang<bash>
# create -i shortcut for ignoring case
$ rak --ignorecase --save=i
Saved option '-i' as: --ignorecase

# create -m shortcut for ignoring accents
$ rak --ignoremark --save=m
Saved option '-m' as: --ignoremark

# same as --ignorecase --ignoremark
$ rak foo -im
=end code

Generally speaking, the most used boolean options can be saved as single
letter options: this allows multiple options to be specified in a single,
short manner (as shown above).

To better document / remember what a particular custom option is meant to
do, you can add a description with the C<--description> option.

=begin code :lang<bash>
# add a description to the -i custom option
$ rak --description='Search without caring for uppercase' --save=i
Saved '--description='Search without caring for uppercase'' as: -i

# add an option -g for searching only git files
$ rak --description='Committed files only' --under-version-control --save=g
Saved '--description='Committed files only' --under-version-control' as: -g
=end code

There is also a special named option that indicates the options that will
be automatically activated on any invocation: C<(default)>.

=begin code :lang<bash>
# enable --smartcase by default on every run
$ rak --smartcase --save='(default)'
Saved '--smartcase' as: (default)
=end code

You can use the C<--list-custom-options> to see what options you have saved
before.

Custom options are saved in C<~/.rak-config.json>.  You can override this
by specifying the C<RAK_CONFIG> environment variable.

=begin code :lang<bash>
# read custom options from ".custom.json" (in the current directory)
$ RAK_CONFIG=.custom.json rak foo
=end code

You can also use the C<RAK_CONFIG> variable to disable loading any
configuration by not specifying a value:

=begin code :lang<bash>
# start rak without any custom configuration
$ RAK_CONFIG= rak foo
=end code

=head1 SUPPORTED OPTIONS

All options are optional.  Any unexpected options, will cause an exception
to be thrown with the unexpected options listed and possible alternatives
mentioned.  Unless specifically indicated otherwise, using the negation of
a flag has the same effect as B<not> specifying it.

=head2 --absolute

Flag.  If specified indicates that whenever paths are shown, they will be
shown as absolute paths.  Defaults to C<False>, which will cause paths to
be produced as paths relative to the current directory.

=head2 --accept=code

Specifies the code that should be executed that should return C<True> if
the path is acceptable, given an C<IO::Path> object of the path.  See also
C<--deny>.

=begin code :lang<bash>
# Include files that have "use Test" in them
$ rak --accept='*.slurp.contains("use Test")'
=end code

=head2 --accessed=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The access time of the file
(number of seconds since epoch, as a C<Num> value) will be passed as the
only argument.  Note that many file systems do not actually support this
reliably.

See "CHECKING TIMES ON FILES" for more information about features that
can be used inside the C<Callable>.

=head2 --ack

Attempt to interpret following arguments as if they were arguments to the
L<C<ack>|https://metacpan.org/pod/ack> utility.  This is incomplete and
may be subtly different in behaviour.  Intended as a temporary measure
for people used to using C<ack>, while they train their muscle memory
to use B<rak> instead.

If you'd like a list of the option configuration, you can use the
C<--list-custom-options> argument.

=begin code :lang<bash>
# Show the current mappinng of "ack" to "rak" options
$ rak --ack --list-custom-options
=end code

=head2 --after-context=N

Indicate the number of lines that should be shown B<after> any line that
matches.  Defaults to B<0>.  Will be overridden by a C<--context> argument.

=head2 --allow-loose-escapes

Only applicable if C<--csv-per-line> has been specified.  Flag.  If specified,
indicates that B<any> character may be escaped.

=head2 --allow-loose-quotes

Only applicable if C<--csv-per-line> has been specified.  Flag.  If specified,
indicates that fields do not need to be quoted to be acceptable.

=head2 --allow-whitespace

Only applicable if C<--csv-per-line> has been specified.  Flag.  If specified,
indicates that whitespace is allowed around separators.

=head2 --also-first[=N]

Indicates the number of lines from the start of the file that should be
shown B<if> there is a match.  If not specified, B<0> will be assumed.
If specified as a flag, B<1> will be assumed.

=head2 --always-first[=N]

Indicates the number of lines from the start of the file that will B<always>
be shown, regardless of whether there is a match or not.  If not specified,
B<0> will be assumed.  If specified as a flag, B<1> will be assumed.

=head2 --auto-decompress

Flag.  If specified with a True value, will accept compressed files
with the C<.gz> (gzip) or C<.bz2> (bzip2) extension, if the extension was
otherwise acceptable.  Will automatically decompress files for inspection.

=head2 --and=foo

Specify B<additional> pattern that should match as well as any previously
specified pattern to produce a full match.

=head2 --andnot=foo

Specify B<additional> pattern that should B<not> match as well as any
previously specified pattern to produce a full match.

=head2 --auto-diag

Only applicable if C<--csv-per-line> has been specified.  Flag.  If
(implicitly) specified, will show diagnostic information about problems
that occurred during parsing of the CSV file.  The default is C<True>.

=head2 --backtrace

Flag.  When specified with a True value, will interpret either standard
input, or a single file, as a Raku backtrace.  And produce a result
containing the lines of source code from that backtrace.  Can be used
together with C<--context>, C<--before-context>, C<--after-context>,
C<--edit> and C<--vimgrep>.  Any pattern specification will only be used
for highlighting.  If B<not> used in combination with C<--edit> or
C<--vimgrep>, will assume a context of 2 lines.

=begin code :lang<bash>
# look at source of a stacktrace
$ raku script 2>&1 | rak --backtrace

# inspect the source of a stacktrace in an editor
$ raku script 2>&1 | rak --backtrace --edit

# inspect a backtrace stored in a file
$ rak --backtrace filename
=end code

=head2 --backup[=extension]

Indicate whether backups should be made of files that are being modified.
If specified without extension, the extension C<.bak> will be used.

=head2 --batch[=N]

Indicate the number of files that should be checked per thread.  If specified
as a flag, will assue C<1>.  Defaults to C<64> if not specified.  See also
<--degree>.

=head2 --before-context=N

Indicate the number of lines that should be shown B<before> any line that
matches.  Defaults to B<0>.  Will be overridden by a C<--context> argument.

=head2 --blame-per-file

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified,
indicates that each of the selected files will be provided as
L<C<Git::Blame::File>|https://raku.land/zef:lizmat/Git::Blame::File#methods-on-gitblamefile>
objects if C<git blame> can be performed on the a selected file.  If that
is not possible, then the selected file will be ignored.

If <git blame> information can be obtained, then the associated
C<Git::Blame::File> object will be presented to the pattern C<Callable>.
If the Callable returns C<True>, then the filename will be produced.  If
anything else is returned, then the stringification of that object will be
produced.

Requires the L<C<Git::Blame::File>|https://raku.land/zef:lizmat/Git::Blame::File>
Raku module to be installed.

=begin code :lang<bash>
# show files with more than 10 commits
$ rak '*.commits > 10' --blame-per-file --files-with-matches
=end code

=head2 --blame-per-line

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified,
indicates that each line from the selected files will be provided as
L<C<Git::Blame::Line>|https://raku.land/zef:lizmat/Git::Blame::File#accessors-on-gitblameline>
objects if C<git blame> can be performed on the a selected file.  If that
is not possible, then the selected file will be ignored.

If <git blame> information can be obtained, then the associated
C<Git::Blame::Line> object will be presented to the pattern C<Callable>.
If the Callable returns C<True>, then the short representation of the
C<git blame> information will be produced.  If the returned value is anything
else, then the stringification of that object will be produced.

=begin code :lang<bash>
# show git blame on lines of which the author is "Scooby Doo"
$ rak '{ .author eq "Scooby Doo" }' --blame-per-line
=end code

Requires that the L<C<Git::Blame::File>|https://raku.land/zef:lizmat/Git::Blame::File> module is installed.

=head2 --blocks=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The number of logical blocks
that a file takes up in the filesystem, will be passed as the only argument.

=begin code :lang<bash>
# show files that consist of at least 3 blocks
$ rak --find --blocks='* >= 3'
=end code

=head2 --break[=string]

Indicate whether there should be a visible division between matches of
different files.  Can also be specified as a string to be used as the
divider.  Defaults to C<True> (using an empty line as a divider) if
C<--group-matches> is (implicitly) set to C<True>, else defaults to C<False>.

=head2 --checkout=branch

Only valid if the current directory is under git version control.  Indicate
the branch to checkout by the general matching logic of App::Rak.  Will
produce listing of matching branches if more than one, or say that there
is no match.  Branches need not have been checked out locally yet.

=head2 --categorize=categorizer

If specified, indicates the C<Callable> that should return zero or more
keys for a given line to have it categorized.  This effectively replaces
the filename if a line by its key in the result.  See also C<--classify>.

=begin code :lang<bash>
# categorize by the first two letters of a line
$ rak --categorize='*.substr(0,2).comb'
=end code

=head2 --classify=classifier

If specified, indicates the C<Callable> that should return a key for a
given line to have it classified.  This effectively replaces the filename
if a line by its key in the result.  See also C<--categorize>.

=begin code :lang<bash>
# classify by the last letter of a line
$ rak --classify='*.substr(*-1)'
=end code

=head2 --context=N

Indicate the number of lines that should be produced B<around> any line that
matches.  Defaults to B<0>.

=head2 --count-only

Flag.  Indicate whether just the number of lines with matches should be
calculated.  When specified with a C<True> value, will show a "N matches
in M files" by default, and if the C<:files-with-matches> (or
C<files-without matches>) option is also specified with a C<True> value,
will just show total counts.  See also C<--stats-only>.

=head2 --created=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The creation time of the file
(number of seconds since epoch, as a C<Num> value) will be passed as the
only argument.

See "CHECKING TIMES ON FILES" for more information about features that
can be used inside the C<Callable>.

=head2 --csv-per-line

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified with a
C<True> value, indicates that selected files should be interpreted as
comma separated values (CSV).  Each row from the selected files will be
provided as a list of strings (or as C<CSV::Field> objects if C<--keep-meta>
was specified).

Attempt to interpret file as a CSV file, and pass each row as a List to
to the pattern Callable.  Only files with extensions from the C<#csv> group
will be tried, unless overridden by any explicit extension specification.

More documentation can be found with the
L<Text::CSV|https://raku.land/github:Tux/Text::CSV> module itself.

=begin code :lang<bash>
# Show the values of the column named "foo" of the rows in the "info.csv"
# file if the column named "bar" is equal to "foo"
$ rak --csv-per-line '{.<foo> if .<bar> eq "foo"}' info.csv

# Show the values of the first column of the rows in the "info.csv" file
# if the second column is equal to "foo"
$ rak --csv-per-line --/headers '{.[0] if .[1] eq "foo"}' info.csv
=end code

=head2 --degree[=N | code]

Indicate the number of worker threads that should be maximally.  Defaults
to the number of cores minus 1 if not specified.  Assumes C<1> if specified
as a flag.  Can also take a C<Callable> specification, in which case the
number of CPU cores will be presented to that Callable as the only argument.
See also <--batch>.

=head2 --deny=code

Specifies the code that should be executed that should return C<True> if
the path is B<NOT> acceptable, given an C<IO::Path> object of the path.
See also C<--accept>.

=begin code :lang<bash>
# Include files that **NOT** have "use Test" in them
$ rak --deny='*.slurp.contains("use Test")'
=end code

=head2 --description=text

Specify a description to be saved with the custom option.  This will be
shown prominently with --list-custom-options.  If it is the only argument
apart from --save, then the discription will be added (if there was no
description yet) or replace the current description of the option.

=head2 --device-number=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The device number of the
filesystem on which the file is located, will be passed as the only argument.

=head2 --dir=condition

If specified, indicates the C<Callable> that should return True to have a
directory be included for further recursions in file selection.  The basename
of the directory will be passed as the only argument.  Defaults to all
directories that do not start with a period.  Can specify as a flag to
include B<all> directories for recursion.

=head2 --dont-catch

Flag.  If specified as a flag, will B<not> catch any error during processing,
but will throw any error again.  Defaults to C<False>, making sure that
errors B<will> be caught.  Mainly intended for debugging and error reporting.

=head2 --dryrun

Flag.  Indicate to B<not> actually make any changes to any content
modification if specified with a C<True> value.  Only makes sense together
with the C<--modify-files> and the C<--rename-files> option.

=head2 --eco-code=[rea|fez]

Indicate that B<all> the files that can contain Raku code in the local
ecosystem cache (as generated by
L<C<Ecosystem::Cache>|https://raku.land/zef:lizmat/Ecosystem::Cache>)
should be searched.  If specified as a flag, will assume the C<"rea">
(Raku Ecosystem Archive).

=head2 --eco-doc=[rea|fez]

Indicate that B<all> the files that can contain documentation in the
local ecosystem cache (as generated by
L<C<Ecosystem::Cache>|https://raku.land/zef:lizmat/Ecosystem::Cache>)
should be searched.  If specified as a flag, will assume the C<"rea">
(Raku Ecosystem Archive).

=head2 --eco-meta[=name1,name2]

Intended to be used by Raku ecosystem maintainers.  Indicates the name of
zero or more Raku ecosystems of which to inspect the C<META6.json>
information of all its modules.  Currently supported names are:
 
=table
  name   description
  ------------------
  p6c    the original git ecosystem (deprecated)
  cpan   the ecosystem piggybacking on PAUSE / CPAN (deprecated)
  fez    the currently recommended ecosystem for new modules / updates
  rea    the Raku Ecosystem Archive

Defaults to C<rea> if specified as a flag.  Implies C<--json-per-elem>.

=begin code :lang<bash>
# show all unique module names by an author from the REA
$ rak '{ .author eq "Scooby Doo" }' --eco-meta

# same, but now from the p6c and cpan ecosystems
$ rak '{ .author eq "Scooby Doo" }' --eco-meta=p6c,cpan
=end code

Assumes C<zef> is installed and its meta information is available.

=head2 --eco-provides=[rea|fez]

Indicate that the module files (from the C<"provides"> section of the
meta-information in a distribution) in the local ecosystem cache (as
generated by 
L<C<Ecosystem::Cache>|https://raku.land/zef:lizmat/Ecosystem::Cache>)
should be searched.  If specified as a flag, will assume the C<"rea">
(Raku Ecosystem Archive).

=head2 --eco-scripts=[rea|fez]

Indicate that the scripts (from the C<"bin"> directory of a distribution)
in the local ecosystem cache (as generated by
L<C<Ecosystem::Cache>|https://raku.land/zef:lizmat/Ecosystem::Cache>)
should be searched.  If specified as a flag, will assume the C<"rea">
(Raku Ecosystem Archive).

=head2 --eco-tests=[rea|fez]

Indicate that the test files (from the C<"t"> and C<"xt"> directories
of a distribution) in the local ecosystem cache (as generated by
L<C<Ecosystem::Cache>|https://raku.land/zef:lizmat/Ecosystem::Cache>)
should be searched.  If specified as a flag, will assume the C<"rea">
(Raku Ecosystem Archive).

=head2 --edit[=editor]

Indicate whether the patterns found should be fed into an editor for
inspection and/or changes.  Defaults to C<False>.  Optionally takes the
name of the editor to be used.  If no editor is specified, will use what
is in the C<EDITOR> environment variable.  If that is not specified either,
will call "vim".

Requires the L<C<Edit::Files>|https://raku.land/zef:lizmat/Edit::Files>
Raku module to be installed.

=head2 --encoding[=utf8-c8]

Indicate the encoding to be used when reading text files.  Defaults to
L<C<utf8-c8>|https://docs.raku.org/language/unicode#UTF8-C8>.  Other
encodings are e.g. C<utf8> and C<ascii>.

=head2 --eol=lf|cr|crlf

Only applicable if C<--csv-per-line> has been specified.  Indicate a
line ending different from the standard line ending assumed by the system.
Can be specified as C<lf> for a single LineFeed character, C<cr> for a
single CarriageReturn character, or C<crlf> for a combination of a
CarriageReturn and a LineFeed character.

=head2 --escape=char

Only applicable if C<--csv-per-line> has been specified.  Indicates the
escape character to be used to escape characters in a field.  Defaults to
B<double quote>.

=head2 --exec=invocation

If specified, indicates the name of a program and its arguments to be
executed. Any C<$_> in the invocation string will be replaced by the file
being checked. The file will be included if the program runs to a successful
conclusion.

=head2 --execute-raku[=code]

Flag or code specification.  When specified with a True value, will
use the pattern as the name of a script to execute.  If code is specified
will execute that code.  If the code consists of "-", then will read code
from STDIN to execute.  Any execution error's backtrace will be used
to produce a result with the lines of source code of that backtrace.

Can be used together with C<--context>, C<--before-context>,
C<--after-context>, C<--edit> and C<--vimgrep>.  Will assume a context of
2 lines if B<not> used in combination with C<--edit> or C<--vimgrep>,

If C<--verbose> is specified, will try to create an extended (--ll-exception)
backtrace.

=begin code :lang<bash>
# look at source of a stacktrace after running script
$ rak --execute-raku script

# inspect the source of a stacktrace in an editor
$ rak --execute-raku script --edit

# inspect a backtrace from execution of code read from STDIN
$ cat script | rak --execute-raku=-
=end code

=head2 --extensions=spec

Indicate the extensions of the filenames that should be inspected.
By default, only files with known extensions, will be searched.

Extensions can be specified as a comma-separated list of either a
a predefined group of extensions (indicated by C<#name>), a single
extension, or C<*> to indicate all known extensions.

=begin code :lang<bash>
# inspect files with extensions used by Raku and Perl
$ rak foo --extensions=#raku,#perl

# inspect files with presumable Markdown content
$ rak foo --extensions=md,markdown

# inspect files without extension
$ rak foo --extensions=

# inspect files without extension or with the extension "foo"
$ rak foo --extensions=,foo
=end code

Predefined groups are C<#raku>, C<#perl>, C<#cro>, C<#text>, C<#c>, C<#c++>,
C<#yaml>, C<#ruby>, C<#python>, C<#r>, C<#wl>, C<#html>, C<#markdown>, C<#js>, C<#json>,
C<#jsonl>, C<#csv>, C<#config>, and C<#text>.

The C<--list-known-extensions> argument can be used to see which predefined
groups of extensions are supported, and which extensions they cover.

=head2 --file=condition

If specified, indicates the C<Callable> that should return True to have a
file be included in the file selection process.  The basename of the file
will be passed as the only argument.  Defaults to C<True>, indicating that
all files should be included.

If C<--/file> is specified, then only directory paths will be accepted.
This only makes sense if C<--find> is also specified.

=head2 --file-separator-null

Flag.  Indicate to separate filenames by null bytes rather than newlines
if the C<--files-with-matches> or C<--files-without-matches> option are
specified with a C<True> value.

=head2 --files-from=filename

Indicate the path of the file to read filenames from instead of the
expansion of paths from any positional arguments.  "-" can be specified
to read filenames from STDIN.

=head2 --files-with-matches

Flag.  If specified, will only produce the filenames of the files in which
the pattern was found.  Defaults to C<False>.

=head2 --files-without-matches

Flag.  If specified, will only produce the filenames of the files in which
the pattern was B<not> found.  Defaults to C<False>.

=head2 --filesize=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The number of bytes of data
in the file, will be passed as the only argument.  See also C<--is-empty>.

=begin code :lang<bash>
# show files that consist of at 30 bytes
$ rak --find --filesize='* >= 30'
=end code

=head2 --find

Flag.  If specified, will B<not> look at the contents of the selected paths,
but instead consider the selected paths as lines in a virtual file.  And as
such will always only produce filenames.

=head2 --only-first[=N]

Indicate the B<overall> number of matches to show.  If specified without a
value, will default to B<1>.  Defaults to B<1000> if a human is watching,
otherwise defaults to returning all possible matches.  Can be used to tweak
search results, before letting it loose to get all possible results.

Special values that are allowed to produce all possible results are C<∞>
(aka C<221E INFINITY>), C<*> and C<Inf>.

=head2 --formula=[none]

Only applicable if C<--csv-per-line> has been specified.  If specified,
indicates the action to be taken when a field starts with an equal sign
(indicating a formula of some kind in many spreadsheets).  The following
values are recognized:

=table
  type   action
  -------------
  none   take not action, just pass on
  die    throw an exception
  diag   report line and position where formula was found
  empty  replace the formula by an empty string

=head2 --frequencies

Flag.  If specified, will produce a frequency table of the matches with
the most frequent match first.  Default is C<False>.  See also C<--unique>.
Usually used in conjunction with C<--matches-only> and/or C<Callable>
patterns returning something other than True/False/Nil/Empty.

=head2 --gid=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The numeric C<gid> of the file
will be passed as the only argument.  Can also be specified as a single
numeric argument.  See also C<--group>.

=begin code :lang<bash>
# show files of which the numeric group id is greater than 20
$ rak --find --gid='* > 20'

# show files of which the numeric group id is 20
$ rak --find --gid=20
=end code

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --group=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The name of the group
associated with the C<gid> of the file will be passed as the only argument.

Can also be specified as a list of comma separated names to (not) select on.
To select all names B<except> the listed named, prefix with a C<!>.

See also C<--gid>.  Requires the
L<P5getgrnam|https://raku.land/zef:lizmat/P5getgrnam> module to be installed.

=begin code :lang<bash>
# files of which the name associated with the user id starts with underscore
$ rak --find --group='*.starts-with("_")'

# show files of which the group is "staff"
$ rak --find --group=staff

# show files of which the group is NOT "staff"
$ rak --find --group='!staff'
=end code

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --group-matches

Flag.  Indicate whether matches of a file should be grouped together by
mentioning the filename only once (instead of on every line).  Defaults
to C<True> if a human is watching, else C<False>.

=head2 --hard-links=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The number of hard-links to
the file on the filesystem, will be passed as the only argument.

=head2 --has-setgid

Flag. If specified, will only select files that do have the SETGID bit set
in their attributes.  Use negation C<--/has-setgid> to only select files
that do B<not> have the SETGID bit set.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --has-setuid

Flag. If specified, will only select files that do have the SETUID bit set
in their attributes.  Use negation C<--/has-setuid> to only select files
that do B<not> have the SETUID bit set.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --headers

Only applicable when C<--csv-per-line> is also specified.  It defaults to
"auto".  It can have the following values:

=item --headers

Boolean True, same as "auto"

=item --/headers

Boolean False, assume comma separator and no header line, produce a list
of column values for each line in the CSV file.

=item --headers=auto

Automatically determine separator, first line is header with column names,
produce a hash with values keyed to column names for each line in the CSV
file.

=item --headers=skip

Assume the first line is a header, but skip it.  Produce a lust of column
values for each line in the CSV file.

=item --headers=uc

Same as "auto", but uppercase the column names found in the header line.

=item --headers=lc

Same as "auto", but lowercase the column names found in the header line.

=item --headers='<a b c>'

Specifies a list of column names to associate with columns, in order.
Assumes no header line is available.

=item --headers=':a<foo>, :b<bar>'

Indicates a list of C<Pair>s with column name mapping to use instead
of the column names found in the header line of the CSV file.

=item --headers='code'

Any Raku code that produces one of the above values.  Also supports a
C<Map> or C<Hash> instead of a list of C<Pair>s.

=begin code :lang<bash>
# Use uppercase column names
$ rak --csv-per-line --headers=uc '{.<FOO> if .<BAR> eq "foo"}' info.csv

# Use alternate column names in order of columns
$ rak --csv-per-line --headers='<a b>' '{.<a> if .<n> eq "foo"}' info.csv

# Use alternate column names using mapping
$ rak --csv-per-line --headers=':foo<a>, :bar<b>' '{.<a> if .<n> eq "foo"}' info.csv
=end code

=head2 --help[=area-of-interest]

Show argument documentation, possibly extended by giving the area of
interest, which are:

=item argument
=item code
=item content
=item debugging
=item examples
=item faq
=item filesystem
=item general
=item haystack
=item item
=item listing
=item option
=item pattern
=item philosophy
=item resource
=item result
=item special
=item string

If no area of interest is given, then the overview will be shown.

Any pattern specification will be used to search the help subjects, and only
show the logical paragraphs with matches.

=head2 --highlight

Flag.  Indicate whether the pattern should be highlighted in the line in
which it was found.  Defaults to C<True> if a human is watching (aka STDOUT
connected to a terminal), or C<--highlight-before> or C<highlight-after>
are explicitely specified, or C<False> otherwise.

=head2 --highlight--after[=string]

Indicate the string that should be used at the end of the pattern found in
a line.  Specifying implies C<--highlight>ing implicitely.  If C<--highlight>
or C<--highlight-before> are explicitely specified, will default to whatever
is specified with C<--highlight-before>, or to the ANSI code to end B<bold>.

=head2 --highlight--before[=string]

Indicate the string that should be used at the end of the pattern found in
a line.  Specifying implies C<--highlight>ing implicitly.  If C<highlight>
is explicitely specified, will default to the terminal code to start B<bold>.

=head2 --human

Flag.  Indicate that search results should be presented in a human readable
manner.  This means: filenames shown on a separate line, line numbers
shown, and highlighting performed.  Defaults to C<True> if C<STDOUT> is
a TTY (aka, someone is actually watching the search results), otherwise
defaults to C<False>.

=head2 --ignorecase

Flag.  If specified, indicates that any matching using a literal string or
a regex, should be done case insensitively.  Default is C<False>.

=head2 --ignoremark

Flag.  If specified, indicates that any matching using a literal string or
a regex, should be done without consideration of any accents.  Default is
C<False>.

=head2 --inode=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The inode number of the file
on the filesystem, will be passed as the only argument.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --invert-match

Flag.  If specified, will negate the result of any match if it has a logical
meaning:

=table
  given value        result
  -------------------------
  True               False
  False              True
  Nil                True
  Empty              True
  none of the above  just that

=head2 --is-empty

Flag. If specified, will only select files that do not contain any data.
Use negation C<--/is-empty> to only select files that B<do> contain data.
Special case of C<--filesize>.

=head2 --is-executable

Flag. If specified, will only select files that can be executed by the
current user.  Use negation C<--/is-executable> to only select files that
are B<not> executable by the current user.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-group-executable

Flag. If specified, will only select files that can be executed by members
of the group of the owner.  Use negation C<--/is-group-executable> to only
select files that are B<not> executable by the members of the group of the
owner.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-group-readable

Flag. If specified, will only select files that can be read by members of
the group of the owner.  Use negation C<--/is-group-readable> to only select
files that are B<not> readable by the members of the group of the owner.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-group-writable

Flag. If specified, will only select files that can be written to by members
of the group of the owner.  Use negation C<--/is-group-writable> to only
select files that are B<not> writable by the members of the group of the owner.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-moarvm

Flag.  If specified, will only select files that appear to be MoarVM
bytecode files. Defaults to C<False>.

=head2 --is-owned-by-group

Flag. If specified, will only select files that are owned by the group of
the current user.  Use negation C<--/is-owned-by-group> to only select files
that are B<not> owned by the group of the current user.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-owned-by-user

Flag. If specified, will only select files that are owned by current user.
Use negation C<--/is-owned-by-user> to only select files that are B<not>
owned by the current user.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-owner-executable

Flag. If specified, will only select files that can be executed by the owner.
Use negation C<--/is-owner-executable> to only select files that are B<not>
executable by the owner.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-owner-readable

Flag. If specified, will only select files that can be read by the owner.
Use negation C<--/is-owner-readable> to only select files that are B<not>
readable by the owner.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-owner-writable

Flag. If specified, will only select files that can be written to by the
owner.  Use negation C<--/is-owner-writable> to only select files that are
B<not> writable by the owner.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-pdf

Flag.  If specified, will only select files that appear to be PDF files.
Defaults to C<False>.

=head2 --is-readable

Flag. If specified, will only select files that can be read by the current
user.  Use negation C<--/is-readable> to only select files that are B<not>
readable by the current user.

=head2 --is-sticky

Flag. If specified, will only select files that do have the STICKY bit set
in their attributes.  Use negation C<--/is-sticky> to only select files that
do B<not> have the STICKY bit set.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-symbolic-link

Flag. If specified, will only select files that are symbolic links.  Use
negation C<--/is-symbolic-link> to only select files that are B<not>
symbolic links.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-text

Flag.  If specified, will only select files that appear to contain text
(rather than binary data).  Defaults to C<True> if no other file filter
has been specified, and C<--find> is not specified either.  Use negation
C<--/is-text> to only select files with binary data.

Note: support for searching for binary data is not yet implemented, so
C<--/is-text> can only be used in conjunction with --find.

=head2 --is-world-executable

Flag. If specified, will only select files that can be executed by anybody.
Use negation C<--/is-group-executable> to only select files that are B<not>
executable by anybody.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-world-readable

Flag. If specified, will only select files that can be read by anybody.
Use negation C<--/is-world-readable> to only select files that are B<not>
readable by anybody.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-world-writable

Flag. If specified, will only select files that can be written to by anybody.
Use negation C<--/is-world-writable> to only select files that can B<not> be
written to by anybody.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --is-writable

Flag. If specified, will only select files that can be written to by the
current user.  Use negation C<--/is-writable> to only select files that
can B<not> be written to by the current user.

=head2 --json-per-elem

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified,
indicates that each selected file will be interpreted as JSON, and if valid,
will then produce all elements of the outermost data structure to the
pattern for introspection.  If the data structure is a hash, then key/value
C<Pair>s will be produced.

If the Callable returns C<True>, the stringification of the element will
be produced.  If the returned value is a string, that string will be produced.
For example when searching the list of modules in the zef ecosystem (which
consists of an array of hashes):

=begin code :lang<bash>
# Show all defined "auth" values of top elemens in JSON file
$ rak '{ .<auth> // False }' META.json --json-per-elem
=end code

=head2 --json-per-file

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified,
indicates that each selected file will be interpreted as JSON, and if valid,
will then be given to the pattern for introspection.  If the Callable
returns C<True>, the filename will be produced.  If anything else is
returned, then the stringification of that object will be produced.  For
example:

=begin code :lang<bash>
# show the "auth" value from all JSON files
$ rak '*<auth> // False' --json-per-file
=end code

=head2 --json-per-line

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified,
indicates that each line from the selected files will be interpreted as
JSON, and if valid, will then be given to the pattern for introspection.
If the Callable returns C<True>, the filename and line number will be
produced.  If the returned value is anything else, then the stringification
of that object will be be produced.  For example:

=begin code :lang<bash>

# show the "auth" value from the JSON blob on each line
$ rak '{ $_ with .<auth> }' --json-per-line

=end code

=head2 --keep-meta

Flag.  Only applicable if C<--csv-per-line> has been specified.  If specified,
indicates that meta-information will be kept for each field, by presenting
each field as a C<CSV::Field|https://github.com/Tux/CSV/blob/master/doc/Text-CSV.md#csvfield>
object rather than as a string.  The most important methods that can be called
on a C<CSV::Field> object are:

=table
  method      meaning
  -------------------
  is-quoted   field was quoted
  is-binary   field contains undecodable data
  is-utf8     field contains decodable data beyond ASCII
  is-formula  field looks like it contains a spreadsheet formula

=head2 --list-custom-options

Flag.  If specified as the only option, will list all additional options
previously saved with C<--save>.

=begin code :lang<bash>
# show all of the custom options
$ rak --list-custom-options
fs: --'follow-symlinks'
im: --ignorecase --ignoremark
=end code

=head2 --list-expanded-options

Flag.  If specified, will show all actual options being activated after
having been recursively expanded, and then exit.  Intended as a debugging
aid if you have many custom options defined.

=begin code :lang<bash>
# show how custom option "--im" expands
$ rak --im --list-expanded-options
--ignorecase --ignoremark
=end code

=head2 --list-known-extensions

Flag.  If specified, will show all known extension groups and the extensions
they represent.  Intended as an informational aid.

=begin code :lang<bash>
# show the filename extensions that "rak" knows about
$ rak --list-known-extensions
       #c: c h hdl
     #c++: cpp cxx hpp hxx
  #config: ini
     #cro: (none) crotmp
     #csv: (none) csv psv tsv
    #html: htm html css
      #js: js ts tsx
    #json: json
   #jsonl: jsonl
#markdown: md markdown
    #perl: (none) pl pm t
  #python: py ipynb
       #r: (none) r R Rmd
    #raku: (none) raku rakumod rakutest rakudoc nqp t pm6 pl6 pod6 t6
    #ruby: rb
    #text: (none) txt
      #wl: (none) wl m wlt mt nb
    #yaml: yaml yml
=end code

=head2 --matches-only

Flag.  Indicate whether only the matched pattern should be produced, rather
than the line in which the pattern was found.  Defaults to C<False>.
Frequently used in conjunction with C<--per-file>.  Will show separated by
space if multiple matches are found on the same line.

=head2 --max-matches-per-file[=N]

Indicate the maximum number of matches that should be produced per file.
If specified as a flag, will assume B<1> for its value.  By default, will
produce B<all> possible matches in a file.

=head2 --mbc

Flag.  Indicates that a L<C<MoarVM::Bytecode>|https://raku.land/zef:lizmat/MoarVM::Bytecode>
object should be produced for each MoarVM bytecode file, to be presented
to the matcher.  Only makes sense if the pattern is a C<Callable>.  Will
also set the C<is-moarvm> flag to only select MoarVM bytecode files,
unless reading from STDIN.

Requires the L<C<MoarVM::Bytecode>|https://raku.land/zef:lizmat/MoarVM::Bytecode>
Raku module to be installed.

=head2 --mbc-frames

Flag.  Indicates that the frames in a MoarVM bytecode file should be
produced as a L<C<MoarVM::Bytecode::Frame>|https://raku.land/zef:lizmat/MoarVM::Bytecode#frame>
to the matcher.  Only makes sense if the pattern is a C<Callable>.  Will
also set the C<is-moarvm> flag to only select MoarVM bytecode files,
unless reading from STDIN.

Requires the L<C<MoarVM::Bytecode>|https://raku.land/zef:lizmat/MoarVM::Bytecode>
Raku module to be installed.

=head2 --mbc-strings

Flag.  Indicates that the strings in the string hap in a MoarVM bytecode
file should be produced to the matcher.  Will also set the C<is-moarvm>
flag to only select MoarVM bytecode files, unless reading from STDIN.

Requires the L<C<MoarVM::Bytecode>|https://raku.land/zef:lizmat/MoarVM::Bytecode>
Raku module to be installed.

=head2 ---meta-modified=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The modification time of meta
information of the file (number of seconds since epoch, as a C<Num> value)
will be passed as the only argument.

See "CHECKING TIMES ON FILES" for more information about features that
can be used inside the C<Callable>.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --mode=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The full numeric mode value
of the file on the filesystem, will be passed as the only argument.

=begin code :lang<bash>

# list files with sticky bit set
$ rak --find --mode='{ $_ +& 0o1000 }'

=end code

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --modifications

Indicate whether modifications with C<--modify-files> and C<--rename-files>
are allowed.  Defaults to C<True>, hence it will probably only be actually
used in the negation case: C<--no-modifications> or C<--/modifications>.
Intended to be used in cases where there is no complete control over the
arguments being specified, e.g. when being used through a web or chat-bot
interface.

=head2 --modified=condition

If specified, indicates the C<Callable> that should return True to include a
file in the selection of files to be checked.  The modification time of the
file (number of seconds since epoch, as a C<Num> value) will be passed as the
only argument.

See "CHECKING TIMES ON FILES" for more information about features that
can be used inside the C<Callable>.

=head2 --modify-files

Flag.  Only makes sense if the specified pattern is a C<Callable>.
Indicates whether the output of the pattern should be applied to the file
in which it was found.  Defaults to C<False>.

The C<Callable> will be called for each file (in sorted order) and each
line of the file, giving the line.  By default, the line will be presented
to the code B<without> its line ending.  You need to specify
C<--with-line-endings> if you want to have the line ending also.

The C<$*N> dynamic variable is available inside the C<Callable> and is
initialized to 0 (in case modifications require keeping numeric state
between calls).  It is then up to the C<Callable> to return:

=head3 False

Remove this line from the file.  NOTE: this means the exact C<False> value.

=head3 True

Keep this line unchanged the file.  NOTE: this means the exact C<True> value.

=head3 Nil

Keep this line unchanged the file.  NOTE: this means the exact C<Nil> value.

=head3 Empty

Keep this line unchanged the file.  NOTE: this means the exact C<Empty> value.
This is typically returned as the result of a failed condition.  For example,
only change the string "foo" into "bar" if the line starts with "#":

=begin code :lang<bash>
# replace "foo" by "bar" in all files
$ rak '*.subst("foo","bar")' --modify-files

# replace "foo" by "bar" in all comment lines
$ rak '{ .subst("foo","bar") if .starts-with("#") }' --modify-files
=end code

=head3 any other value

Inserts this value in the file instead of the given line.  The value can
either be a string, or a list of strings (which would add lines to the file).

=head2 --module=Foo

Indicate the Raku module that should be loaded.  Only makes sense if the
pattern is a C<Callable>.

=head2 --not=foo

Specify B<primary> pattern that should B<not> match to produce a hit.

=head2 --or=foo

Specify B<additional> pattern that should match to produce a hit.

=head2 --ornot=foo

Specify B<additional> pattern that should B<not> match to produce a hit.

=head2 --output-dir=directory

Specify the name of the directory to store the results in.  For each group,
a separate file will be created.  Usually used in conjunction with
C<--classify> or C<--categorize>, but can also be used for normal search
results.  In that case, the basename of a file with results, will be taken
as the name of the file to create in that output directory.  The directory
must B<not> exist beforehand.

=head2 --output-file=filename

Indicate the path of the file in which the result of the search should
be placed.  Defaults to C<STDOUT>.

=head2 --pager=name

Indicate the name (and arguments) of a pager program to be used to page
through the generated output.  Defaults to the C<RAK_PAGER> environment
variable.  If that isn't specified either, then no pager program will be
run.

=begin code :lang<bash>
# use the "more" pager to page the output
$ RAK_PAGER='more -r' rak foo

# use the "less" pager to page the output
$ rak foo --pager='less -r'
=end code

=head2 --paragraph-context

Flag.  Indicate all lines that are part of the same paragraph B<around>
any line that matches.  Defaults to C<False>.  Paragraph boundaries are:

=item the start of the file
=item an empty line
=item the end of the file

=head2 --passthru

Flag.  Indicate whether B<all> lines from source should be shown always.
Highlighting will still be performed, if so (implicitely) specified.

=begin code :lang<bash>
# watch a log file, and highlight a IP address 123.45.67.89
$ tail -f ~/access.log | rak --passthru 123.45.67.89
=end code

=head2 --passthru-context

Flag.  Indicate whether B<all> lines from source should be produced if at
least one line matches.  Highlighting will still be performed, if so
(implicitely) specified.

=head2 --paths=path1,path2

Indicates the path specification to be used instead of from any positional
arguments.  Multiple path specifications should be separated by comma's.

=head2 --paths-from=filename

Indicate the path of the file to read path specifications from instead of
from any positional arguments.  "-" can be specified to read path
specifications from STDIN.

=head2 --pattern=foo

Alternative way to specify the pattern to search for.  If (implicitly)
specified, will assume the first positional parameter specified is
actually a path specification, rather than a pattern.  This allows
the pattern to be saved with C<--save>, and thus freeze a specific
pattern as part of a custom option.

=head2 --patterns-from=file

Alternative way to specify one or more patterns to search for.  Reads the
indicated file and interprets each line as a pattern according to the rules
(implicitly) set with the C<--type> argument.  If the file specification is
C<"-">, then the patterns will be read from STDIN.

=head2 --pdf-info

Flag.  Indicates that the meta-info of any PDF file should be produced
as single hash to the matcher.  Only makes sense if the pattern is a
C<Callable>.  Will also set the C<is-pdf> flag to only select PDF files,
unless reading from STDIN.

Requires the L<C<PDF::Extract>|https://raku.land/zef:librasteve/PDF::Extract>
Raku module to be installed.

=head2 --pdf-per-file

Flag.  Indicates that any PDF file text contents should be produced as
single text to the matcher.  Will also set the C<is-pdf> flag to only
select PDF files, unless reading from STDIN.

Requires the L<C<PDF::Extract>|https://raku.land/zef:librasteve/PDF::Extract>
Raku module to be installed.

=head2 --pdf-per-line

Flag.  Indicates that any PDF file text contents should be produced as
lines to the matcher.  Will also set the C<is-pdf> flag to only select
PDF files, unless reading from STDIN.

Requires the L<C<PDF::Extract>|https://raku.land/zef:librasteve/PDF::Extract>
Raku module to be installed.

=head2 --per-file[=code]

Indicate whether matching should be done per file, rather than per line.
If specified as a flag, will slurp a file with the indicated C<--encoding>
and present that to the matcher.  Optionally takes a C<Callable>
specification: this will be given an C<IO::Path> object of the file:
whatever it produces will be presented to the matcher.  Usually used in
conjunction with C<--matches-only> and/or C<count-only>.

=begin code :lang<bash>
# look for foo in only the first 10 lines of each file
$ rak foo --per-file='*.lines(:!chomp).head(10).join'
=end code

=head2 --per-line[=code]

Indicate whether matching should be done per line.  If specified as a flag,
will read lines with the indicated C<--encoding> and present each line to the
matcher (which is actually the default if no action was specified).i

Optionally takes a C<Callable> specification: this will be given an C<IO::Path>
object of the file: that is then expected to produce lines that will be
presented to the matcher.

=begin code :lang<bash>
# look for foo in only the last 10 lines of each file
$ rak foo --per-line='*.lines.tail(10)'
=end code

=head2 --per-paragraph

Indicate whether matching should be done per paragraph.  It will read lines
with the indicated C<--encoding>, combine them into paragraphs and present
each paragraph to the matcher, with the line number of the start of the
paragraphs associated with it.

=head2 --progress

Flag.  If specified, will produce a progress indicator on STDERR that
indicates the number of files checked, number of lines checked and number
of matches, updated 5 times per second.  Defaults to C<False>.

=head2 --proximate=[N]

Indicates whether matched lines should be grouped together that are within
N lines of each other. This is useful for visually picking out matches that
appear close to other matches.  If specified as a flag, indicates a
proximation of B<1>.  Defaults to <0> otherwise (indicating no proximation
check should be performed).

=head2 --quietly

Flag.  Only makes sense if the pattern is a C<Callable>.  If specified,
will catch all B<warnings> that are emitted when executing the pattern's
C<Callable>.  Defaults to C<False>.

=head2 --quote=["]

Only applicable if C<--csv-per-line> has been specified.  Indicates the
character that should be used for quoting fields.  Defaults to B<double quote>.

=head2 --rak

Flag.  Intended for debugging purposes only.  When specified, will show the
named arguments sent to the C<rak> plumbing subroutine just before it isi
being called.

=head2 --rakudo-all

Indicate that B<all> the files recognized by the Rakudo cache (as generated
by L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>)
should be searched.

=head2 --rakudo-c

Indicate that the files recognized as C<C> programming language files by
the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-doc

Indicate that the files recognized as documentation files by the Rakudo
cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-java

Indicate that the files recognized as C<Java> programming language files
by the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-js

Indicate that the files recognized as C<Javascript> programming language
files by the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-nqp

Indicate that the files recognized as C<NQP> related files by the Rakudo
cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-perl

Indicate that the files recognized as C<Perl> programming language files
by the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-raku

Indicate that the files recognized as C<Raku> Programming Language files
by the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-shell

Indicate that the files recognized as shell scripts / batch files by
the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-test

Indicate that the files recognized as test related files by the Rakudo
cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --rakudo-yaml

Indicate that the files recognized as files containing YAML of some
sort by the Rakudo cache (as generated by
L<C<Rakudo::Cache>|https://raku.land/zef:lizmat/Rakudo::Cache>) should
be searched.

=head2 --recurse-unmatched-dir

Flag.  Indicate whether directories that didn't match the C<--dir>
specification, should be recursed into anyway.  Will not produce files
from such directories, but may recurse further if directories are
encountered.  Defaults to C<False>.

=head2 --recurse-symlinked-dir

Flag.  Indicate whether directories that are actually symbolic links,
should be recursed into.  Defaults to C<False>.

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --rename-files

Flag.  Only makes sense if the specified pattern is a C<Callable>.
Feeds all selected files, sorted by absolute path, as C<IO::Path> objects
to the pattern, and uses the result (if different from the original) as
the new name of the file.

The C<--dryrun> argument can be used to run through the whole process
B<except> doing actually any renaming.

The C<--verbose> argument can be used to get more verbose feedback on
the operation.

The C<Callable> will be called for each line, giving the file as an
C<IO::Path> object.  The C<$*N> dynamic variable is available inside the
C<Callable> and is initialized to 0.  It is then up to the C<Callable> to
return:

=head3 False

Don't change the name of the file  NOTE: this means the exact C<False> value.

=head3 True

Don't change the name of the file.  NOTE: this means the exact C<True> value.

=head3 Nil

Don't change the name of the file.  NOTE: this means the exact C<Nil> value.

=head3 Empty

Don't change the name of  the file.  NOTE: this means the exact C<Empty> value.
This is typically returned as the result of a failed condition.

=head3 any other value

Use this value as the new name of the file.  It can either be a string
or an C<IO::Path> object.  Only when the returned value is different from
the given value, will a rename actually be attempted.  To make this easier
on the user, any C<Str> returned, will be automatically converted to an
C<IO::Path> object before being compared using C<eqv>.

=begin code :lang<bash>
# change the extension of all .t files to .rakutest
$ rak '*.subst(/ \.t $/,".rakutest")' --rename-files

# Rename files with 3 digits word bounded with an interval of 10
$ rak '*.subst(/ << \d ** 3 >> /, { ($*N += 10).fmt("%03d") })' --rename-files
=end code

Note that files that are under git revision control will be renamed using
C<git mv>: if that fails for any reason, a normal rename will be performed.

=head2 --repository=dir

Indicate the directory that should be searched for Raku module loading.
Only makes sense if the pattern is executable code.

=head2 --save=shortcut-name

Save all options with the given name in the configuration file
(C<~/.rak-config.json>), and exit with a message that these options have
been saved with the given name.

This feature can used to both create shortcuts for specific (long) options,
or just as a convenient way to combine often used options, or both.

=begin code :lang<bash>
# save options as "--im"
$ rak --ignorecase --ignoremark --save=im
Saved option '--im' as: --ignorecase --ignoremark

# can use shortcut to --ignorecase --ignoremark
$ rak foo --im

# save options as "--rsd"
$ rak --recurse-symlinked-dir --save=rsd
Saved option '--rsd' as: --recurse-symlinked-dir

# save as "--B" with a default of '---'
$ rak --break='[---]' --save=B
Saved option '--B' as: --break='[---]'

# save as "--P" requiring a value
$ rak --pattern=! --save=P
Saved option '--P' as: --pattern='!'

# remove shortcut "--foo"
$ rak --save=foo
Removed configuration for 'foo'
=end code

Any options can be accessed as if it is a standard option.  Please note
that no validity checking on the options is being performed at the moment
of saving, as validity may depend on other options having been specified.

One option can be marked as requiring a value to be specified (with "!")
or have a default value (with "[default-value]").

To remove a saved set of options, use C<--save>=foo as the only option
to remove the "foo" set of options.

=head2 --sep=,

Only applicable if C<--csv-per-line> has been specified.  Indicates the
character to indicate the field separator.  Defaults to the B<comma>.

=head2 --show-blame

Flag.  Indicate whether to show C<git blame> information for matching lines
if possible, instead of just the line.  Defaults to C<False>.

Requires that the L<C<Git::Blame::File>|https://raku.land/zef:lizmat/Git::Blame::File> module is installed.

=head2 --show-item-number

Flag.  Indicate whether item numbers should be shown.  Defaults to C<True>.

=head2 --show-filename

Flag.  Indicate whether filenames should be shown.  Defaults to C<True>.

=head2 --shell=invocation

If specified, indicates the command(s) to be executed in a shell. Any C<$_>
in the invocation string will be replaced by the file being checked. The
file will be included if the shell command(s) run to a successful conclusion.

=head2 --silently[=out,err]

Flag and option.  Only applicable if the pattern is a C<Callable>.  Indicates
whether any output from the C<Callable> pattern should be caught.  Defaults
to C<False>.  If specified as a flag, will catch both STDOUT as well as
STDERR output from the pattern's execution.  When specified as an option,
will accept:

=table
  flag(s)  action
  ---------------
  out      only capture STDOUT
  err      only capture STDERR
  out,err  capture both STDIN as well as STDERR
  err,out  capture both STDIN as well as STDERR

=head2 --smartcase

Flag.  An intelligent version of C<--ignorecase>.  If the pattern does
B<not> contain any uppercase letters, it will act as if C<--ignorecase>
was specified.  Otherwise it is ignored.

=head2 --smartmark

Flag.  An intelligent version of C<--ignoremark>.  If the pattern does
B<not> contain any accented letters, it will act as if C<--ignoremark>
was specified.  Otherwise it is ignored.

=head2 --sourcery

Flag.  Mainly intended for Raku Programming Language core developers.
If specified, indicates that the pattern should be interpreted as code
specifying a simple call to a subroutine, or a simple call to a method,
optionally with arguments.  The search result will then contain the source
locations of subroutine / method that is expected to be able to handle that
call.

Compatible with the C<--edit>, C<--vimgrep> and the implicit C<per-line>
option.

=begin code :lang<bash>
# edit the location(s) of the "say" sub handling a single string
$ rak --sourcery 'say "foo"' --edit
=end code

Requires the L<C<sourcery>|https://raku.land/zef:lizmat/sourcery> module
to be installed.

=head2 --stats

Flag.  Also show statistics about the search operation after having shown
the full search result.

=head2 --stats-only

Flag.  B<Only> show statistics about the search operation.  See also
C<--count-only>.

=head2 --strict

Flag. Only applicable if C<--csv-per-line> has been specified.  If
specified, then each line in the CSV file B<must> have the same number
of fields.  Default is to allow different numbers of fields.

=head2 --summary-if-larger-than=N

Indicate the maximum size a line may have before it will be summarized.
Defaults to C<160> if C<STDOUT> is a TTY (aka, someone is actually watching
the search results), otherwise defaults to C<Inf> effectively (indicating
no summarization will ever occur).

=head2 --type=string

The C<--type> argument indicates how any pattern, as specified on the
commmand line, or from previously saved options, should be interpreted.
If not specified specified, will assume C<auto>.

The following strings can be specified:

=head3 auto

If C<--type=auto> is (implicitely) specified, will look for cues in a
specified pattern to understand what functionality is requested.  See
the L<pattern> for more information.

=head3 regex

If C<--type=regex> is specified, then a pattern will be interpreted as a
regex, as if it was surrounded by slashes.

=head3 code

If C<--type=code> is specified, then a pattern will be interpreted as Raku
source code, as if it was surrounded by curly braces.

=head3 json-path

If C<--type=json-path> is specified, then a pattern will be interpreted as
a C<JSON path>.  Only makes sense when used together with C<--json-per-file>,
C<--json-per-line> or C<--json-per-elem>.  Requires the
L<C<JSON::Path>|https://raku.land/cpan:JNTHN/JSON::Path> module to be installed.

=head3 contains

If C<--type=contains> is specified, then a pattern will be interpreted as a
literal string, while honouring any C<--smartcase>, C<--smartmark>,
C<--ignorecase> and C<--ignoremark> specifications.

=head3 words

If C<--type=words> is specified, then a pattern will be interpreted as a
literal string that should be bounded by word boundares at both ends,
while honouring any C<--smartcase>, C<--smartmark>, C<--ignorecase> and
C<--ignoremark> specifications.

=head3 starts-with

If C<--type=starts-with> is specified, then a pattern will be interpreted as
a literal string that should occur at the B<start> of a line, while honouring
any C<--smartcase>, C<--smartmark>, C<--ignorecase> and C<--ignoremark>
specifications.

=head3 ends-with

If C<--type=ends-with> is specified, then a pattern will be interpreted as
a literal string that should occur at the B<end> of a line, while honouring
any C<--smartcase>, C<--smartmark>, C<--ignorecase> and C<--ignoremark>
specifications.

=head3 equal

If C<--type=equal> is specified, then a pattern will be interpreted as a
literal string that should be B<equal> to the line, while honouring
any C<--smartcase>, C<--smartmark>, C<--ignorecase> and C<--ignoremark>
specifications.

=head2 --trim

Flag.  Indicate whether lines that have the pattern, should have any
whitespace at the start and/or end of the line removed.  Defaults to
C<True> if no context for lines was specified, else defaults to C<False>.

=head2 --uid=condition

If specified, indicates the C<Callable> that should return C<True> to include
a file in the selection of files to be checked.  The numeric C<uid> of the
file will be passed as the only argument.  Can also be specified as a single
numeric argument.  See also C<--user>.

=begin code :lang<bash>
# select files of which the numeric user id is greater than 500
$ rak --find --uid='* > 500'

# select files of which the numeric user id is 501
$ rak --find --uid=501
=end code

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --under-version-control[=git]

Indicate whether to only select files that are under some form of version
control.  If specified as a flag, will assume files that are under C<git>
version control.  Can also specify the name of the version control system
as the value: currently only B<git> is supported.

=head2 --unicode

Flag.  If specified, will search the unicode database for defined codepoints
by name.  Default is C<False>.

=head2 --unique

Flag.  If specified, will only produce unique lines of output.  Default is
C<False>.  See also C<--frequencies>.

=head2 --user=condition

If specified, indicates the C<Callable> that should return C<True> to include
a file in the selection of files to be checked.  The user name associated
with the C<uid> of the file will be passed as the only argument.

Can also be specified as a list of comma separated names to (not) select on.
To select all names B<except> the listed named, prefix with a C<!>.

See also C<--uid>.  Requires the
L<P5getpwnam|https://raku.land/zef:lizmat/P5getpwnam> module to be installed.

=begin code :lang<bash>
# files of which the name associated with the user id starts with underscore
$ rak --find --user='*.starts-with("_")'

# select files of which the owner is liz or wendy
$ rak --find --user=liz,wendy

# select files of which the owner is NOT liz or wendy
$ rak --find --user='!liz,wendy'
=end code

NOTE: support of this feature depends on Raku supporting that feature on
the current operating system.

=head2 --version

Flag.  If the only argument, shows the name and version of the script, and
the system it is running on.  Additionally specify C<--verbose> to see more
information.

=head2 --vimgrep

Flag.  If specified, will output search results in the format
"filename:linenumber:column:line".  This allows integration with the
C<:grep> action in vim-like editors.

=head1 CHECKING TIMES ON FILES

The C<--accessed>, C<--created>, C<--modified> and C<--meta-modified>
options expect C<Callable> to perform the check to include a file in the
search process.  It is passed the B<epoch> (number of seconds since
1 January 1970 UTC) value of the file being checked for the indicated
option, and it should return C<True> to include that file in any search.

To facilitate checks, some extra features are activated for these
C<Callable>s, allowing you to more easily craft your conditions.

=head2 Automatic conversion to epoch

In Raku, the C<.accessed>, C<.created>, C<.changed> and C<.modified>
methods on the C<IO::Path> object return
L<C<Instant>|https://docs.raku.org/type/Instant> objects, which are
atomic time rather than epoch.  Within these special C<Callables>,
these values are automatically converted to epoch values, to ease
comparisons.

=head2 Specifying some time ago

Within these special C<Callable>s, one can also indicate an epoch
value in the past by using the C<.ago> method in a specially formatted
string.  This string is formatted similarly to time specifications of
the Unix C<find> command: one of more digits followed by "s" for
seconds, "m" for minutes, "h" for hours, "d" for days and "w" for weeks.
"+" and "-" may also be used, but do not have any special meaning other
than negating the value they apply to.

=head2 On method naming

For C<rak> it was decided to name the option for checking the meta
information of a file as C<--meta-modified>.  In Raku, the associated
method on the C<IO::Path> object is (probably for historical reasons)
called C<.changed>.  To facilitate the creation of the C<Callable>s
for these options, one can use both C<.meta-modified> as well as
C<.changed> as methods.

=head2 Examples

=begin code :lang<bash>
# select all files that were modified later than an hour ago
$ rak --find --modified='* > "1h".ago'

# select all files that were created before 2.5 hours ago
$ rak --find --created='* < "2h30m".ago'

# select all files that were modified after "Changes" was created
$ rak --find --modified='* > "Changes".IO.created'
=end code

=head1 JSON PATH SUPPORT

=begin table :caption<Supported JSON path syntax>

  expression  meaning
  -------------------
  $           root node
  .key        index hash key
  ['key']     index hash key
  [2]         index array element
  [0,1]       index array slice
  [4:5]       index array range
  [:5]        index from the beginning
  [-3:]       index to the end
  .*          index all elements
  [*]         index all elements
  [?(expr)]   filter on Raku expression
  ..key       search all descendants for hash key

=end table

A query that is not rooted from $ or specified using .. will be evaluated
from the document root (that is, same as an explicit $ at the start).

=head4 Full Raku support

The C<jp:path> and C<--type=json-path> syntax are actually syntactic sugar
for calling a dedicated C<jp> macro that takes an unquoted JSON path as its
argument, and returns an instantiated C<JP> object.

This means that:

=begin code :lang<bash>
$ rak --json-per-file jp:foo
$ rak --json-per-file --type=json-path foo
=end code

are a different way of saying:

=begin code :lang<bash>
$ rak --json-per-file '{ jp("path").Slip }'
=end code

using the "pattern is Raku code" syntax.

The following methods can be called on the C<JP> object:

=table
  method             selected
  ---------------------------
  .value             The first selected value.
  .values            All selected values as a Seq.
  .paths             The paths of all selected values as a Seq.
  .paths-and-values  Interleaved selected paths and values.

Without listing all of the methods that can be called on the C<JP> object,
one should note that all efforts have been made to make the C<JP> object
act like a C<Seq>.

=head1 AUTHOR

Elizabeth Mattijsen <liz@raku.rocks>

Source can be located at: https://github.com/lizmat/App-Rak .
Comments and Pull Requests are welcome.

If you like this module, or what I’m doing more generally, committing to a
L<small sponsorship|https://github.com/sponsors/lizmat/>  would mean a great
deal to me!

=head1 COPYRIGHT AND LICENSE

Copyright 2022, 2023, 2024, 2025, 2026 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under
the Artistic License 2.0.

=end pod

# vim: expandtab shiftwidth=4
