### ----------------------------------------------------
### -- App::Rak
### -- Licenses: Artistic-2.0
### -- Authors: Elizabeth Mattijsen
### -- File: README.md
### ----------------------------------------------------
### -- Chunk 3 of 3
 value as the new name of the file. It can either be a string or an `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 `Str` returned, will be automatically converted to an `IO::Path` object before being compared using `eqv`.

```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
```

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

--repository=dir
----------------

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

--save=shortcut-name
--------------------

Save all options with the given name in the configuration file (`~/.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.

```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'
```

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 `--save`=foo as the only option to remove the "foo" set of options.

--sep=,
-------

Only applicable if `--csv-per-line` has been specified. Indicates the character to indicate the field separator. Defaults to the **comma**.

--show-blame
------------

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

Requires that the [`Git::Blame::File`](https://raku.land/zef:lizmat/Git::Blame::File) module is installed.

--show-item-number
------------------

Flag. Indicate whether item numbers should be shown. Defaults to `True`.

--show-filename
---------------

Flag. Indicate whether filenames should be shown. Defaults to `True`.

--shell=invocation
------------------

If specified, indicates the command(s) to be executed in a shell. Any `$_` 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.

--silently[=out,err]
--------------------

Flag and option. Only applicable if the pattern is a `Callable`. Indicates whether any output from the `Callable` pattern should be caught. Defaults to `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 class="pod-table">
<thead><tr>
<th>flag(s)</th> <th>action</th>
</tr></thead>
<tbody>
<tr> <td>out</td> <td>only capture STDOUT</td> </tr> <tr> <td>err</td> <td>only capture STDERR</td> </tr> <tr> <td>out,err</td> <td>capture both STDIN as well as STDERR</td> </tr> <tr> <td>err,out</td> <td>capture both STDIN as well as STDERR</td> </tr>
</tbody>
</table>

--smartcase
-----------

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

--smartmark
-----------

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

--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 `--edit`, `--vimgrep` and the implicit `per-line` option.

```bash
# edit the location(s) of the "say" sub handling a single string
$ rak --sourcery 'say "foo"' --edit
```

Requires the [`sourcery`](https://raku.land/zef:lizmat/sourcery) module to be installed.

--stats
-------

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

--stats-only
------------

Flag. **Only** show statistics about the search operation. See also `--count-only`.

--strict
--------

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

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

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

--type=string
-------------

The `--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 `auto`.

The following strings can be specified:

### auto

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

### regex

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

### code

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

### json-path

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

### contains

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

### words

If `--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 `--smartcase`, `--smartmark`, `--ignorecase` and `--ignoremark` specifications.

### starts-with

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

### ends-with

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

### equal

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

--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 `True` if no context for lines was specified, else defaults to `False`.

--uid=condition
---------------

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

```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
```

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

--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 `git` version control. Can also specify the name of the version control system as the value: currently only **git** is supported.

--unicode
---------

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

--unique
--------

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

--user=condition
----------------

If specified, indicates the `Callable` that should return `True` to include a file in the selection of files to be checked. The user name associated with the `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 **except** the listed named, prefix with a `!`.

See also `--uid`. Requires the [P5getpwnam](https://raku.land/zef:lizmat/P5getpwnam) module to be installed.

```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'
```

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

--version
---------

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

--vimgrep
---------

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

CHECKING TIMES ON FILES
=======================

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

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

Automatic conversion to epoch
-----------------------------

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

Specifying some time ago
------------------------

Within these special `Callable`s, one can also indicate an epoch value in the past by using the `.ago` method in a specially formatted string. This string is formatted similarly to time specifications of the Unix `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.

On method naming
----------------

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

Examples
--------

```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'
```

JSON PATH SUPPORT
=================

<table class="pod-table">
<caption>Supported JSON path syntax</caption>
<thead><tr>
<th>expression</th> <th>meaning</th>
</tr></thead>
<tbody>
<tr> <td>$</td> <td>root node</td> </tr> <tr> <td>.key</td> <td>index hash key</td> </tr> <tr> <td>[&#39;key&#39;]</td> <td>index hash key</td> </tr> <tr> <td>[2]</td> <td>index array element</td> </tr> <tr> <td>[0,1]</td> <td>index array slice</td> </tr> <tr> <td>[4:5]</td> <td>index array range</td> </tr> <tr> <td>[:5]</td> <td>index from the beginning</td> </tr> <tr> <td>[-3:]</td> <td>index to the end</td> </tr> <tr> <td>.*</td> <td>index all elements</td> </tr> <tr> <td>[*]</td> <td>index all elements</td> </tr> <tr> <td>[?(expr)]</td> <td>filter on Raku expression</td> </tr> <tr> <td>..key</td> <td>search all descendants for hash key</td> </tr>
</tbody>
</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).

#### Full Raku support

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

This means that:

```bash
$ rak --json-per-file jp:foo
$ rak --json-per-file --type=json-path foo
```

are a different way of saying:

```bash
$ rak --json-per-file '{ jp("path").Slip }'
```

using the "pattern is Raku code" syntax.

The following methods can be called on the `JP` object:

<table class="pod-table">
<thead><tr>
<th>method</th> <th>selected</th>
</tr></thead>
<tbody>
<tr> <td>.value</td> <td>The first selected value.</td> </tr> <tr> <td>.values</td> <td>All selected values as a Seq.</td> </tr> <tr> <td>.paths</td> <td>The paths of all selected values as a Seq.</td> </tr> <tr> <td>.paths-and-values</td> <td>Interleaved selected paths and values.</td> </tr>
</tbody>
</table>

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

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 [small sponsorship](https://github.com/sponsors/lizmat/) would mean a great deal to me!

COPYRIGHT AND LICENSE
=====================

Copyright 2022, 2023, 2024, 2025 Elizabeth Mattijsen

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



