=begin pod

=head1 NAME

rak - plumbing to be able to look for stuff

=head1 NOTE

If you are here looking for the C<rak> command-line interface, then
you should look at:
L<App::Rak|https://raku.land/zef:lizmat/App::Rak> or
L<App::Rak::Complete|https://raku.land/zef:lizmat/App::Rak::Complete>.

If you are interested in the underlying search logic that C<App::Rak>
provides and want to use that in a more customized environment, then
please read on!

=head1 SYNOPSIS

=begin code :lang<raku>
use rak;

# look for "foo" in all .txt files from current directory
my $rak = rak / foo /, :file(/ \.txt $/);

# show results
for $rak.result -> (:key($path), :value(@found)) {
    if @found {
        say "$path:";
        say .key ~ ':' ~ .value for @found;
    }
}
=end code

=head1 DESCRIPTION

The C<rak> subroutine provides a mostly abstract core search (plumbing)
functionality to be used by modules such as (porcelain) C<App::Rak>.

=head1 THEORY OF OPERATION

The C<rak> subroutine basically goes through 6 steps to produce a
C<Rak> object.  Any execution error will be caught and made harmless
and inspectable with the C<.exception> method on the C<Rak> object.

This behaviour can be adapted:

=table
  argument    meaning
  -------------------------------
  dont-catch  do *not* catch exception, immediately throw

=head3 1. Acquire sources

The first step is determining the objects that should be searched
for the specified pattern.  If an object is a C<Str>, it will be
assumed that it is a path specification of a file to be searched in
some form and an C<IO::Path> object will be created for it.

Related named arguments are (in alphabetical order):

=table
  argument                meaning
  -------------------------------
  :dir                    filter for directory basename check to include
  :file                   filter for file basename check to include
  :files-from             file containing filenames as source
  :ioify                  code to create IO::Path-like objects with
  :paths                  paths to recurse into if directory
  :paths-from             file containing paths to recurse into
  :recurse-symlinked-dir  recurse into symlinked directories
  :recurse-unmatched-dir  recurse into directories not matching :dir
  :sources                list of objects to be considered as source
  :under-version-control  only include paths under version control

The result of this step, is a (potentially lazy and hyperable)
sequence of objects.

=head3 2. Filter applicable objects

Filtering may occur using hypering, depending on these arguments:

=table
  argument  meaning
  -------------------------------
  :batch    number of items per thread at a time
  :degree   maximum number of threads

Filter down the list of sources from step 1 on any additional filesystem
related properties.  This assumes that the list of objects created are
strings of absolute paths to be checked (except where otherwise indicated).

=table
  argument              meaning
  -------------------------------
  :accept               given an IO::Path, is path acceptable
  :accessed             when was path last accessed
  :blocks               number of filesystem blocks
  :created              when was path created
  :deny                 given an IO::Path, is path NOT acceptable
  :device-number        device number on which path is located
  :exec                 run program, include if successful
  :filesize             size of the path in bytes
  :gid                  numeric gid of the path
  :hard-links           number of hard-links to path on filesystem
  :has-setgid           has SETGID bit set in attributes
  :has-setuid           has SETUID bit set in attributes
  :inode                inode of path on filesystem
  :is-empty             is path empty (filesize == 0)
  :is-executable        is path executable by current user
  :is-group-executable  is path executable by group
  :is-group-readable    is path readable by group
  :is-group-writable    is path writable by group
  :is-moarvm            is path a MoarVM bytecode file
  :is-owned-by-group    is path owned by group of current user
  :is-owned-by-user     is path owned by current user
  :is-owner-executable  is path executable by owner
  :is-owner-readable    is path readable by owner
  :is-owner-writable    is path writable by owner
  :is-pdf               is path a PDF file
  :is-readable          is path readable by current user
  :is-sticky            has STICKY bit set in attributes
  :is-symbolic-link     is path a symbolic link
  :is-text              does path contains text?
  :is-world-executable  is path executable by any user
  :is-world-readable    is path readable by any user
  :is-world-writable    is path writable by any user
  :is-writable          is path writable by current user
  :meta-modified        when meta information of path was modified
  :mode                 the mode of the path
  :modified             when path was last modified
  :shell                run shell command, include if successful
  :uid                  numeric uid of path

The result of this step, is a (potentially lazy and hyperable)
sequence of objects.

=head3 3. Produce items to search in (apply transformers)

The third step is to create the logic for creating items to
search in from the objects in step 2.  If search is to be done
per object, then C<.slurp> is called on the object.  Otherwise
C<.lines> is called on the object.  Unless one provides their
own logic for producing items to search in.

Related named arguments are (in alphabetical order):

=table
  argument             meaning
  -----------------------------
  :encoding            encoding to be used when creating items
  :find                map sequence of step 1 to item producer
  :produce-one         produce one item per given source
  :produce-many        produce zero or more items by given source
  :produce-many-pairs  produce zero or more items by given source as pairs
  :omit-item-number    do not store item numbers in result
  :with-line-ending    produce lines with line endings

The result of this step, is a (potentially lazy and hyperable)
sequence of objects.

=head3 4. Create logic for matching

Take the logic of the pattern C<Callable>, and create a C<Callable> to
do the actual matching with the items produced in step 3.

Related named arguments are (in alphabetical order):

=table
  argument       meaning
  ----------------------
  :invert-match  invert the logic of matching
  :old-new       produce pairs of old/new state
  :quietly       absorb any warnings produced by the matcher
  :silently      absorb any output done by the matcher
  :stats         produce results and full statistics
  :stats-only    don't produce results, just statistics

=head3 5. Create logic for running

Take the matcher logic of the C<Callable> of step 4 and create a runner
C<Callable> that will produce the items found and their possible context
(such as extra items before or after).  Assuming no context, the runner
changes a return value of C<False> from the matcher into C<Empty>, a
return value of C<True> in the original item, and passes through any other
value.

Related named arguments are (in alphabetical order):

=table
  argument                 meaning
  --------------------------------
  :also-first              initial items to show if there is a match
  :always-first            initial items to show always
  :after-context           number of items to show after a match
  :before-context          number of items to show before a match
  :context                 number of items to show around a match
  :paragraph-context       items around match until false item
  :passthru-context        pass on *all* items if there is a match
  :max-matches-per-source  max # of matches per source
  :passthru                pass on *all* items always

Matching items are represented by C<PairMatched> objects, and items that
have been added because of the above context arguments, are represented by
C<PairContext> objects.  Unless C<:omit-item-number> has been specified
with a trueish value, in which case items will always be just a string,
whether they matched or not (if part of a context specification).

=head3 6. Run the sequence(s)

The final step is to take the C<Callable> of step 5 and run that
repeatedly on the sequence of step 3.  Make sure any phasers
(C<FIRST>, C<NEXT> and C<LAST>) are called at the appropriate
time in a thread-safe manner.  Inside the C<Callable> of step 5,
the dynamic variable C<$*SOURCE> will be set to the source of
the items being checked.

Either produces a sequence in which the key is the source, and the
value is a C<Slip> of C<Pair>s where the key is the item-number and
the value is item with the match, or whatever the pattern matcher
returned.

Or, produces sequence of whatever a specified mapper returned
and/or with uniqueifying enabled.

Related named arguments are (in alphabetical order):

=table
  argument               meaning
  ------------------------------
  :categorize            classify items according to zero or more keys
  :classify              classify items according to a single key
  :eager                 produce all results before creating Rak object
  :frequencies           produce items and their frequencies
  :map-all               also call mapper if a source has no matches
  :mapper                code to map results of a single source
  :progress              code to show progress of running
  :sort                  sort the result of :unique
  :sort-sources          sort the sources before processing
  :sources-only          only produce the source of any match
  :sources-without-only  produce the source without any match
  :unique                only produce unique items

=head1 EXPORTED CLASSES

=head2 Rak

The return value of a C<rak> search.  Contains the following attributes:

=head3 completed

A C<Bool> indicating whether the search has already been completed.

=head3 exception

Any C<Exception> object that was caught.

=head3 nr-changes

Number of items (that would have been) changed.

=head3 nr-items

Number of items inspected.

=head3 nr-matches

Number of items that matched.

=head3 nr-passthrus

Number of items that have passed through.

=head3 nr-sources

Number of sources seen.

=head3 result

A C<Seq> with search results.  This could be a lazy C<Seq> or a C<Seq> on
a fully vivified C<List>.

=head3 stats

A C<Map> with any statistics collected (so far, in case an exception was
thrown).  If the C<Map> is not empty, it contains the following keys:

=table
  argument               meaning
  ------------------------------
  nr-sources    number of sources seen
  nr-items      number of items inspected
  nr-matches    number of items that matched
  nr-passthrus  number of items that have passed through
  nr-changes    number of items that would have been changed

If the C<Map> is empty, then no statistics (other than C<nr-sources>) have
been collected.

Note that if the result is lazy, then the statistics won't be complete until
every result has been processed.

=head2 PairContext

A subclass of C<Pair> of which both the C<matched> B<and> C<changed> method
return C<False>.  Used for non-matching items when item-numbers are
required to be returned and a certain item context was requested.

=head2 PairMatched

A subclass of C<PairContext> of which the C<matched> method returns
C<True>, but the C<changed> method returns C<False>.  Used for matching
items when item-numbers are required to be returned.

=head2 PairChanged

A subclass of C<PairMatched> of which the C<matched> B<and> C<changed> method
return C<True>.  Used for changed items when item-numbers are required to
be returned.

=head2 Progress

Passed to the C<:progress> C<Callable> 5 times per second while searching
is taking place.  It provides several methods that allow a search application
to show what is going on.

=head3 nr-changes

Number of items (that would have been) changed.  Continuously updated
if the search has not been completed yet.

=head3 nr-items

Number of items inspected.  Continuously updated if the search has not
been completed yet.

=head3 nr-matches

Number of items that matched.  Continuously updated if the search has
not been completed yet.

=head3 nr-passthrus

Number of items that have passed through.  Continuously updated if the
search has not been completed yet.

=head3 nr-sources

Number of sources seen.  Continuously updated if the search has not been
completed yet.

=head1 EXPORTED SUBROUTINES

=head2 rak

The C<rak> subroutine takes a C<Callable> (or C<Regex>) pattern as the
only positional argument and quite a number of named arguments.  Or it
takes a C<Callable> (or C<Regex>) as the first positional argument for
the pattern, and a hash with named arguments as the second positional
argument.  In the latter case, the hash will have the arguments removed
that the C<rak> subroutine needed for its configuration and execution.

=head3 Return value

A C<Rak> object (see above) is always returned.  The object
provides three attributes: C<result> (with the result C<Iterable>),
C<completed> (a Bool indicating whether all searching has been done
already), and C<exception> (any C<Exception> object or C<Nil>).

Additionally it provides five methods that allow you to monitor
progress and/or provide statistics at the end of a search.  They are:
C<nr-sources>, C<nr-items>, C<nr-matches>, C<nr-changes>, C<nr-passthrus>.

=head4 Result Iterable

If the C<:unique> argument was specified with a trueish value, then
the result C<Iterable> will just produce the unique values that were
either explicitely returned by the matcher, or the unique items that
matched.

Otherwise the value is an C<Iterable> of C<Pair>s which contain the
source object as key (by default the absolute path of the file in
which the pattern was found).

If there was only one item produced per source, then the value will
be that value, or whatever was produced by the matching logic.

Otherwise the value will be a C<Slip>.  If no item numbers were
requested, each element contains the result of matching.  If
item-numbers were requested, each element is a C<Pair>, of which
the key is the item-number where the pattern was found, and the value
is the product of the search (which, by default, is the item in which
the pattern was found).

In a graph:

=begin code

rak(...)
 |- Rak
     |- exception: Exception object or Nil
     |- nr-sources: number of sources seen
     |- nr-items: number of items seen
     |- nr-matches: number of matches seen
     |- nr-changes: number of changes (that could be) done
     |- nr-passthrus: number of passthrus done
     |- completed: Bool whether all searching done already
     |- result: Iterable
          |- Pair
          |   |- key: source object
          |   |- value:
          |        |- Slip
          |        |   |- PairMatched|PairContext
          |        |   |   |- key: item-number
          |        |   |   \- value: match result
          |        |   or
          |        |   \- match result
          |        or
          |        \- single item match result
          or
          \- unique match result

=end code

=head3 Named Arguments

The following named arguments can be specified (in alphabetical
order):

=head4 :accept(&filter)

If specified, indicates a C<Callable> filter that will be given an
C<IO::Path> of the path.  It should return C<True> if the path is
acceptable.

=head4 :accessed(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<access> time of the path.  The C<Callable> is
passed a C<Num> value of the access time (number of seconds since epoch)
and is expected to return a trueish value to have the path be considered
for further selection.

=head4 :after-context(N)

Indicate the number of items that should also be returned B<after>
an item with a pattern match.  Defaults to B<0>.

=head4 :also-first(N)

Indicate the number of initial items to be produced B<if> there is an
item with a pattern match.  Defaults to B<0>.  If specified as a flag,
will assume B<1>.

=head4 :always-first(N)

Indicate the number of initial items to be B<always> be produced
regardless whether there is an item with a pattern match or not.
Defaults to B<0>.  If specified as a flag, will assume B<1>.

=head4 :batch(N)

When hypering over multiple cores, indicate how many items should be
processed per thread at a time.  Defaults to whatever the system
thinks is best (which B<may> be sub-optimal).

=head4 :before-context(N)

Indicate the number of items that should also be returned B<before>
an item with a pattern match.  Defaults to B<0>.

=head4 :blocks(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<number of blocks> used by the path on the filesystem
on which the path is located.  The C<Callable> is passed the number of blocks
of a path and is expected to return a trueish value to have the path be
considered for further selection.

=head4 :categorize(&categorizer)

If specified, indicates the C<Callable> that should return zero or more
keys for a given item to have it categorized.  This effectively replaces
the source if an item by any of its key in the result.  The result will
contain the key/item(s) pairs ordered by most to least number of items
per key.

=head4 :classify(&classifier)

If specified, indicates the C<Callable> that should return a key for
a given item to have it classified.  This effectively replaces the
source if an item by its key in the result.  The result will contain
the key/item(s) pairs ordered by most to least number of items per key.

=head4 :context(N)

Indicate the number of items that should also be returned around
an item with a pattern match.  Defaults to B<0>.

=head4 :created(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<creation> time of the path.  The C<Callable> is
passed a C<Num> value of the creation time (number of seconds since epoch)
and is expected to return a trueish value to have the path be considered
for further selection.

=head4 :degree(N)

When hypering over multiple cores, indicate the maximum number of
threads that should be used.  Defaults to whatever the system
thinks is best (which B<may> be sub-optimal).

=head4 :deny(&filter)

If specified, indicates a C<Callable> filter that will be given an
C<IO::Path> of the path.  It should return C<True> if the path is
B<NOT> acceptable.

=head4 :device-number(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<device number> of the path.  The C<Callable> is
passed the device number of the device on which the path is located and is
expected to return a trueish value to have the path be considered for further
selection.

=head4 :dir(&dir-matcher)

If specified, indicates the matcher that should be used to select
acceptable directories with the C<paths> utility.  Defaults to C<True>
indicating B<all> directories should be recursed into.  Applicable
for any situation where C<paths> is used to create the list of files
to check.

=head4 :dont-catch

Flag.  If specified with a trueish value, 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.

=head4 :eager

Flag.  If specified with a trueish value, will B<always> produce B<all>
results before returning the C<Rak> object.  Defaults to C<False>,
making result production lazy if possible.

=head4 :encoding("utf8-c8")

When specified with a string, indicates the name of the encoding
to be used to produce items to check (typically by calling
C<lines> or C<slurp>).  Defaults to C<utf8-c8>, the UTF-8
encoding that is permissive of encoding issues.

=head4 :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.

=head4 :file(&file-matcher)

If specified, indicates the matcher that should be used to select
acceptable files with the C<paths> utility.  Defaults to C<True>
indicating B<all> files should be checked.  Applicable for any
situation where C<paths> is used to create the list of files to
check.

If the boolean value C<False> is specified, then only directory
paths will be produced.  This only makes sense if C<:find> is also
specified.

=head4 :filesize(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<number of bytes> of the path.  The C<Callable> is
passed the number of bytes of a path and is expected to return a trueish
value to have the path be considered for further selection.

=head4 :files-from($filename)

If specified, indicates the name of the file from which a list
of files to be used as sources will be read.

=head4 :find

Flag.  If specified, maps the sources of items into items to search.

=head4 :frequencies

Flag.  If specified, produces key/value C<Pair>s in which the key is the
item, and the value is the frequency with which the item was seen.

=head4 :gid(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<gid> of the path.  The C<Callable> is passed the
numeric gid of a path and is expected to return a trueish value to have the
path be considered for further selection.  See also C<owner> and C<group>
filters.

=head4 :hard-links(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<number of hard-links> of the path.  The C<Callable>
is passed the number of hard-links of a path and is expected to return a
trueish value to have the path be considered for further selection.

=head4 :has-setgid

Flag.  If specified, indicates paths that have the SETGID bit set in
their attributes, are (not) acceptable for further selection.  Usually
only makes sense when uses together with C<:find>.

=head4 :has-setuid

Flag.  If specified, indicates paths that have the SETUID bit set in
their attributes, are (not) acceptable for further selection.  Usually
only makes sense when uses together with C<:find>.

=head4 :inode(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<inode> of the path.  The C<Callable> is passed the
inode of a path and is expected to return a trueish value to have the path be
considered for further selection.

=head4 :invert-match

Flag. If specified with a trueish value, will negate the return
value of the pattern if a C<Bool> was returned.  Defaults to
C<False>.

=head4 :ioify(&coercer)

If specified, indicates the C<Callable> that will be called with a path
and which should return an object on which C<.lines> and C<.slurp> can be
called.  Defaults to C<*.IO>, creating an C<IO::Path> object by default.

=head4 :is-empty

Flag.  If specified, indicates paths, that are empty (aka: have a filesize
of 0 bytes), are (not) acceptable for further selection.  Usually only
makes sense when uses together with C<:find>.

=head4 :is-executable

Flag.  If specified, indicates paths, that are B<executable> by the current
B<user>, are (not) acceptable for further selection.

=head4 :is-group-executable

Flag.  If specified, indicates paths, that are B<executable> by the current
B<group>, are (not) acceptable for further selection.

=head4 :is-group-readable

Flag.  If specified, indicates paths, that are B<readable> by the current
B<group>, are (not) acceptable for further selection.

=head4 :is-group-writable

Flag.  If specified, indicates paths, that are B<writable> by the current
B<group>, are (not) acceptable for further selection.

=head4 :is-moarvm

Flag.  If specified, indicates only paths that are C<MoarVM> bytecode
files are (not) acceptable for further selection.

=head4 :is-owned-by-group

Flag.  If specified, indicates only paths that are B<owned> by the B<group>
of the current user, are (not) acceptable for further selection.

=head4 :is-owned-by-user

Flag.  If specified, indicates only paths that are B<owned> by the current
B<user>, are (not) acceptable for further selection.

=head4 :is-owner-executable

Flag.  If specified, indicates paths, that are B<executable> by the owner,
are (not) acceptable for further selection.

=head4 :is-owner-readable

Flag.  If specified, indicates paths, that are B<readable> by the owner,
are (not) acceptable for further selection.

=head4 :is-owner-writable

Flag.  If specified, indicates paths, that are B<writable> by the owner,
are (not) acceptable for further selection.

=head4 :is-pdf

Flag.  If specified, indicates only paths that are C<PDF> files are
(not) acceptable for further selection.

=head4 :is-readable

Flag.  If specified, indicates paths, that are B<readable> by the current
B<user>, are (not) acceptable for further selection.

=head4 :is-sticky

Flag.  If specified, indicates paths that have the STICKY bit set in
their attributes, are (not) acceptable for further selection.  Usually
only makes sense when uses together with C<:find>.

=head4 :is-symbolic-link

Flag.  If specified, indicates only paths that are symbolic links,
are (not) acceptable for further selection.

=head4 :is-text

Flag.  If specified, indicates only paths that contain text are (not)
acceptable for further selection.

=head4 :is-world-executable

Flag.  If specified, indicates paths, that are B<executable> by any user
or group, are (not) acceptable for further selection.

=head4 :is-world-readable

Flag.  If specified, indicates paths, that are B<readable> by any user
or group, are (not) acceptable for further selection.

=head4 :is-world-writeable

Flag.  If specified, indicates paths, that are B<writable> by any user
or group, are (not) acceptable for further selection.

=head4 :is-writable

Flag.  If specified, indicates paths, that are B<writable> by the current
B<user>, are (not) acceptable for further selection.

=head4 :mapper(&mapper)

If specified, indicates the C<Callable> that will be called (in a
thread-safe manner) for each source, with the matches of that source.
The C<Callable> is passed the source object, and a list of matches,
if there were any matches.  If you want the C<Callable> to be called
for every source, then you must also specify C<:map-all>.

Whatever the mapper C<Callable> returns, will become the result of the
call to the C<rak> subroutine.  If you don't want any result to be
returned, you can return C<Empty> from the mapper C<Callable>.

=head4 :map-all

Flag.  If specified with a trueish value, will call the mapper logic, as
specified with C<:mapper>, even if a source has no matches.  Defaults to
C<False>.

=head4 :max-matches-per-source(N)

Indicate the maximum number of items that may be produce per source.
Defaults to B<all> (which can also be specified by a falsish value).

=head4 :meta-modified(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<modification> time of the path.  The C<Callable> is
passed a C<Num> value of the modification time (number of seconds since epoch)
and is expected to return a trueish value to have the path be considered
for further selection.

=head4 :mode(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<mode> of the path.  The C<Callable> is passed the
mode of a path and is expected to return a trueish value to have the path be
considered for further selection.  This is really for advanced types of tests:
it's probably easier to use any of the C<readable>, C<writeable> and
C<executable> filters.

=head4 :modified(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<modification> time of the path.  The C<Callable> is
passed a C<Num> value of the modification time (number of seconds since epoch)
and is expected to return a trueish value to have the path be considered
for further selection.

=head4 :old-new

Flag. If specified with a trueish value, will produce C<Pair>s of the
current value being investigated, and whatever was returned by the C<Callable>
pattern for that value (if what was returned was B<not> a C<Bool>, C<Empty>
or C<Nil>) B<if> that value was different from the original value.  Defaults
to C<False>, meaning to just produce according to what was returned.

=head4 :omit-item-number

Flag. If specified with a trueish value, won't produce any C<PairMatched>
or C<PairContext> objects in the result, but will just produce the result
of the match.  Defaults to C<False>, meaning to include item numbers.

=head4 :paragraph-context

Flag. If specified with a trueish value, produce items B<around>
the empty with a pattern match until a falsish item is encountered.

=head4 :passthru

Flag. If specified with a trueish value, produces B<all> items always.

=head4 :passthru-context

Flag. If specified with a trueish value, produces B<all> items if there
is at least one match.

=head4 :paths-from($filename)

If specified, indicates the name of the file from which a list
of paths to be used as the base of the production of filename
with a C<paths> search.

=head4 :paths(@paths)

If specified, indicates a list of paths that should be used
as the base of the production of filename with a C<paths>
search.  If there is no other sources specification (from
either the C<:files-from>, C<:paths-from> or C<:sources>) then
the current directory (aka ".") will be assumed.  If that directory
appears to be the top directory in a git repository, then
C<:under-version-control> will be assumed, only producing files
that are under version control under that directory.

=head4 :produce-many(&producer)

If specified, indicates a C<Callable> that will be called given
a source, and is expected to produce zero or more items to be
inspected.  Defaults to a producer that calles the C<lines> method
on a given source, with the C<:encoding> and C<:with-line-ending>
arguments.

The C<Callable> should return C<Empty> if for some reason nothing
could be produced.

=head4 :produce-many-pairs(&producer)

If specified, indicates a C<Callable> that will be called given
a source, and is expected to produce zero or more C<PairContext>
objects to be inspected, in which the key represents the item
number.

This option will set the C<:omit-item-number> option to C<False>.

The C<Callable> should return C<Empty> if for some reason nothing
could be produced.

=head4 :produce-one(&producer)

If specified, indicates a C<Callable> that will be called given
a source, and is expected to produce one items to be inspected.

The C<Callable> should return C<Nil> if for some reason nothing
could be produced).

=head4 :progress(&announcer)

If specified, indicates a C<Callable> that will be called 5 times
per second to indicate how the search action is progressing.  It
will either be called with a C<Progress> object (while the search
action is still progressing) or B<without> any arguments to indicate
that search has completed.

=head4 :recurse-symlinked-dir

Flag. If specified with a trueish value, will recurse into directories
that are actually symbolic links.  The default is C<False>: do B<not>
recurse into symlinked directories.

=head4 :recurse-unmatched-dir

Flag. If specified with a trueish value, will recurse into directories
that did B<not> pass the :<dir>.  No files will ever be produced from
such directories, but further recursion will be done if directories
are encountered.  The default is C<False>: do B<not> recurse into
directories that didn't match the C<:dir> specification.

=head4 :quietly

Flag. If specified with a trueish value, will absorb any warnings
that may occur when looking for the pattern.

=head4 :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.

=head4 :silently("out,err")

When specified with C<True>, will absorb any output on STDOUT
and STDERR.  Optionally can only absorb STDOUT ("out"), STDERR
("err") and both STDOUT and STDERR ("out,err").

=head4 :sort(&logic)

When specified with C<True>, will sort the result alphabetically
(using foldcase logic).  Can also be specified with a C<Callable>,
which should contain the logic sorting (just as the argument to
the C<.sort> method).

Only supported with C<:unique> at this time.

=head4 :sort-sources(&logic)

When specified with C<True>, will sort the sources alphabetically
(using foldcase logic).  Can also be specified with a C<Callable>,
which should contain the logic sorting (just as the argument to
the C<.sort> method).

=head4 :sources(@objects)

If specified, indicates a list of objects that should be used
as a source for the production of items.  Which generally means
they cannot be just strings.

=head4 :sources-only

Flag.  If specified with a trueish value, will only produce the
source of a match once per source.  Defaults to C<False>.

=head4 :sources-without-only

Flag.  If specified with a trueish value, will only produce the
source of a match if there is B<not> a single match.  Defaults
to C<False>.

=head4 :stats

Flag.  If specified with a trueish value, will keep stats on number
number of items seen, number of matches, number of changes and number
of passthrus.  Stats on number of sources seen, will always be kept.

Note that on lazy results, the statistics won't be complete until all
results have been processed.

=head4 :stats-only

Flag.  If specified with a trueish value, will perform all searching, but
only update counters and not produce any result.  The statistics will
be available in C<nr-xxx> methods, and the C<result> attribute will
be C<Empty>.  Note that this causes eager evaluation.

=head4 :uid(&filter)

If specified, indicates the C<Callable> filter that should be used to select
acceptable paths by the B<uid> of the path.  The C<Callable> is passed the
numeric uid of a path and is expected to return a trueish value to have the
path be considered for further selection.  See also C<owner> and C<group>
filters.

=head4 :under-version-control($name = 'git')

If specified, indicates that any path specification that is a directory,
should be considered as the root of a directory structure under some
form of version control.  If specified as C<True>, will assume C<git>.
If such a path is under version control, then only files that are
actually controlled, will be produced for further inspection.  If it
is B<not> under version control, B<no> files will be produced.

Currently, only C<git> is supported.

=head4 :unique

Flag.  If specified, indicates that only unique matches will be returned,
instead of the normal sequence of source => result pairs.

=head4 :with-line-ending

Flag.  If specified, indicates line endings are to be kept when producing
items to check.  Defaults to C<False>, meaning that line endings are
removed from items to check.  Only applicable with line-based checking.

=head2 PATTERN RETURN VALUES

Some examples using C<Callable>s:

=begin code :lang<raku>
rak { .contains(/ foo /) };            # True || False
rak { True if .contains(/ foo /) };    # True || Empty
rak { Nil unless .contains(/ foo /) }; # Nil || Empty
rak { ~$/ if .contains(/ foo \w+ /) }; # "foobar" || Empty  
=end code

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

=head3 True

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

=head3 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.

=head3 Nil

If C<Nil> is returned, assume the pattern is B<not> found.  This can
typically happen 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.

=head3 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>.

=head3 any other value

Produce that value.

=head2 PHASERS

Any C<FIRST>, C<NEXT> and C<LAST> phaser that are specified in the
pattern C<Callable>, will be executed at the correct time.

=head2 MATCHED ITEMS vs CONTEXT ITEMS

The C<Pair>s that contain the search result within an object, have
an additional method mixed in: C<matched>.  This returns C<True> for
items that matched, and C<False> for items that have been added because
of a context specification (C<:context>, C<:before-context>, C<:after-context>,
C<paragraph-context> or C<passthru-context>).

These C<Pair>s can also be recognized by their class: C<PairMatched> versus
C<PairContext>, which are also exported.

=head1 AUTHOR

Elizabeth Mattijsen <liz@raku.rocks>

Source can be located at: https://github.com/lizmat/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
