A guided walk through exp, one recording per section. Every command
here runs against the vendored fixture pages, so you can follow along on
any machine with:
cargo build --release
export MANPATH="$PWD/tests/fixtures/man"
export PATH="$PWD/target/release:$PATH"Drop the MANPATH line to explain the tools actually installed on your
system, which is the normal way to use it.
demos/01-explain.cast, asciinema play for a real terminal
exp 'tar -xzvf a.tgz'The command line comes back with every span underlined and numbered.
-xzvf is four options, so it gets four spans; f takes an argument, so
a.tgz shares its footnote. Under the line, one table row per footnote:
the tokens that share it, the page and section they come from, and the
paragraph text.
exp 'sudo xargs -0 rm -f < list.txt'sudo and xargs are wrappers: after their own options, the first
operand starts a new command that gets its own page. rm -f is explained
from rm(1), and the redirect from the shell.
demos/02-pipeline.cast
exp 'git log --oneline | head -n 5 > out.txt'git is explained from git(1), log from git-log(1), and --oneline
from that page's options. The pipe and the redirect get built-in
explanations, not page lookups.
exp "find . -name '*.log' -exec rm {} \;"Everything between -exec and \; is a command in its own right, so
rm gets rm(1). The terminator points back at -exec.
demos/03-ugly-tail.cast
exp 'ps aux'
exp 'dd if=/dev/zero of=out.img bs=4M count=10'BSD-style aux is three bare tags in ps(1); bs=4M matches dd's
bs=BYTES paragraph. Both grammars live in knowledge/commands.toml,
not in code.
exp 'ssh -p 2222 -o StrictHostKeyChecking=no user@host'The whole StrictHostKeyChecking=no argument belongs to -o; the key
inside it gets a second footnote from ssh_config(5), where it is
documented.
demos/04-formats.cast
exp --format text 'rsync -avz --delete src/ dst/'
exp --format markdown 'rsync -avz --delete src/ dst/'
exp --json 'rsync -avz --delete src/ dst/' | jq '.spans[] | [.text, .kind, .footnote]'text is the ruler plus plain footnotes; markdown pastes into an
issue; json carries byte offsets and full provenance and is the format
the snapshot tests freeze.
demos/05-search.cast
exp search --tool rsync checksum
exp categories
exp search --category archive exclude
exp search --tool grep --zone any --regex 'binary file'
exp search --tool tar --fuzzy 'exclde vcs'Search runs over the SQLite cache that explaining fills as a side
effect. Named tools are indexed on demand; exp index --all indexes the
whole manpath (about 20 seconds for 21,000 pages) so --all and
categories with git-* patterns see everything.
Explain the previous command from fish:
function explain --description 'explain the last command'
exp (history --max 1)
end
funcsave explainFrom bash or zsh:
alias explain='fc -ln -1 | exp'Add a wrapper, an arity override, or a category in ~/.config/exp/:
# ~/.config/exp/commands.toml
[commands.run-as]
wraps = true
[[overrides]]
command = "mytool"
option = "-t"
arg_policy = "required"# ~/.config/exp/categories.toml
[categories]
backup = ["restic", "borg", "rsync", "tar"]When an explanation is wrong, exp page TOOL shows what was extracted,
and exp index --all --report lists pages the extractor could not make
sense of. A fix that survives the golden corpus becomes a rule or a TOML
entry, never an inline special case; see DESIGN.md.




