Files
str/HELP.md

388 lines
14 KiB
Markdown
Raw Permalink Normal View History

2026-04-06 09:22:44 -05:00
`str` : An interactive string manipulation environment
Copyright (C) 2026 Garrett Mills <shout@garrettmills.dev>
## Syntax Overview
String manipulation operations are performed on a "subject" -- a given string you are working on.
Most of the time, you do this by pasting a string into the interpreter, then running a series of
statements that make some changes to the string. Here's an example where a few lines of a TSV file
have been pasted in as the subject:
```text
str %> paste
┌───────────────
│ 0 │Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4
│ 1 │Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4
│ 2 │Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
│ 3 │Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
│ 4 │Hornet Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2
├───────────────
│ :: string
└───────────────
str %>
```
Statements in `str` take the form of `<command> [...args]`. For a trivial example, here we use a
command to replace all instances of `Hornet` with `Foobar`:
```text
str %> replace Hornet Foobar
┌───────────────
│ 0 │Mazda RX4 21 6 160 110 3.9 2.62 16.46 0 1 4 4
│ 1 │Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4
│ 2 │Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
│ 3 │Foobar 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
│ 4 │Foobar Sportabout 18.7 8 360 175 3.15 3.44 17.02 0 0 3 2
├───────────────
│ :: string
└───────────────
str %>
```
Notice that I did not have to quote the strings `Hornet` and `Foobar` because they do not contain any
special syntax characters. The only special syntax characters in `str` are single quotes themselves (`'`),
whitespace, and opening parens (`(`).
Commands are separated either by newlines (pressing enter), or using the `;` separator. For example:
```text
┌───────────────
│ 0 │foo bar baz
├───────────────
│ :: string
└───────────────
str %> replace oo OO; replace ba BA
┌───────────────
│ 0 │fOO BAr BAz
├───────────────
│ :: string
└───────────────
str %>
```
Comments start with `--` and run through the end of the line. Example:
```text
str %> = abc -- my comment
┌───────────────
│ 0 │abc
├───────────────
│ :: string
└───────────────
str %>
```
2026-04-06 09:22:44 -05:00
## Data Types
- `:: string` - Strings. Does what it says on the tin.
- `:: int` - Base-10 integers (e.g. for use as offsets).
- `:: destructured` - A list split by some value (e.g. `foo::bar` split on `::`).
- These differ from normal lists in that they keep track of their "connective tissue".
- For example, `foo::bar` split on `::` will give you `[foo, bar]`, but will remember that `bar` is prefixed with `::`
- This allows you to `join` the destructured back together later on
- `:: ... :: ()` - Lambdas. Multi-parameter functions. See "Working with Lambdas" below.
## Available Commands
### I/O & Editor Control
#### `exit`
Stop `str` and exit. This can also be done with `^C`.
#### `paste`
Replace the current subject with the current contents of your clipboard.
#### `copy`
Copy the current subject to your clipboard.
#### `infile <path>`
Replace the current subject with the contents of the given file.
Example: `infile ~/foo.txt`
#### `outfile <path>`
Write the current subject to the given file (replacing its current contents).
Example: `outfile ~/foo.txt`
#### `assign <value>` / `= <value>`
Replace the current context with the given value.
Example: `= 'foo bar'` -> `foo bar`
Example: `= $a` -> (value of `$a`)
#### `clear`
Clear the current subject (replace it with an empty string).
#### `show`
Print the current subject. This is done by default after every operation.
#### `undo`
Undo the last statement/operation.
#### `redo`
Redo the last undone statement/operation.
#### `history`
Show a log of recent statements/operations.
#### `edit`
Open the current subject in an external text editor (specified by `$EDITOR`).
Once you save and close the editor, the modified contents will be loaded back into `str`.
A crutch.
#### `save [<statefile>]`
Save the current state of the `str` session to the given statefile (default `~/.str.json`).
#### `load [<statefile>]`
Restore a `str` session from a saved state file (default `~/.str.json`).
#### `runfile <path>`
Execute the contents of the given file as a series of `str` commands.
#### `script <path> [...<args>]`
Execute an external script and replace the current subject with the returned output.
The current subject is passed as the first argument, followed by the optional additional `args`.
2026-04-06 09:22:44 -05:00
### Basic String Operations
#### `enclose [<with>]`
Wrap the string on either side with the given string (default = `(`).
If the string is one half of a matching pair (e.g. `(`, `[`, `{`, &c), surround with the matching pair.
Example: `foo` -> `enclose [` -> `[foo]`
#### `lower`
Convert the string to lower-case.
Example: `FoO` -> `lower` -> `foo`
#### `upper`
Convert the string to upper-case.
Example: `FoO` -> `upper` -> `FOO`
#### `lsub <offset> [<length>]`
Take a left-substring starting at the given `offset`. Stop after the given `length`, if provided.
Example: `abcdef` -> `lsub 1 3` -> `bcd`
#### `rsub <offset> [<length>]`
Take a right-substring starting at the given `offset`. Stop after the given `length`, if provided.
Example: `abcdef` -> `rsub 1 3` -> `cde`
#### `prefix <with>`
Prefix the current subject with the given string.
Example: `bar` -> `prefix foo` -> `foobar`
#### `suffix <with>`
Suffix the current subject with the given string.
Example: `foo` -> `suffix bar` -> `foobar`
#### `quote [<with>]`
Quote the string with the given quotemark (default `'`).
If the string is already quoted with a standard quotemark, strip it off first.
Example: `'bar'` -> `quote "` -> `"bar"`
#### `unquote [<with>]`
Unquote the string if it is quoted with a standard quotemark (or `with`, if provided explicitly).
Example: `"foo"` -> `unquote` -> `foo`
#### `replace <find> <with>`
Replace all instances of `find` with the given `with`.
Example: `foobaz` -> `replace baz bar` -> `foobar`
#### `rev`
Reverse the given string (or destructured list).
Example: `abcdef` -> `rev` -> `fedcba`
#### `trim [<type>] [<char>]`
Trim leading/trailing instances of `char` from the subject (by default, any whitespace).
By default, `trim` uses the `both` type, but supports the following modes:
- `start`/`left` - only from the start of the string
- `end`/`right` - only from the end of the string
- `both` - from both start and end of the string
- `lines` - remove any empty lines
Example: ` foo ` -> `trim left` -> `foo `
Example: `fffubarfff` -> `trim both f` -> `ubar`
#### `indent <space|tab> [<level>]`
Reindent the current subject with tabs or spaces.
If a `level` is provided, adjust the indentation to that level.
Example: ` word` -> `indent tab` -> `\tword`
#### `concat [...<strings>]`
Replace the current subject with the result of concatenating the provided strings together.
Mostly useful in conjunction with variables.
Example: `concat foo bar` -> `foobar`
### Multi-part Manipulation (line-wise, word-wise, destructured)
#### `line ...<subcommand>`
Execute the given `subcommand` on every line of the subject.
Example: `foo\nbar` -> `line prefix --` -> `--foo\n--bar`
#### `word ...<subcommand>`
Execute the given `subcommand` on every word of the subject, preserving whitespace.
Example: `foo bar baz` -> `word prefix --` -> `--foo --bar --baz`
#### `each ...<subcommand>`
Execute the given `subcommand` on every part of a destructured subject.
Example: `[foo, bar, baz]` -> `each prefix A` -> `[Afoo, Abar, Abaz]`
#### `on <word|line|index> <index> ...<subcommand>`
Execute the given subcommand on the specified word/line/index from the current subject.
`word` and `line` apply to strings that have not been destructured.
`index` is applied for destructured subjects. For destructured subjects you may omit the type (e.g. `on 4 ...`).
Example: `foo bar baz` -> `on word 1 rsub 1` -> `foo ba baz`
#### `drop <word|line|index> <index>`
Delete the specified word/line/index from the current subject.
`word` and `line` apply to strings that have not been destructured.
`index` is applied for destructured subjects. For destructured subjects you may omit the type (e.g. `drop 4`).
Example: `foo bar baz` -> `drop word 1` -> `foo baz`
#### `take <word|line|index> <index>`
Keep only the specified word/line/index from the current subject.
`word` and `line` apply to strings that have not been destructured.
`index` is applied for destructured subjects. For destructured subjects you may omit the type (e.g. `take 4`).
Example: `foo bar baz` -> `take word 1` -> `bar`
2026-04-06 09:22:44 -05:00
#### `contains <find>`
If the subject contains the given substring, keep it. Otherwise, replace it with an empty string.
Most often used in conjunction with `line`, `word`, or `each` for filtering.
Example: `afoo \n bfoo \n cbar` -> `line contains foo` -> `afoo \n bfoo \n `
#### `missing <find>`
If the subject contains the given substring, replace it with an empty string. Otherwise, keep it.
Most often used in conjunction with `line`, `word`, or `each` for filtering.
Example: `afoo \n bfoo \n cbar` -> `line missing foo` -> `\n \n cbar`
#### `lines`
Destructure the current subject into individual lines.
Example: `foo \n bar` -> `lines` -> `[foo, bar]`
#### `words`
Destructure the current subject into individual words.
Example: `foo bar \n baz` -> `words` -> `[foo, bar, baz]`
#### `split <on> [<limit>]`
Destructure the current subject based on the given delimiter.
If a `limit` is provided, split the subject no more than the given number of times.
Example: `foo::bar::baz::ban` -> `split :: 2` -> `[foo, bar, baz::ban]`
#### `join [<on>]`
Join the current destructured subject back together using the given delimiter.
If no delimiter is provided, it will preserve the existing delimiters between substrings.
If string is not destructured, joins the lines in the string.
Example: `[foo, bar]` -> `join ::` -> `foo::bar`
#### `chunk <every> <line|word|char>`
Destructure the current subject into chunks based on `every` Nth line/word/character.
Example: `a b c d e f` -> `chunk 2 word` -> `[a b, c d, e f]`
#### `group <callable>`
Group the current destructured subject based on some mapped value.
The `callable` is called for each destructured part and parts are bucketed together by the output value.
Example: `[aa, ab, ba, bb]` -> `group (rsub 1)` => `[[aa, ab], [ba, bb]]`
2026-04-06 09:22:44 -05:00
#### `sort [<asc|desc>]`
Sort the items in the destructured subject alphabetically either `asc`ending (default) or `desc`ending.
If string is not destructured, sorts the lines in the string.
Example: `[foo, bar]` -> `sort` -> `[bar, foo]`
#### `unique`
Filter out duplicate values from the destructured subject.
If string is not destructured, filters out duplicate lines in the string.
Example: `[foo, bar, foo]` -> `unique` -> `[foo, bar]`
#### `zip <with>`
Interleave the current destructured subject with the given other destructured subject.
Example: Say `$a` is `[1, 2, 3]` and subject is `[a, b, c]` -> `zip $a` -> `[a, 1, b, 2, c, 3]`
### Working with Variables
Variables in `str` start with a dollar sign and may be alphanumeric with underscores (e.g. `$my_var`).
Assign a variable using the standard syntax: `$a = 'mystr'`
You can then use them anywhere you may use a string: `split $a`
There are also several commands for interactive with variables, defined below.
#### `to <var>`
Store the current subject into the given variable.
Example: `foo bar` -> `to $a`
#### `from <var>`
Replace the current subject with the value of the given variable.
Example: `from $a`
#### `set <var> <value>`
Alternative syntax for variable assignment.
Example: `set $a 'mystr'` is equivalent to `$a = 'mystr'`
#### `over <var> ...<subcommand>`
Execute the given `subcommand` against the contents of `var` instead of the current subject.
Example: `over $a replace foo bar`
### Working with Lambdas (functions, closures, &c)
`str` supports Lambda functions. These are defined as a series of commands which may optionally
have some number of parameters. For example:
```text
$myReplacer = (|$a $b| split $a; join $b)
```
This trivial lambda takes two parameters, splits the subject on `$a` and joins it back together on `$b` (effectively, `replace`).
You may omit the parameter list if the lambda takes no parameters. For example, this basic TSV parser:
```text
$myTSVParser = (
trim;
trim lines;
lines;
each split \t
)
```
#### `call <lambda> [...<params>]`
Execute the given lambda with the provided parameters, replacing the current context with the result.
Example: `call $myReplacer foo bar`
`call` operates over the current context. However, you can execute lambdas over the contents of a variable using `over`:
```text
str %> $a = 'foo bar'
str %> over $a call $myReplacer foo bar
```
`call` also supports partial application. For example:
```text
str %> over $myFooReplacer call $myReplacer foo
```
You can then call the partially-applied lambda with the remaining parameter(s):
```text
str %> call $myFooReplacer bar
```
### Misc
#### `lipsum <num> <word|line|para>`
Replace the current subject with "Lorem ipsum..." placeholder text.
Can generate individual words, lines, or paragraphs.
Example: `lipsum 4 word` -> `lorem ipsum dolor sit`
#### User-specific setup files
The file `~/.str.rc` is automatically executed when `str` starts up.
You can use this to define a user-specific environment.