@sema-agent/core
Version:
Stateless, task-oriented AI agent core
868 lines • 62.6 kB
TypeScript
/**
* The PROGRAM READ MODEL — one table that answers "what does this program do with its k-th word", and the readers
* every shell face reads it through.
*
* A row is one program (the basename bash runs; a versioned spelling of an interpreter is its row), carrying every
* argument fact the shell faces need: its option grammar (one per implementation where implementations disagree),
* the ROLE each option value and each operand plays, whether a form walks a tree, how an interpreter receives the
* program it runs, what a launcher steps over before the program it runs, which words a builtin keeps as shell text
* to run later. The rows live in `program-read-model.rows.ts`; this module is the schema and the readers.
*
* Every reader below is a PROJECTION of the same row: the option-slot reading the candidate extraction walks
* (`readArgs`), the traversal reading, the program-delivery reading, the launcher step, the program-text reading of a
* language the station parses, the message slots, the code bodies. A reader never carries a table of its own; a fact
* one reader needs and the row does not state is added to the row, where every other reader sees it too.
*
* Rows are checked against the real binaries by `test/program-read-model.binary-gate.test.ts`: each declared option
* of each row is run, per implementation, on fixtures whose every word is a FIFO, and the words the binary OPENED are
* compared with the words the row predicts it opens. A row whose opener cannot be witnessed locally (a daemon, an
* object store, a shell builtin) says so in its `witness`, with the reason.
*/
import { type WordPiece } from "../../shell/lex.js";
/** What a datum names: never a file. */
export declare const DATUM_FORMS: readonly ["count", "pattern", "name-pattern", "label", "message", "delimiter"];
export type DatumForm = (typeof DATUM_FORMS)[number];
/** How a path-valued word carries its path, when it is not the plain word: `indirect` = the word, or what it names
* past a leading `@`; `form` = a field spec whose files sit after `@` / `<`; `header` = only a whole-word `@<file>`;
* `url` = the local path a `file:` URL names. */
export declare const PATH_VALUE_FORMS: readonly ["indirect", "form", "header", "url"];
export type PathValueForm = (typeof PATH_VALUE_FORMS)[number];
/** What selecting an option does to how the program runs ({@link OptionSpec.mode}) — a CLOSED set (`docs/CLOSED-SETS.md`,
* `OptionMode`). */
export declare const OPTION_MODES: readonly ["banner", "interactive", "names-program", "follows", "repeats", "quiet", "forced", "queries"];
export type OptionMode = (typeof OPTION_MODES)[number];
/**
* What one word is in this program's hands — a CLOSED set (`docs/CLOSED-SETS.md`, `ArgRoleKind`), the eleven members the
* read-station design names.
*/
export declare const ARG_ROLE_KINDS: readonly ["path", "mount-source", "object-path", "program-text", "program-file", "shell-text", "command", "assignment", "binds-name", "entry-probe", "datum"];
export type ArgRoleKind = (typeof ARG_ROLE_KINDS)[number];
/**
* WHERE a write reaches a path it names. `landing` — the path followed through every link to where it lands: the
* program opens the path and writes through it. `entry` — the directory entry itself, the canonical parent joined with
* the last name: the program renames over the entry, unlinks it or replaces it, and a link there is not followed.
*/
export type WriteSeat = "landing" | "entry";
/** What a path role does with the path: opens it for reading, only NAMES it (examines its entry, matches it, changes
* into it), writes it (an existing file or a new one, or removes it), creates it, or edits it IN PLACE (an existing
* file is rewritten — a program edits nothing that is not there). */
export declare const PATH_EFFECTS: readonly ["read", "names", "write", "create", "edit-in-place"];
export type PathEffect = (typeof PATH_EFFECTS)[number];
/** The effects that write the path: the write face's targets. */
export declare const WRITING_EFFECTS: ReadonlySet<PathEffect>;
export type ArgRole =
/** A path, by what the program does with it ({@link PathEffect}). Every effect is a path the command names. */
{
readonly kind: "path";
readonly effect: PathEffect;
readonly valueForm?: PathValueForm;
/** The program expands `{a,b}` sets and `[a-z]` / `[1-9]` ranges in the value itself before it opens anything
* (curl's URL glob), unless the invocation carries an option marked {@link OptionSpec.literalValues}. */
readonly programGlob?: true;
/** A writing effect: the seats the program writes the path at (absent: where it lands). */
readonly seats?: readonly WriteSeat[];
/** A writing effect the program does NOT itself perform at every seat: the seats it does write (`[]`: none — a
* copy READS its sources; the write face still judges them, as the reference implementation does). Absent: every
* seat in {@link seats}. */
readonly writtenAt?: readonly WriteSeat[];
/** A writing effect that writes the path's CONTENT by opening it (`true`), or does so only while the invocation carries
* no option word (`"plain"`: a copy's `-f`, `-b` and `--remove-destination` replace the entry, `-l` and `-s` link it) —
* the one kind of write a standard device takes without a containment question (`passesUnasked`). Absent: the program
* creates, unlinks, renames or retargets the path's ENTRY, or the row does not say it only writes through. */
readonly through?: true | "plain";
/** The program RUNS in this directory (`env -C <dir>`), or with it as its root (`sudo -R <dir>`): the paths it is
* handed resolve against it, not against the working directory the command line stands in. Or the program word is
* LOOKED UP in these directories (`env -P <dirs>`): which program runs is not the one the word names on the PATH. */
readonly base?: "working-directory" | "root" | "program-search";
}
/** A HOST path a container runtime's daemon opens and mounts: `src[:dst[:opts]]` (`form: "volume"`, the source before the
* first `:`) or `key=value,…` with a `source=` / `src=` key (`form: "mount"`). A source that is no path (a volume name:
* no `/`, not led by `.` or `~`) names nothing on the host. */
| {
readonly kind: "mount-source";
readonly form: "volume" | "mount";
}
/** A repository object named `<rev>:<path>`: the object store opens it, not the working tree, so `<path>` is a
* spelling of a path the repository holds — relative to its top, which the text does not name. */
| {
readonly kind: "object-path";
}
/** Program text in `language`, run rather than opened. */
| {
readonly kind: "program-text";
readonly language: string;
}
/** A file holding program text in `language` — the file itself is opened. */
| {
readonly kind: "program-file";
readonly language: string;
}
/** Text the shell runs (now or later) as a command line. */
| {
readonly kind: "shell-text";
}
/** The program a launcher or a builtin runs by name: a function (`compgen -F`), the program a launcher runs in place of
* a shell (`su -s PROGRAM`). */
| {
readonly kind: "command";
}
/** A `NAME=value` the program (or the shell) consumes as an assignment. */
| {
readonly kind: "assignment";
}
/** A variable NAME the builtin reads or binds (`read NAME`, `printf -v NAME`, `unset NAME`, `declare NAME=…`, `test -v
* NAME`): an array element's subscript in it is evaluated as arithmetic — unless the builtin takes the name as
* WRITTEN (`asWritten`: `export` / `readonly` evaluate no subscript and refuse an element as no identifier). */
| {
readonly kind: "binds-name";
readonly asWritten?: true;
}
/** A path whose directory ENTRY is examined (type, mode, size) — nothing is opened. */
| {
readonly kind: "entry-probe";
} | {
readonly kind: "datum";
readonly form: DatumForm;
};
export type Arity =
/** A switch. */
0
/** A value: the rest of the token, the next word, or `=value` for a long name. */
| 1
/** A value that exists only attached (`getopt_long`'s optional argument): the bare spelling takes nothing. */
| "attached"
/** A backup suffix: the rest of the token, or the NEXT word whatever it is spelled — the implementation's own reading
* (the role walk, the write reading, the binary gate). The read extraction (the candidate view and the program-text
* slot) takes the next word only when it is spelled like a suffix (empty, or `.`-led): taking any word there reads the
* everyday other-implementation spelling `-i '<script>' <file>` with its FILE as the script. */
| "suffix";
/**
* One option of a program row.
*
* @contract shell.read_boundary.option_value_slots — where a program row declares an option, the read boundary reads
* that option's value from the DECLARED role and nowhere else: a role that can name a file yields exactly the value
* as a path candidate (an `indirect` value also yields what it names past its `@`, a `header` value only a
* whole-value `@<file>`, a `form` value the files after its `@` / `<`, a `url` value the local path a `file:` URL
* names — each after the program's own glob where the role says the program expands one), and a role that cannot
* yields none; the attached and separated spellings of one option read the same row, except a value that exists
* only attached, which has no separated spelling. Past the command's first operand the separated spelling consumes
* nothing and its value is judged BOTH as that value and as an operand (which of the two it is, is
* implementation-dependent), unless the row's options stand anywhere in every implementation. A spelling one
* implementation rejects is read by the others alone, and an arity they dispute is read the way that consumes
* nothing. Where the row declares nothing — no row for the program, an option character it does not account for, a
* value declared without a role, a long-option prefix whose reachable names leave the value unsettled — the token
* is read the speculative way (its payloads are candidates), so an absent or partial row costs precision and never
* a judgement. A row is DATA about a PROGRAM and not about the read-only allowlist: it says what that program does
* with its own arguments, never that the program may be read from, and it grants no per-program arm to a program a
* deployment has not listed.
*/
export interface OptionSpec {
readonly arity: Arity;
/** The value's role. Absent = this row does not model the value; a reader that needs it reads the option the
* speculative way (every spelling it could name is a candidate). */
readonly value?: ArgRole;
/** Selecting this option makes the operands roots of a tree walk (`traversal`), or makes the ordinary operands files
* the program rewrites in place (`edit-in-place`: they take {@link OperandSpec.editedInPlace}; the option's value, when
* it is given one, is the BACKUP suffix). */
readonly selects?: "traversal" | "edit-in-place";
/** Selecting this switch makes the program write every path it writes at these seats instead (`touch -h` writes the
* entry too; an in-place `sed --follow-symlinks` writes where the operand lands, and names its backups after that). */
readonly writesAt?: readonly WriteSeat[];
/** What selecting this option does beyond its value's role: `writes` a file or the system's state (`find -delete`,
* `date -s`), `executes` a command (`find -exec`), or `none` — neither, which the binary gate witnesses for every
* option that states it (the read-only form of a program admits only such options). Absent: not stated. */
readonly effect?: "writes" | "executes" | "none";
/** The option's value names a FILE the program reads its OPERANDS from (`find -files0-from`, `tar -T`) — or, a switch, says they
* arrive on its standard input (`ack -x`): what it walks or opens is not in the command line, so a segment that selects it has
* reads the station cannot establish ({@link deliversOperands}); the list file itself is a read like any other and meets the deny
* rows as itself. */
readonly delivers?: "operands";
/** The option's value is a PLACE the program's walk works in or compares (`tar -C DIR`, `diff --from-file=DIR`): a root of a
* recursive form, whichever way the value is spelled. Absent: a path value is a file the program READS (a config, ignore or
* exclusion file, an archive, a pattern file) or an entry it examines — judged as itself, never a root, so it does not count
* as the root the walk was given (`rg --ignore-file ig pat` walks `.`). A list the operands come from ({@link delivers}) is a
* root of a recursive form too, in either spelling: the program works on what the list names, not on the working directory
* (and, the names not being in the text, the segment is not vouched: {@link deliversOperands}). */
readonly walks?: true;
/** The option's value bounds the program's output, in bytes or in lines (`head -c` / `head -n`). */
readonly bounds?: "bytes" | "lines";
/** The option's value is what the row's LAST operand would otherwise be (`cp -t <dir>`), so every operand is an
* ordinary one after it. */
readonly fillsLast?: true;
/** An enum option: selecting the value (case-folded, any unambiguous prefix of it) makes the operands roots of a
* tree walk (`grep -d recurse`). */
readonly selectsWhenValue?: string;
/** This option delivers what the row's first positional would otherwise be (grep's `-e`, sed's `-f`, an
* interpreter's `-c`), so the first operand is an ordinary operand after it. */
readonly fillsSlot?: true;
/** What follows this option (after its value) is the named program's own argv (`python -m <module> …`). */
readonly endsOptions?: true;
/** `banner`: prints and exits; `interactive`: reads commands from its standard input (after its program, `python -i`;
* instead of a script file, `sh -s`; a launcher's shell, run where no program follows, `sudo -s`); `names-program`: selects
* the program to run without a value (`node --test`; a launcher's, from the caller's environment: `su -m`); `follows`:
* follows its files as they grow, until killed (`tail -f`); `repeats`: repeats on an interval until killed (`free -s`);
* `quiet`: prints only what the program's own text tells it to (`sed -n`); `forced`: removes without asking, and passes
* over an operand that is not there (`rm -f`); `queries`: a LOOKUP — the operands are names it looks up and describes, and
* it runs none of them (`command -v`). */
readonly mode?: OptionMode;
/** This switch turns the program's own value glob off (`curl -g`): every {@link ArgRole} `programGlob` value of the
* invocation is read literally. */
readonly literalValues?: true;
/** What selecting this switch makes a declaration builtin do to the names it binds (`declare -i`): evaluate an assigned
* value as ARITHMETIC (`integer` — a substitution in a subscript of it runs; the value bound is not the text), make
* the name a REFERENCE to another (`reference` — an assignment through it binds the name it holds), bind something
* other than the text (`transformed` — a case change, an array), make the name READ-ONLY (`frozen` — the shell
* refuses every later assignment to it and keeps the value, or exits; the builtin's own `NAME=value` still binds), or
* leave what a `NAME=value` operand binds UNSETTLED (`unsettled` — the builtin may assign none of them: it displays
* the names, `declare -p`; names functions, `-f`; or a bash it runs on refuses the switch, bash 3.2's `declare -g`). */
readonly assigns?: DeclaredAttribute;
}
/** What a declaration builtin does to the names it binds ({@link OptionSpec.assigns}). */
export type DeclaredAttribute = "integer" | "reference" | "transformed" | "frozen" | "unsettled";
/** One implementation's option grammar. `any` = every implementation the row was measured on reads it this way. */
export type Dialect = "any" | "gnu" | "bsd";
export interface Grammar {
readonly dialect: Dialect;
/** Short option letters. */
readonly short: Readonly<Record<string, OptionSpec>>;
/** Long option names, without the leading `--`. */
readonly long: Readonly<Record<string, OptionSpec>>;
/** Single-dash WORD options (`find -name`, `sqlite3 -cmd`), without the dash. */
readonly dashWords?: Readonly<Record<string, OptionSpec>>;
/** What a dash-led word past the first operand is: still an `options` word (permuting, or a grammar whose options
* stand anywhere), an `operands` word (the implementation stops at the first operand), or `either` (the row is
* read for implementations that disagree). */
readonly afterFirstOperand: "options" | "operands" | "either";
/** A `+` word is an option word too, read as its `-` spelling (a POSIX shell's `+x` turns `-x` off; `+o NAME` takes its
* name as `-o` does). */
readonly plusOptions?: true;
/** The `+` spellings of a declaration builtin's switches (`declare +x` turns an attribute off), measured apart from the
* `-` ones: a `+` word with a letter this table does not carry (`++`, `+Z`) is one the builtin refuses. Absent, a
* `+` word is no switch of the builtin (`export ++` is an operand). */
readonly plusShort?: Readonly<Record<string, OptionSpec>>;
/** A launcher whose walk steps over a bare `--` (the `time` reserved word's TIMEIGN, the program's end-of-options). */
readonly stepsDashDash?: true;
/** With no operand, this implementation walks the working directory (`grep -r pat`); absent, it walks nothing (it
* reads its standard input, or refuses to run). */
readonly walksCwdWithoutOperand?: true;
/** Whether this implementation reads an unambiguous PREFIX of a long option's name as that option (`getopt_long`, Perl's
* Getopt::Long: `grep --max 1`, `tar --dir d`). Absent = it does; `false` = only the exact name is an option and a prefix
* is an unrecognised flag that runs nothing (ripgrep's parser: `rg --ignore-f x` is an error while `rg --ignore` is the
* switch). Every reader that matches a long name against the table asks this one fact, so a name a row leaves undeclared is
* never read as the abbreviation of a declared one in a program that does not take abbreviations. */
readonly acceptsAbbreviations?: boolean;
/** The traditional FIRST-argument form `<sign><number><letters>` (`tail +0f`, `tail -1f`): the signs this
* implementation reads it with, and the option each letter names. */
readonly obsoleteFirst?: {
readonly signs: string;
readonly letters: Readonly<Record<string, OptionSpec>>;
};
}
export interface OperandSpec {
/** Roles of the positional operands by position (`undefined` = an ordinary operand). */
readonly positional?: readonly (ArgRole | undefined)[];
/** The role of every operand past `positional` (absent = an ordinary operand: a path the program may read). */
readonly rest?: ArgRole;
/** A bare `-` operand is a FILE name (absent: it is standard input). */
readonly dash?: "file";
/** The program evaluates its words (an array subscript in one runs a substitution): a word the shell or that
* evaluation rewrites is still handed over, whatever the operand role says. */
readonly evaluates?: true;
/** A `NAME=value` argument's value names no path to this program. */
readonly assignmentArguments?: "not-paths";
/** The role of the LAST operand, unless an option delivered it ({@link OptionSpec.fillsLast}): a copy's destination. */
readonly last?: ArgRole;
/** What an ordinary operand becomes when an option selects editing in place ({@link OptionSpec.selects}). */
readonly editedInPlace?: ArgRole;
/** With fewer operands than this (the first-operand slot counted), the program reads its standard input; `always`:
* it reads nothing else. Absent: the row does not say. */
readonly stdinBelow?: number | "always";
}
export interface TraversalSpec {
/** What the walk hands back: the CONTENTS it walked over, or only NAMES (and sizes). */
readonly discloses: "contents" | "names";
/** Every invocation walks (`find`, `du`, `rg`): no option selects it. */
readonly always?: true;
/** Mode letters of a traditional dash-less first-operand key word (`tar cf …`) that select the walk. */
readonly keyWordLetters?: string;
}
export interface LauncherSpec {
/** Positional operands the launcher takes BEFORE the program (`timeout DURATION COMMAND`). */
readonly requiredOperands?: number;
/** The launcher reads `NAME=VALUE` operands with its own name grammar (`env 1=x …`). */
readonly assignmentOperands?: true;
/** A bare negative integer in its option section is its own argument (`nice -5 <cmd>`). */
readonly negativeIntegerIsOwnArgument?: true;
/** It runs a SHELL in place of a program word, and how the words after it become that shell's argv: `joined` — its
* non-option words, joined by a space, are the shell's `-c` text (`watch "cat /x"`); `user` — its first operand (past
* a lone `-`) names the user it runs as, and the words after the user are the shell's own argv, behind a `-c TEXT` its
* own shell-text option gives (`su [-] [USER [ARG…]]`: an implementation that reads its options anywhere takes them
* past the user too, one that stops at the user hands them on); the program is its option of role `command` where
* one is given (`su -s PROGRAM`), or a `names-program` switch's (`su -m`: the caller's `$SHELL`). */
readonly shellText?: "joined" | "user";
/** Option spellings that make a {@link shellText} launcher run the program its operands name instead
* (`runuser -u USER CMD…`). */
readonly programWith?: readonly string[];
/** With no program word it runs a shell. */
readonly whenNoProgram?: "shell";
/** Where a switch selecting its shell (mode `interactive`: `sudo -s`) has words after it, they are that shell's `-c`
* text: `escaped` — joined by a space, every character of each but a letter, a digit, `_`, `-` and `$` escaped with a
* backslash. Absent, the launcher takes no such words (`doas -s CMD` is refused) and they are read as the program. */
readonly shellCommand?: "escaped";
/** The spelling a required operand must have (a word spelled otherwise is not one the launcher accepts). Absent: any
* word that is not option-shaped. */
readonly requiredOperandSpelling?: RegExp;
/** A lone `-` in its option section is its own switch (`env -`, the obsolete spelling of `env -i`). */
readonly bareDash?: true;
/** It runs its shell as ANOTHER user ({@link TargetUser}): the user an option of `userWith` names (`sudo -u USER`), or —
* a {@link shellText} `user` launcher — its user operand; root where none is named. The shell's `HOME` is that user's
* home (`target`), or the caller's or that user's as the launcher's policy decides (`policy`: `sudo -s`); a switch of
* `loginWith` (`sudo -i`, `su -l`, su's lone `-` operand) starts it as a LOGIN shell — its `HOME` that user's, and it
* stands in that home. A `names-program` switch (`su -m`) keeps the caller's environment, `HOME` with it. */
readonly asUser?: {
readonly userWith?: readonly string[];
readonly home: "target" | "policy";
readonly loginWith: readonly string[];
};
}
/** The user a launcher runs its shell as ({@link LauncherSpec.asUser}): the name, where a word spells it literally; the
* shell's `HOME` (`caller` — kept; `target` — that user's; `either` — one of the two); whether it is a login shell. */
export interface TargetUser {
readonly name?: string;
readonly home: "caller" | "target" | "either";
readonly login: boolean;
}
/** How a program receives the PROGRAM it runs (an interpreter): an option value, an operand (`operands.positional`),
* or standard input when it names none. */
export interface DeliverySpec {
readonly stdinWhenUnnamed: boolean;
}
/** The shell text a re-entry program runs: `-c`'s value, its words joined (`eval`), its non-option words (`parallel`),
* or none (`source FILE` reads a file operand). `stdin: "script"`: where its argv names no text and no script file, it
* runs its STANDARD INPUT (`bash <<EOF`, `… | sh`, `parallel < commands`). */
export type ShellReentry = {
readonly kind: "shell";
readonly text: "c-option" | "words" | "non-option-words" | "file-operand";
readonly stdin?: "script";
}
/** Its operands arrive on a stream and it execs `defaultProgram` when the chain names none (`xargs`). */
| {
readonly kind: "argv";
readonly defaultProgram: string;
};
/** Where a builtin keeps shell text it runs later: its first operand after the options (`trap`), the values of its
* `NAME=VALUE` operands (`alias`), or the values of its shell-text options (`mapfile -C`). */
export type CodeBody = "first-operand" | "assignment-values" | "option-values";
/** How a row is checked against the program: the gate runs the binary, or the row says why it cannot. */
export type Witness = "binary" | {
readonly declared: string;
};
/** One subcommand of a row: its own grammar, and — where its words name paths in their own way — its operands and its
* traversal. Read as a row of its own ({@link subcommandOf}); witnessed with its program's row. */
export interface Subcommand {
readonly grammar: Grammar;
readonly operands?: OperandSpec;
readonly traversal?: TraversalSpec;
}
export interface ProgramRow {
readonly key: string;
/** A versioned spelling (`python3`, `python3.11`) is this row. */
readonly versioned?: true;
readonly grammars: readonly Grammar[];
readonly operands?: OperandSpec;
readonly traversal?: TraversalSpec;
readonly delivery?: DeliverySpec;
readonly launcher?: LauncherSpec;
readonly reentry?: ShellReentry;
readonly body?: CodeBody;
/** `declaration`: performs its `NAME=value` operands as shell assignments (`export`); `inert`: opens no file, starts
* no program and evaluates nothing (`echo`). A declaration builtin is inert only bare. */
readonly builtin?: "declaration" | "inert";
/** What a declaration builtin does to every name it binds with no switch selected ({@link OptionSpec.assigns}):
* `readonly` makes them read-only, as `declare -r` does. */
readonly assigns?: DeclaredAttribute;
/** It moves the working directory through the directory stack (`pushd` / `popd`): the working-directory thread reads
* how (`shell-read-workdir.ts`). */
readonly movesBase?: "stack";
/** A shell block word at the program position: it names no command of its own. */
readonly syntax?: "block";
/** Git-style subcommands: the word after the program's own options names one, and the words after it are read by
* ITS grammar, operands and traversal ({@link subcommandOf}). */
readonly subcommands?: Readonly<Record<string, Subcommand>>;
/** Modules the interpreter runs by name (`python -m <module>`) whose own argv tail is not argv: the role of every word
* after the module name (`timeit` compiles and runs it as program text). */
readonly modules?: Readonly<Record<string, ArgRole>>;
readonly witness: Witness;
}
/** The row bash runs for this basename: the exact key, or — for a row that declares versioned spellings — the name
* with its trailing version dropped (`python3.11` is `python`). */
export declare function programRow(name: string): ProgramRow | undefined;
/** Every row, in table order. */
export declare function programRows(): readonly ProgramRow[];
/** The launcher names — derived from the rows. */
export declare const LAUNCHER_NAMES: ReadonlySet<string>;
/** The block words — derived from the rows. */
export declare const BLOCK_WORD_NAMES: ReadonlySet<string>;
/** Does this program run its argument as SHELL text (`sh -c`, `eval`, `source`, `parallel`)? */
export declare function runsShellText(name: string): boolean;
/** Does this program take its operands from a stream and exec a program with them (`xargs`)? */
export declare function feedsArgvFromStdin(name: string): boolean;
/** The program a stream-fed launcher runs when the chain names none. */
export declare function streamDefaultProgram(name: string): string | undefined;
/** Does this program open none of its operands (they are text, numbers, names, or entries it only examines)? */
export declare function opensNoOperand(name: string): boolean;
/** Does this no-path program evaluate its words (so a rewritten one is still handed over)? */
export declare function evaluatesOperands(name: string): boolean;
/** Is a `NAME=value` argument of this program a value it never opens? */
export declare function assignmentArgumentsAreNotPaths(name: string): boolean;
export declare function isDeclarationBuiltin(name: string): boolean;
/** What one invocation of a declaration builtin does to the names it binds: the row's own attribute and every selected
* switch's ({@link OptionSpec.assigns}). A `-` word reads the grammar's letters, a `+` word its `+` spellings
* ({@link Grammar.plusShort}; a `+` word turns an attribute off — it gives none); a switch word a bash it runs on
* refuses — a letter the table of its sign does not carry — leaves the operands `unsettled`. */
export declare function declaredAttributes(row: ProgramRow | undefined, args: readonly string[]): ReadonlySet<DeclaredAttribute>;
/** Opens no file, starts no program and evaluates nothing (a declaration builtin: only bare — its caller checks). */
export declare function isInertBuiltin(name: string): boolean;
export declare function movesBaseByStack(name: string): boolean;
/** The LONG-OPTION name carried by a token (`--file=p` → `file`, `--reg` → `reg`); `undefined` for anything that is
* not a long option with a non-empty name (`--`, `--=x`, a short option). */
export declare function longOptionNameOf(tok: string): string | undefined;
/** Is `name` a spelling of the long option `full`? The exact name always; a proper prefix — an abbreviation — only where the
* program takes them (`accepts`: {@link Grammar.acceptsAbbreviations}, or {@link Merged.abbreviable} of a merged name). Every
* prefix counts there — `getopt_long`'s ambiguity is not modelled, and each caller makes that over-approximation land on its
* own safe side. This is the one place a long name is matched against another. */
export declare function isLongOptionSpellingOf(name: string, full: string, accepts: boolean): boolean;
/** The languages whose program text the read station parses (the rest is program text it does not read). */
export declare const READ_LANGUAGES: ReadonlySet<string>;
/**
* What program text in a language can do to the reads of the command running it (its `opensVia` reading):
* · `any` — the language opens files (and runs programs) from its text by any spelling: its text is never a path, but
* where it may open what it opens is not readable from it;
* · a token list — the language opens a file only through these words or characters (jq's `import` / `include`; awk's
* `getline`, `system`, `ARGV` / `ARGC` (it can replace the input files), the `(` of a call — an indirect `@f(…)` call
* reaches `system` too — and `|` pipes): text carrying one of them may open a file; text carrying none opens nothing;
* · `never` — the language opens nothing from its text;
* · `parsed` — the station reads the text itself (`sed`: the script's `r` / `w` / `e` commands, `READ_LANGUAGES`);
* · `arithmetic` — the shell's arithmetic evaluator: it opens nothing, but a substitution in an array subscript it
* evaluates runs (the station reads those substitutions itself).
* A language the table does not name is read as `any`.
*/
type ProgramTextOpens = "any" | "never" | "parsed" | "arithmetic" | readonly string[];
/** How program text in `language` opens files ({@link PROGRAM_TEXT_OPENS}; `any` for a language it does not name). */
export declare function programTextOpensOf(language: string): ProgramTextOpens;
/** Does this program text in `language` carry what may make it open a file (`any`, or a token of its list)? `parsed`,
* `arithmetic` and `never` texts answer no: what they open is read elsewhere, or nothing. */
export declare function programTextMayOpen(language: string, text: string): boolean;
/** What a row makes of ONE option token. `unexplained` = the row cannot account for it, and the caller reads it the
* speculative way. `R` is the role a value carries: always known in the candidate view, possibly unmodelled in the
* role view. */
type Reading<R> = {
readonly form: "unexplained";
} | {
readonly form: "no-value";
} | {
readonly form: "attached";
readonly value: string;
readonly role: R;
readonly spec?: OptionSpec;
} | {
readonly form: "separated";
readonly role: R;
readonly spec?: OptionSpec;
};
export type OptionSlotReading = Reading<ArgRole>;
export type OptionRoleReading = Reading<ArgRole | undefined>;
/** Which options a reader may rely on. `candidates`: switches and values of a role the candidate extraction reads
* (a value of any other role, an attached-only SHORT letter and a short letter whose arity the
* implementations dispute are not in it — the extraction reads those the speculative way). `roles`: every declared
* option, its value's role when the row models it — what the binary gate checks the row against. */
type View = "candidates" | "roles";
/** The candidate extraction's reading of one option token: a value whose role it does not read is read the speculative
* way. */
export declare function readOptionSlot(row: ProgramRow, tok: string): OptionSlotReading;
/** The role reading of one option token: every declared option, its value's role where the row models it. */
export declare function readOptionRole(row: ProgramRow, tok: string, next?: string): OptionRoleReading;
/** The row's FIRST positional as a slot a reader reads by its role (grep's pattern, sed's script) — with the options
* that deliver it instead, which leave the first operand an ordinary operand after all. The candidate view has the
* slot only where the extraction reads its role. */
export interface FirstOperandSlot {
readonly role: ArgRole;
readonly suppliedByLetters: string;
readonly suppliedByLongNames: readonly string[];
/** The long names of {@link suppliedByLongNames} a prefix of which supplies it too ({@link Grammar.acceptsAbbreviations}). */
readonly abbreviableLongNames: readonly string[];
/** The other letters that take a value in every implementation: in a cluster, the rest of the token is theirs. */
readonly valueLetters: string;
}
export declare function firstOperandSlot(row: ProgramRow | undefined, view?: View): FirstOperandSlot | undefined;
/** Does this token supply the first-operand slot? A short cluster is read as getopt reads it: scanning left to right,
* a letter that delivers the slot supplies it, and the first OTHER letter that takes a value owns the rest of the
* token (`grep -Dread x f`: `read` is `-D`'s value, its `e` delivers nothing); a letter the row does not declare is
* stepped over (it may be a switch), as digits are (grep's obsolete numeric context spec: `-2ebeta`). A long option
* supplies it by its name, or by a prefix of it where the program takes abbreviations. Over-triggering makes the first operand a CHECKED path candidate, the safe side. */
export declare function suppliesFirstOperandSlot(slot: FirstOperandSlot, tok: string): boolean;
/** The row's options stand anywhere in its argv in every implementation (`find`'s predicates past its paths), so the
* "is a dash-word past the first operand still an option" ambiguity does not exist for it. */
export declare function optionsStandAnywhere(row: ProgramRow | undefined): boolean;
/** The most values a program glob is listed out to; past it the value names files the reader does not list. */
export declare const PROGRAM_GLOB_MAX = 256;
/**
* The values a program glob expands to (curl's URL glob): `{a,b}` sets (no nesting, a `\` escaping the next character),
* `[a-z]` / `[1-9]` / `[01-10:2]` ranges, `\{ \[ \} \]` literal. `undefined` = the reader does not list what the value
* names: more than {@link PROGRAM_GLOB_MAX} values, or a form it does not read (an unmatched or nested bracket, a range
* it cannot parse) — never "names nothing", since a form misread as refused would hide a read.
*/
export declare function programGlobExpansions(value: string): readonly string[] | undefined;
/**
* The path candidates one value offers, which is also the answer to "did this value name a file?" — an empty list IS
* the no. A plain path offers itself; an `indirect` one itself and what it names past an `@`; a `header` only a
* whole-word `@<file>`; a `form` field spec the files after its `@` / `<`; a `url` the local path of a `file:` URL. A
* `programGlob` value offers what each of its expansions offers (`globs: "literal"` = the invocation turned the glob
* off); `undefined` = it expands past {@link PROGRAM_GLOB_MAX}: it names files the reader does not list.
*/
export declare function slotValueCandidates(value: string, role: ArgRole, globs?: "expanded" | "literal"): string[] | undefined;
/** The paths an object name `<rev>:<path>` ({@link ArgRole} `object-path`) may spell: the text after each `:` (a stage
* number, `:1:x`, and a revision spelled with a colon both leave more than one reading — every one is offered). None
* for a word with no `:`, a URL-like `scheme://…`, or an empty path. */
export declare function objectPathsOf(value: string): string[];
/** One word of the argv a candidate reader hands the walk: `skip` = the reader already handed it over (it is stepped
* past, though an option before it may still take it as its value). */
export interface ArgWord {
readonly folded: string;
readonly skip?: boolean;
}
/** What the walk read at one index, in the order a reader must hand the candidates over. `R` as in {@link Reading}. */
type Event<R> =
/** The `--` that ends the options. */
{
readonly kind: "end-of-options";
readonly at: number;
}
/** A dash-word past the first operand on a grammar that may have stopped reading options: it is ALSO an operand. */
| {
readonly kind: "dash-word-operand";
readonly at: number;
}
/** An option word: `no-value`, `attached` (its value inside the word), or `speculative` (the row does not explain
* it, or its separated value is read without being consumed). */
| {
readonly kind: "option";
readonly at: number;
readonly reading: "no-value" | "speculative" | {
readonly attached: string;
readonly role: R;
readonly spec?: OptionSpec;
};
}
/** The value of the separated option at `of`: `consumed` = the walk steps past it; otherwise it is read as that value
* AND later as whatever it is on its own. */
| {
readonly kind: "value";
readonly at: number;
readonly of: number;
readonly role: R;
readonly consumed: boolean;
readonly spec?: OptionSpec;
readonly unsettled?: true;
}
/** An operand, the `ordinal`-th. `slot` = the first-operand slot's role when the slot applies; `role` = the role the
* row declares for an operand at this position past the slot (a URL, a name it only examines); `dash` = the word is
* a lone `-`, read as standard input (`stdin`) or as a file name. */
| {
readonly kind: "operand";
readonly at: number;
readonly ordinal: number;
readonly slot?: ArgRole;
readonly role?: ArgRole;
readonly dash?: "stdin" | "file";
};
export type ArgEvent = Event<ArgRole>;
export type ArgRoleEvent = Event<ArgRole | undefined>;
/** The candidate extraction's walk (the program word excluded). `firstOperandSlot: false` reads every operand as an
* ordinary one. `ownedValues`: a bare option of a traversing program that may take the NEXT word as its value
* ({@link bareOptionValueOf}) hands that word over as a value read both ways (`consumed: false`) — what the roots of a
* recursive form are read from. */
export declare function readArgs(row: ProgramRow | undefined, words: readonly ArgWord[], opts: {
readonly firstOperandSlot: boolean | "program-text";
readonly ownedValues?: true;
}): ArgEvent[];
/** The role walk: the SAME walk, every declared option read by its declared arity and role. What the binary gate
* predicts a binary opens is read off these events. */
export declare function readArgRoles(row: ProgramRow, args: readonly string[]): ArgRoleEvent[];
/**
* Does this invocation take the program's OPERANDS from a list file ({@link OptionSpec.delivers}: `ack --files-from LIST`,
* `tar -T LIST`, `find -files0-from LIST`)? What the program then walks or opens is written in a file this reading does not
* open — no root of it is in the command. The reading of a check that only ever refuses or asks ({@link selectedOptions} over the
* merged row: a word spelled as the option counts, an abbreviation that reaches it counts, a value spelled like it counts). The
* traditional key word is every letter of it an option — each value-taking letter takes one of the arguments that follow, in
* order, so none owns the rest of the word (`tar cfT out.tar list` takes `list` for `T`).
*/
export declare function deliversOperands(row: ProgramRow | undefined, args: readonly string[]): boolean;
/**
* Does this invocation walk its operands' subtrees AND hand back their CONTENTS? Detection over-approximates: a flag
* misread as recursive costs one ask, an under-read hides a traversal. A value-taking letter owns its value only where
* every implementation reads it so; a `--` right after a long option that may take a value is that option's value
* (`grep --label -- -r . .` recurses).
*/
export declare function selectsContentsTraversal(row: ProgramRow | undefined, args: readonly string[]): boolean;
/** With no operand, does some implementation walk the working directory? A contents walk then has `.` as its root. */
export declare function walksCwdWithoutOperand(row: ProgramRow | undefined): boolean;
/**
* Does this invocation turn the program's own value glob off (`curl -g`, `--globoff`)? Read with the role walk, so a
* spelling that is another option's value does not count; a cluster counts the switch only up to its first letter that
* is not an unambiguous switch, a long name only when it abbreviates nothing else, a switch behind an option the row
* does not explain is not trusted (it may be that option's value), and a `--no-` spelling of the switch anywhere turns
* the glob back on — every doubt reads the glob ON (more candidates, never fewer).
*/
export declare function valuesAreLiteral(row: ProgramRow | undefined, args: readonly string[]): boolean;
/** A lone `-` operand is standard input to this program (absent row: it is). */
export declare function dashOperandIsStdin(row: ProgramRow | undefined): boolean;
/** Does the row declare an option (in any implementation, short, long or dash word) the predicate holds for? */
export declare function declaresOption(row: ProgramRow, pred: (spec: OptionSpec) => boolean): boolean;
/**
* Does this option token take the NEXT word as a value that never names a file (a count, a label, a pattern, a
* delimiter)? Read for a count of the operands a program is handed, in the direction that lowers it: an arity the
* implementations dispute counts as taking the value (some implementation does), and a long spelling counts when any
* name it can abbreviate takes one. A value that may name a file — or that delivers the first positional (`grep -e`,
* whose value the count states as one of its operands) — is not stepped over: a `-` there is a standard-input read the
* count must still see. getopt's cluster rule: the FIRST value-taking letter owns the rest of the token.
*/
export declare function takesSeparatedDatum(row: ProgramRow | undefined, tok: string): boolean;
/**
* The value the NEXT word may be, for an option token written BARE (no value attached) — the one place the "which word does this
* option own" question of a cluster or an optional count is answered. Each grammar of the row reads the token as getopt does (a
* cluster: a letter the row does not declare is a switch, the first value-taking letter owns the rest of the token, so the next
* word only when it ends the token; a long name: the name or, where the grammar takes abbreviations, any name it abbreviates,
* `--name=` carries its own value):
* · a REQUIRED value is the next word wherever the option is read — the extraction's slot reading fails to see it where the token
* is a cluster with a letter the row leaves undeclared (`rg -nA 2 pat`: rg / ag / ack declare no switches), and `tok` is then
* read the speculative way;
* · an OPTIONAL count (the value only attached) is the next word to a parser that reads an optional integer (Getopt::Long's `:i`:
* ack's `-A` / `-B` / `-C`) or a required one (GNU grep's `--context`) when that word is spelled like a count, and an operand to
* a parser that reads it attached-only (getopt_long's optional argument: ag's long names, BSD grep) — the row files it
* attached-only, the reading that consumes nothing.
* · a long name the row declares NOWHERE (not as a name, nor — in a grammar that takes abbreviations — as the abbreviation of one)
* may take the next word: the row cannot say it does not (`rg --hostname-bin x pat`, whose option runs a program, is left
* undeclared on purpose; `rg --ignore pat sub`, a switch of rg that is no abbreviation of `--ignore-file` there) — the word's value role is
* {@link UNDECLARED_VALUE}, no more than "names no file", as it is also read as whatever it is on its own. A long name with its
* value attached owns nothing, and one the row declares as a switch owns nothing.
* A SHORT letter the row leaves undeclared owns no word: the rows of rg / ag / ack declare no switches, so every word behind `-i`
* would otherwise be one — the letter is read as the switch it is in rg (whose table of value letters is complete). The extraction
* reads the word both ways (`consumed: false` — as the value, and as whatever it is on its own). Served to the contents walkers
* (`readArgs` `ownedValues`), whose rows carry no single-dash WORD options (`find -name`): a cluster here is always letters.
*/
export declare function bareOptionValueOf(row: ProgramRow, tok: string, next: string | undefined): {
readonly role: ArgRole;
readonly spec?: OptionSpec;
} | undefined;
/**
* Does this option word carry, ATTACHED, the value `-` for an option whose value is a file the program opens or names
* (`grep -f-`, `diff --from-file=-`, `diff -X-`) — or for a spelling the row does not account for? Such a word makes the
* program read its standard input, out of sight of any operand count.
*/
export declare function attachedStdinFile(row: ProgramRow | undefined, tok: string): boolean;
/** The row read under each implementation's grammar alone (one view per grammar), or the row itself when it declares
* at most one. A reader that needs to know what ONE implementation does with an argv reads these views. */
export declare function implementationsOf(row: ProgramRow): readonly ProgramRow[];
/** What a scan over an argv's option words found: the specs selected, the values they took (argv index; the value
* inside the option word when it is attached), and the operands (argv indices). */
interface OptionScan {
readonly specs: readonly OptionSpec[];
/** Each selected option's spelling as its row declares it (`-x`, `--exec`), in step with `specs`. */
readonly names: readonly string[];
readonly values: readonly {
readonly at: number;
readonly value?: string;
readonly spec: OptionSpec;
readonly name: string;
}[];
readonly operands: readonly number[];
}
/**
* Every option spec an argv selects. A short cluster is read as getopt reads it, scanning left to right: a declared
* letter is selected; a value-taking letter owns the rest of the token (and the next word, when it ends the token); a
* letter the row does not declare is read as a switch and the scan goes on. A long option is every name its spelling
* can abbreviate where the grammar takes abbreviations (the exact name alone where there is one, and always in a grammar
* that takes none); a dash word its exact name. Two readings:
* · over ONE implementation's view ({@link implementationsOf}): what that program selects — a separated value is
* stepped over, `--` ends the options, and so does the first operand where the grammar stops there;
* · over the row (every implementation merged): every word is read as the option it SPELLS — a value spelled like an
* option, and a word past `--`, included. The reading a check that only ever refuses takes: it errs to more options.
*/
export declare function selectedOptions(row: ProgramRow | undefined, args: readonly string[], under?: "one-implementation"): OptionSpec[];
/** The options ONE implementation's reading of an argv selects ({@link selectedOptions}), named by the spelling its row
* declares them under (`-x`, `--exec`), and the values they take. An option is told apart by its spelling, never by its
* spec: spellings share specs (every switch of a row is one). */
export declare function selectedSpellings(row: ProgramRow, args: readonly string[]): Pick<OptionScan, "names" | "values">;
/** Does ONE implementation of a row (`view`, {@link implementationsOf}) reject these option words — a spelling the row
* declares (another implementation's) that this one does not? getopt calls it an invalid option: the program runs
* nothing. */
export declare function implementationRejects(row: ProgramRow, view: ProgramRow, words: readonly string[]): boolean;
/** A path role whose effect writes. */
export type WritingRole = Extract<ArgRole, {
kind: "path";
}>;
/** Does this role write its path ({@link WRITING_EFFECTS})? */
export declare function writesPath(role: ArgRole | undefined): role is WritingRole;
/** One word an implementation's reading writes: its argv index, the value inside it when an option carries it
* attached, and the role it is written by. */
export interface WrittenWord {
readonly at: number;
readonly value?: string;
readonly role: WritingRole;
}
/** What ONE implementation's reading of an argv writes. */
export interface WriteReading {
/** The words the reading writes, by the role each is read in. */
readonly written: readonly WrittenWord[];
/** The role the row's ordinary operands write with in this reading (an in-place edit's operands, a removal's, a
* copy's sources), or `undefined` when they write nothing here. */
readonly operandRole?: WritingRole;
/** The reading cannot account for some option word (one this implementation does not declare, whose value may be any
* word that follows): every word the command hands the program may be written, by {@link operandRole}. */
readonly unexplained: boolean;
/** The backup suffixes an option selecting edit-in-place was given (empty values dropped: no backup). */
readonly suffixes: readonly string[];
/** A copy's destination (argv index, and its value when an option carries it attached) and its sources. */
readonly copy?: {
readonly destination: {
readonly at: number;
readonly value?: string;
};
readonly sources: readonly number[];
};
}
/**
* Every implementation's reading of what an argv (the program word excluded) WRITES: the words read in a writing role
* — an option value, an operand by its position, the ordinary operands an option made edited in place, a copy's last
* operand as its destination — and the facts a write face needs beside them. Read with the role walk
* ({@link readArgRoles}) under each implementation alone ({@link implementationsOf}): no reader of writes carries a
* grammar of its own.
*/
export declare function writeReadings(row: ProgramRow, args: readonly string[]): WriteReading[];
/** How this invocation receives its program: `text` (an option value or the program operand is program text), `stdin`
* (it reads the program from its standard input), or `undefined` (it names one — a script file, a module — or names
* none on an interpreter that then reads none). `undefined` too for a row that is no interpreter. */
export type ProgramDelivery = "text" | "stdin";
/**
* Read over the argv with the program word excluded. One rule for every doubt: an option the row does not explain never
* ENDS the search for program text. The word that names the program stops the scan, but only while every option so far
* was one the row EXPLAINS: after an option of unknown arity the next word may be its value rather than the program.
*/
export declare function programDelivery(row: ProgramRow | undefined, args: readonly string[]): ProgramDelivery | undefined;
/** The language of the program an interpreter row runs: the language of its program operand, or of the first option that
* delivers program text or a program file. `undefined` for a row that runs no program text. */
export declare function programLanguageOf(row: ProgramRow | undefined): string | undefined;
/**
* The argv indices some implementation of the row reads as a path it OPENS (an ordinary operand, a value or operand of a
* reading path role, a program file) while another reads them as something else (program text, a backup suffix, a
* datum) — a reading the filesystem decides. Empty where the row has one implementation, or where
* any implementation cannot account for an option of the argv (its reading is then no evidence either way).
*/
export declare function wordsReadBySomeImplementations(row: ProgramRow | undefined, args: readonly string[]): ReadonlySet<number>;
/** The words an interpreter hands a module it runs by name (`python -m timeit …`) when the row says what that module does
* with them ({@link ProgramRow.modules}): the index of the first such word and their role; `undefined` when the
* invocation names no such module. Read with the role walk: the module name is the value of an option that names the
* program. */
export declare function moduleTailOf(row: ProgramRow | undefined, args: readonly string[]): {
readonly from: number;
readonly role: ArgRole;
} | undefined;
/** The arity of a launcher option spelled EXACTLY (`-u`, `--unset`, a stepped `--`): 0 for a switch or an option whose
* value exists only attached (spelled bare, it takes nothing), 1 for one that takes the next word; `undefined` for any
* other spelling and for an option the walk does not step over. */
export declare function launcherOptionArity(row: ProgramRow, tok: string): 0 | 1 | undefined;
/** The PATH role of the value a launcher option word takes (`xargs -a FILE`, `strace -fo FILE`, `strace -oFILE`), or
* `undefined` when its value names no path ({@link readLauncherOption}). Such a value is a word the launcher opens or
* writes, not an operand of its own. */
export declare function launcherOptionPathRole(row: ProgramRow, tok: string): Extract<ArgRole, {
kind: "path";
}> | undefined;
/** Does this launcher option word move the base its program runs in — the directory, the root, or where its word is looked
* up (an option whose value's role is a path with a `base`) — read off the option itself, whether or not its value is
* written (`nsenter -w` bare takes the target process's directory)? In a cluster, a letter up to the first that takes a
* value. `false` for any word the walk does not step. */
export declare function launcherOptionMovesBase(row: ProgramRow, tok: string): boolean;
/** Does this launcher option word select a LOOKUP ({@link OptionSpec.mode} `queries`: `command -v`, `-V`, a cluster
* carrying one — `-pv`), so that the words after the options are names and no program is run? In a cluster, a letter up
* to the first that takes a value. `false` for any word the walk does not step. */
export declare function launcherOptionQueries(row: ProgramRow, tok: string): boolean;
/** How many words one launcher option occupies ({@link readLauncherOption}), or `undefined` where the row does not
* explain it. */
export declare function launcherOptionStep(row: ProgramRow, tok: string): 1 | 2 | undefined;
/** Does a launcher that runs a shell ({@link LauncherSpec.shellText}) run one over these words — the words after it —
* rather than the program they name? Not where an implementation selects one of its {@link LauncherSpec.programWith}
* options (as that implementation reads them: past `--` a word is an operand). */
export declare function launcherRunsShell(row: ProgramRow, args: readonly string[]): boolean;
/** The user a launcher runs its shell as ({@link LauncherSpec.asUser}), read off its own words (`words`, as the program
* receives them) by its row's walk: the value of its last `userWith` option, else its user operand (`operand`; a lone `-`
* in front of it starts a login shell, `dash`), else root — a name only where it is spelled as one (`root`, `#0`, a login
* name); `undefined` for a launcher that runs no other user. */
export declare function targetUserOf(row: ProgramRow, words: readonly string[], operand?: {
readonly name?: string;
readonly dash: boolean;
}): TargetUser | undefined;
/** The spellings of a launcher's command-line options (`env -S` / `--split-string`): the value is a command line the
* launcher splits and runs. */
export declare function commandLineOptionSpellings(row: ProgramRow | undefined): readonly string[];
/** The command line ONE launcher option word carries, read as getopt reads the word ({@link readLauncherOption}): a
* command-line spelling ({@link commandLineOptionSpellings}) exactly — `"next"`, the next word is the line — or with its
* value after `=` (long) or after the letter (short, `attached`); in a short cluster every letter before the
* command-line letter is a switch the walk steps (`env -vS 'S'`, `env -iS'S'`). `undefined` where the word carries
* none. */
export declare function commandLineOf(row: ProgramRow, tok: string): {
readonly attached: string;
} | "next" | undefined;
/** One implementation's reading of where the program text is: the text (every text option's value joined by newlines,
* or the first operand), `from-file` (an option names a FILE holding it), `unparsed` (an option the grammar does not
* declare, or a text option with nothing left to take), or `none` (no program text at all). */
export type ProgramTextReading = {
readonly text: string;
} | "from-file" | "unparsed" | "none";
/** The language of the row's program text when the read station parses it (its first positional is program text in a
* read language), else `undefined`. */
export declare function readProgramTextLanguage(row: ProgramRow | undefined): string | undefined;
/** The program text of an invocation of a row whose first positional is program text, under EACH implementation's
* grammar (no text says which one runs, so a reader combines the readings). */
export declare function programTextReadings(row: ProgramRow, args: readonly string[]): ProgramTextReading[];
/**
* The subcommand an argv (the program word excluded) names, and the row it is read by: the first word past the
* program's own options, which are read EXACTLY by the row's grammar — an option the row does not declare may take the
* next word, so no subcommand is claimed past it. `at` = the subcommand word's index; `relocated` = an option before it
* moves where the program works (a value whose role is a path with a base — `git -C <dir>`), so the subcommand's paths
* are not relative to the command's working directory. The subcommand's row carries its own grammar, operands and
* traversal, and its program's witness.
*/
export declare function subcommandOf(row: ProgramRow | undefined, words: readonly string[]): {
readonly name: string;
readonly at: number;
readonly row: ProgramRow;
readonly relocated: boolean;
} | undefined;
/**
* The indices of the words a row's subcommand reads as message text: the value of its message option attached or as the
* next word, by its own grammar. The global options are read exactly ({@link subcommandOf}); in the subcommand an unknown
* long option takes no value, an unknown short letter or an unsettled word takes the next word (which is then never a
* message). The option word itself is settled; its separate value is a message whether the text settles it or the shell
* computes it as ONE argument — every expansion in it a command substitution in double quotes, whose output is one field
* (a parameter is not taken so: `"$@"` and `"${a[@]}"` are several).
*/
export declare function messageWords(program: string, words: readonly {
readonly folded: string;
readonly expands: unknown;
readonly word?: {
readonly expansions: readonly WordPiece[];
};
}[], programIndex: number): Set<number>;
/** The most bytes a read may be bounded to and still count as small (`head -c N`): a bound above it is no bound a person would call one. */
export declare const SMALL_BYTE_BOUND_MAX = 1000000;
/**
* Does this invocation read at most a SMALL, LITERAL number of BYTES? The rule is positive: the row's role walk ({@link readArgRoles})
* must find an option the row says bounds the output in BYTES ({@link OptionSpec.bounds}), valued with a plain integer within
* {@link SMALL_BYTE_BOUND_MAX}, and NO other option word — a line bound is no bound for a source that holds no newline, and a
* switch, a spelling the row does not explain or an option-shaped word past an operand makes the invocation unreadable, which is
* not exempt (the safe side). `false` for a program with no row.
*/
export declare function byteBoundIsSmall(row: ProgramRow | undefined, args: readonly string[]): boolean;
export {};