Skip to content

Commit

Permalink
Add new modifier arguments
Browse files Browse the repository at this point in the history
--not     must not match
--and     must also match
--andnot  must also NOT match
--or      may also match
--ornot   may also NOT match

Bringing a total of 158 options
  • Loading branch information
lizmat committed Aug 16, 2024
1 parent 3a36dae commit db34b92
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 31 deletions.
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ $ rak foo --files-with-matches
$ rak foo --before=2 --after=2

# lines with foo AND bar
$ rak '{.contains("foo") && .contains("bar")}'
$ rak foo --and=bar
```

DESCRIPTION
Expand Down Expand Up @@ -104,7 +104,7 @@ pattern

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

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

path(s)
-------
Expand Down Expand Up @@ -374,6 +374,16 @@ Only applicable if `--csv-per-line` has been specified. Flag. If specified, indi

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

--and=foo
---------

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

--andnot=foo
------------

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

--auto-diag
-----------

Expand Down Expand Up @@ -1255,6 +1265,21 @@ Inserts this value in the file instead of the given line. The value can either b

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

--not=foo
---------

Specify **primary** pattern that should **not** match to produce a hit.

--or=foo
--------

Specify **additional** pattern that should match to produce a hit.

--ornot=foo
-----------

Specify **additional** pattern that should **not** match to produce a hit.

--output-dir=directory
----------------------

Expand Down
30 changes: 26 additions & 4 deletions doc/App-Rak.rakudoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ $ rak foo --files-with-matches
$ rak foo --before=2 --after=2

# lines with foo AND bar
$ rak '{.contains("foo") && .contains("bar")}'
$ rak foo --and=bar

=end code

Expand Down Expand Up @@ -149,9 +149,9 @@ C<--ignorecase> or C<--ignoremark> arguments will be honoured.

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

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

Expand Down Expand Up @@ -485,6 +485,16 @@ 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
Expand Down Expand Up @@ -1597,6 +1607,18 @@ either be a string, or a list of strings (which would add lines to the file).
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,
Expand Down
49 changes: 41 additions & 8 deletions lib/App/Rak.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ my constant BON = "\e[1m"; # BOLD ON
my constant BOFF = "\e[22m"; # BOLD OFF

#- start of available options --------------------------------------------------
#- Generated on 2024-08-04T16:31:51+02:00 by tools/makeOPTIONS.raku
#- Generated on 2024-08-16T19:20:19+02:00 by tools/makeOPTIONS.raku
#- PLEASE DON'T CHANGE ANYTHING BELOW THIS LINE
my str @options = <absolute accept accessed ack after-context allow-loose-escapes allow-loose-quotes allow-whitespace auto-decompress auto-diag backtrace backup batch before-context blame-per-file blame-per-line blocks break checkout classify categorize context count-only created csv-per-line degree deny description device-number dir dont-catch dryrun ecosystem edit encoding eol escape exec execute-raku extensions file file-separator-null files-from files-with-matches files-without-matches filesize find formula frequencies gid group group-matches hard-links has-setgid has-setuid headers help highlight highlight-after highlight-before human ignorecase ignoremark inode invert-match is-empty is-executable is-group-executable is-group-readable is-group-writable is-moarvm is-owned-by-group is-owned-by-user is-owner-executable is-owner-readable is-owner-writable is-pdf is-readable is-sticky is-symbolic-link is-text is-world-executable is-world-readable is-world-writable is-writable json-per-elem json-per-file json-per-line keep-meta list-custom-options list-expanded-options list-known-extensions matches-only max-matches-per-file mbc mbc-frames mbc-strings meta-modified mode modified modify-files module only-first output-dir output-file pager paragraph-context passthru passthru-context paths paths-from pattern patterns-from pdf-info pdf-per-file pdf-per-line per-file per-line progress proximate rename-files quietly quote rak recurse-symlinked-dir recurse-unmatched-dir repository save sayer sep shell show-blame show-filename show-item-number silently smartcase smartmark sourcery stats stats-only strict summary-if-larger-than trim type uid under-version-control unicode unique user verbose version vimgrep with-line-endings>;
my str @options = <absolute accept accessed ack after-context allow-loose-escapes allow-loose-quotes allow-whitespace and andnot auto-decompress auto-diag backtrace backup batch before-context blame-per-file blame-per-line blocks break checkout classify categorize context count-only created csv-per-line degree deny description device-number dir dont-catch dryrun ecosystem edit encoding eol escape exec execute-raku extensions file file-separator-null files-from files-with-matches files-without-matches filesize find formula frequencies gid group group-matches hard-links has-setgid has-setuid headers help highlight highlight-after highlight-before human ignorecase ignoremark inode invert-match is-empty is-executable is-group-executable is-group-readable is-group-writable is-moarvm is-owned-by-group is-owned-by-user is-owner-executable is-owner-readable is-owner-writable is-pdf is-readable is-sticky is-symbolic-link is-text is-world-executable is-world-readable is-world-writable is-writable json-per-elem json-per-file json-per-line keep-meta list-custom-options list-expanded-options list-known-extensions matches-only max-matches-per-file mbc mbc-frames mbc-strings meta-modified mode modified modify-files module not only-first or ornot output-dir output-file pager paragraph-context passthru passthru-context paths paths-from pattern patterns-from pdf-info pdf-per-file pdf-per-line per-file per-line progress proximate rename-files quietly quote rak recurse-symlinked-dir recurse-unmatched-dir repository save sayer sep shell show-blame show-filename show-item-number silently smartcase smartmark sourcery stats stats-only strict summary-if-larger-than trim type uid under-version-control unicode unique user verbose version vimgrep with-line-endings>;
#- PLEASE DON'T CHANGE ANYTHING ABOVE THIS LINE
#- end of available options ----------------------------------------------------

Expand Down Expand Up @@ -243,6 +243,7 @@ my $debug-rak; # process show rak args

my @patterns; # the specified patterns (if any)
my @highlights; # the pattern used for highlighting
my $seen-initial-pattern; # flag, --pattern/--patterns-from seen
my $matches-only; # whether to produce matches only
my $smartcase; # --smartcase
my $smartmark; # --smartmark
Expand Down Expand Up @@ -377,11 +378,14 @@ my sub add-highlight($_) {
}
# Helper sub to add a pattern
my sub add-pattern($pattern --> Nil) {
my sub add-pattern($pattern, :$first --> Nil) {
$_ := $type && $type ne "auto"
?? Pair.new($type, $pattern)
!! implicit2explicit($pattern);
@patterns.push: $_;
$first
?? @patterns.unshift($_)
!! @patterns.push($_);
# Make sure highlightable patterns are added
add-highlight($_);
Expand Down Expand Up @@ -478,7 +482,8 @@ MEH
meh-unexpected if @unexpected;
# Set up the pattern
add-pattern(@positionals.shift) if !@patterns && @positionals;
add-pattern(@positionals.shift, :first)
if !$seen-initial-pattern && @positionals;
# from here on out, description is a noop
%global<description>:delete;
Expand Down Expand Up @@ -1365,6 +1370,13 @@ my sub set-listing-flag-or-Int(str $name, $value --> Nil) {
}
}
# Set pattern option
my sub set-additional-pattern(str $name, $value, str $prefix) {
Bool.ACCEPTS($value)
?? meh "'--$name' must be a pattern specification, not a flag"
!! add-pattern($prefix ~ $value)
}
#-------------------------------------------------------------------------------
# One subroutine for each supported option. Is assumed to do right thing for
# that option by setting the appropriate global hashes. Not expected to return
Expand Down Expand Up @@ -1404,6 +1416,14 @@ my sub option-allow-whitespace($value --> Nil) {
set-csv-flag('allow-whitespace', $value);
}
my sub option-and($value --> Nil) {
set-additional-pattern('and', $value, '&');
}
my sub option-andnot($value --> Nil) {
set-additional-pattern('andnot', $value, '&!');
}
my sub option-auto-decompress($value --> Nil) {
set-filesystem-flag('auto-decompress', $value);
}
Expand Down Expand Up @@ -1874,13 +1894,26 @@ my sub option-module($value --> Nil) {
!! @modules.push($value)
}
my sub option-not($value --> Nil) {
set-additional-pattern('not', $value, '!');
$seen-initial-pattern := True;
}
my sub option-only-first($value --> Nil) {
set-listing-flag-or-Int(
'only-first',
$value eq '' | '*' | 'Inf' ?? 0 !! $value
);
}
my sub option-or($value --> Nil) {
set-additional-pattern('or', $value, '');
}
my sub option-ornot($value --> Nil) {
set-additional-pattern('ornot', $value, '!');
}
my sub option-output-dir($value --> Nil) {
meh "'--output-dir' expects a directory specification"
if Bool.ACCEPTS($value);
Expand Down Expand Up @@ -1931,9 +1964,8 @@ my sub option-paths-from($value --> Nil) {
}
my sub option-pattern($value --> Nil) {
Bool.ACCEPTS($value)
?? meh "'--pattern' must be a pattern specification, not a flag"
!! add-pattern($value)
set-additional-pattern('pattern', $value, '');
$seen-initial-pattern := True;
}
my sub option-patterns-from($value --> Nil) {
Expand All @@ -1942,6 +1974,7 @@ my sub option-patterns-from($value --> Nil) {
sub read-patterns($handle) {
if $handle.lines -> @lines {
add-pattern($_) for @lines;
$seen-initial-pattern := True;
}
}
Expand Down
11 changes: 11 additions & 0 deletions resources/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ in --patterns-from=file option.
'/ << bar >> /' Raku regex indicated by being bounded by / /
'{ .ends-with("bar") }' Raku code indicated by being bounded by { }
'*.starts-with("foo")' Raku WhateverCode starting with *
's:foo bar' Multiple patterns, split on whitespace:
jp:foo JSON path specification (with --json-per-xxx)
§string String should match as a word
^string String should match at start of line
string$ String should match at end of line
^string$ String should match with line entirely
string String should match anywhere in line
!string String should NOT match anywhere in line
&string Additional string should ALSO match anywhere in line

Pattern type overrides:
--type=auto Interpret special markers in pattern as above (default)
Expand All @@ -25,8 +28,16 @@ in --patterns-from=file option.
--type=starts-with Pattern must match at start of line
--type=ends-with Pattern must match at end of line
--type=equal Pattern must match entirely
--type=not Pattern must NOT match
--type=split Multiple patterns, split on whitespace
--type=contains Pattern must match anywhere (default if no markers)

Additional patterns:
--and=bar Must ALSO match anywhere in line
--andnot=bar Must ALSO NOT match anywhere in line
--or=bar May ALSO match anywhere in line
--ornot=bar May ALSO NOT match annywhere in line

String search pattern modifiers:
--ignorecase Ignore distinction between upper, lower and title case letters
--ignoremark Only compare base characters, ignore additional marks
Expand Down
56 changes: 39 additions & 17 deletions resources/help/pattern.txt
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
Pattern specification:
‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒‒

There are 3 ways in which pattern(s) can be specified:
There are 4 ways in which a primary pattern can be specified:

1. As the first positional argument
2. Or with the --pattern=foo argument
3. Or using the --patterns-from=file argument
3. Or with the --not=foo argument
4. Or using the --patterns-from=file argument

The first is easiest for a quick ad-hoc search. The second can be handy
if you want to create a short-cut to searching for a particular string with
--save. The last one allows you set up a set of patterns to be searched
for simultaneously.
The first is easiest for a quick ad-hoc search. The second and third can
be handy if you want to create a short-cut to searching for (the absence
of) a particular string with --save. The last one allows you set up a
set of patterns to be searched for simultaneously.

The --not=foo argument negates the match, so will select items that do
**NOT** match the pattern specification.

If the --patterns-from=file argument is specified, it will read the content
of the given file and process each line as a pattern specification, as
described below. When searching, each pattern is tried on an item, and
accepted as soon as a pattern matched. Any highlighting will occur on
*that* match only.
any of the patterns specified.

If a literal string is specified as a pattern, then by default any item of
which the stringification contains that string, will be accepted.
Expand Down Expand Up @@ -55,7 +59,7 @@ the string:

Example:
# produce any lines that have the word "bar" in them
$ rak '<< bar >>' --type=regex
$ rak --type=regex '<< bar >>'

Code:

Expand Down Expand Up @@ -110,10 +114,10 @@ omit the initial '*'.

Examples:
# produce uppercased lines
$ rak '.uc' --type=code
$ rak --type=code .uc

# produce all lines, only uppercase the ones that have "rakudoc" in them
$ rak '.contains("rakudoc") ?? .uc !! $_' --type=code
$ rak --type=code '.contains("rakudoc") ?? .uc !! $_'

JSON path:

Expand Down Expand Up @@ -190,13 +194,14 @@ Literal strings matching can be further specialized with other values of the
- starts-with item must *start* with string
- ends-with item must *end* with string
- equal item must be *equal* to string
- split split string on whitespace for separate patterns

Examples:
# produce any lines that have the word "bar" in them
$ rak bar --type=words
$ rak --type=words bar

# produce any lines that start with "Example"
$ rak Example --type=starts-with
$ rak --type=starts-with Example

Both literal string matching, as well as matching with a regex, are
sensitive to the --smartcase, --ignorecase and --ignoremark arguments.
Expand All @@ -206,15 +211,32 @@ Shortcuts:
Several shortcuts are available to indicate some type of behaviour for
literal strings. They are

- string string --type=contains
- §string string --type=words
- ^string string --type=starts-with
- string$ string --type=ends-with
- ^string$ string --type=equal
- string --type=contains string
- §string --type=words string
- ^string --type=starts-with string
- string$ --type=ends-with string
- ^string$ --type=equal string
- !string --type=not

Examples:
# produce any lines that have the word "bar" in them
$ rak §bar

# produce any lines that start with "Example"
$ rak ^Example

Additional patterns:

You can also specify additional patterns that should also (not) match:

- --and=bar Must ALSO match anywhere in line
- --andnot=bar Must ALSO NOT match anywhere in line
- --or=bar May ALSO match anywhere in line
- --ornot=bar May ALSO NOT match annywhere in line

Examples:
# produce any lines that have the words "foo" and "bar" in them
$ rak §foo --and=§bar

# produce any lines that start with "foo" but not have "bar" in them
$ rak ^foo --andnot=bar

0 comments on commit db34b92

Please sign in to comment.