UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

211 lines • 11.3 kB
import type { PipelineStages, TSNodeLike } from './types.ts'; import { ProcessSubDirection, Redirect } from './types.ts'; export declare function getText(node: TSNodeLike): string; /** The root of the tree `node` belongs to. */ export declare function treeRoot(node: TSNodeLike): TSNodeLike; /** * Whether `after` stands on `before`'s line within `root`: no newline between * them. The parse has joined continued lines and folded each heredoc body * into its statement, so a newline between two statements is a line break. * Mirrors Python's same_line. */ export declare function sameLine(root: TSNodeLike, before: TSNodeLike, after: TSNodeLike): boolean; /** * The row the shell began reading `node`'s command on. bash reads a whole * line before running any of it, and a complete command spanning lines * whole, with the rest of the line it ends on: a command after a `;`, or * inside a group that spans rows, was read with the ones before it. Mirrors * Python's read_row. */ export declare function readRow(node: TSNodeLike): number; /** * A node's children with the source text between them, the twin of * python's `source_parts`. * * The parser consumes some text without giving it a node: * whitespace and newlines inside a double-quoted string, and the whitespace * or line continuation opening a `${v:-word}` operand. Only the node's own * source still holds that text, so it is sliced out between child extents * rather than rebuilt from row or byte counts, which lose tabs, newlines and * escapes. The parser counts `startIndex` here in UTF-16 code units, the * units `text.slice` takes. */ export declare function sourceParts(node: TSNodeLike): Generator<string | TSNodeLike>; /** * Walk a double-quoted string without losing scanner-owned text. * * The text between children is the string's own, and the closing quote * token can carry the whitespace before it. Expansion nodes keep their own * folded prefixes. */ export declare function quotedParts(node: TSNodeLike): Generator<string | TSNodeLike>; /** * Where an index into a node's text falls in the parser's offsets, the twin * of python's `byte_offset`. * * The Python parser places a node by the bytes of the UTF-8 source, so an * index counted in code units reads one place too early for every * multibyte character before it. `grep -ob` reads the same answer for the * same reason. * `encodeText` rather than `TextEncoder` because a byte that is not valid * UTF-8 rides as a surrogate escape and stands for one byte. That is a * requirement on the caller, not a hope: grep's family decodes every line * through `decodeText` for it. */ export declare function byteOffset(text: string, index: number): number; export declare function getCommandName(node: TSNodeLike): string; export declare function getParts(node: TSNodeLike): TSNodeLike[]; /** * Whether unquoted text holds a brace expansion (`{a,b}`, `{1..3}`), * which the shell turns into several words. */ export declare function braceExpands(text: string): boolean; /** * The text a word names before any expansion, or null. * * A word is literal when nothing in it waits on the shell: a plain * word, a number, a quoted string with no expansion inside, or a * concatenation of those. Quotes are removed, escapes resolved and a * leading unquoted `~` expanded the way expansion would (`home` null * leaves it literal, as bash does with no `$HOME`). A word carrying a * parameter, command, arithmetic or process substitution, or a brace * expression, answers null: what it names is known only when it runs. */ export declare function literalWord(node: TSNodeLike, home?: string | null): string | null; /** Split FOO=1 BAR=2 cmd parts into [assignments, remaining]. */ export declare function splitEnvPrefix(parts: TSNodeLike[]): [TSNodeLike[], TSNodeLike[]]; export declare function getPipelineCommands(node: TSNodeLike): [TSNodeLike[], boolean[]]; /** * A pipeline's stages as bash reads them, whatever shape the parse gave * them. * * The parser lets a redirect close over everything to its left up * to the next pipe, so `a && b | c < f | d` parses as a pipeline whose * first stage is `redirected(a && b | c, < f)`, and `! a < f | b` as one * whose first stage is `redirected(! a, < f)`. Bash reads them as * `a && (b | c <f | d)` and `! (a <f | b)`: the redirect binds to the * command it follows, the stages on both sides of it are one pipeline, a * `!` negates all of it, and a list the parse pulled into the first * stage runs ahead of the pipeline and decides whether it runs at all. * This is the last-command chain the admission gate climbs for a * redirect's target (`statementRedirects`), read in the direction the * executor walks. `redirects` are hoisted over the whole pipeline and * bind to its last stage. */ export declare function getPipelineStages(node: TSNodeLike, redirects?: readonly Redirect[]): PipelineStages; export declare function getWhileParts(node: TSNodeLike): [TSNodeLike[], TSNodeLike[]]; /** * Get (variable, values, bodyCommands) from for/select. `values` is null for * a header with no `in` (`for f do`), which loops over `"$@"`. */ export declare function getForParts(node: TSNodeLike): [string, TSNodeLike[] | null, TSNodeLike[]]; /** * ([init, cond, update], body) from a C-style for. The expression slots * are positional between the (( )) delimiters, separated by `;` tokens, * and any of them may be empty: `for ((;;))`. A slot holds every node and * token the parser found in it, in order, commas and stray operators * included, since bash evaluates the slot's text as one expression: `for * ((a=1, i=0; ...))` assigns both, and `i<1 2` is an error, not two * expressions. */ export declare function getCforParts(node: TSNodeLike): [TSNodeLike[][], TSNodeLike[]]; /** * Whether a statement's terminator is `&`. * * The parser puts the `&` beside the statement it ends, inside whatever * body holds them both, so a body read as named children (every * extractor above) never sees it. Asking the statement about its own * next sibling is what lets a loop body, an if/case arm, a brace group * and a function body launch the job the program loop launches for a * top-level `cmd &`. */ export declare function isBackgrounded(node: TSNodeLike): boolean; export declare const REDIRECT_NODE_TYPES: ReadonlySet<string>; /** * Parse all redirects from a redirected_statement. * * Returns [command, redirects]; command is null for a bare redirect * like `> file` (bash runs the empty command and applies redirects, * creating/truncating the file). */ export declare function getRedirects(node: TSNodeLike): [TSNodeLike | null, Redirect[]]; /** * The redirects written among a simple command's words, in order: bash * applies them wherever they stand (`> f echo hi`, `cat <<< x`). */ export declare function commandRedirects(node: TSNodeLike): Redirect[]; /** * Redirects hoisted onto a command, after the ones written among its words: * bash applies them in source order (`true && > a echo > b`). Mirrors * Python's with_own_redirects. */ export declare function withOwnRedirects(command: TSNodeLike, redirects: readonly Redirect[]): Redirect[]; export declare function getListParts(node: TSNodeLike): [TSNodeLike, string | null, TSNodeLike]; export declare function getIfBranches(node: TSNodeLike): [[TSNodeLike[], TSNodeLike[]][], TSNodeLike[] | null]; export declare function getCaseWord(node: TSNodeLike): TSNodeLike; /** * Get (patternNodes, bodyStatements, terminator) triples from case. * * Patterns are every named child before the arm's `)`, kept as nodes so * quoting survives to the matcher: 'a'), "$x") and $'a\n') all mean literal * text where a bare word keeps its globs live. An arm's body is every * statement up to its terminator, so multi-statement arms * (x) cmd1; cmd2;;) keep all commands. */ export declare function getCaseItems(node: TSNodeLike): [TSNodeLike[], TSNodeLike[], string][]; export declare function getDeclarationKeyword(node: TSNodeLike): string; /** * Get every operand word of an unset_command, keeping `-f`/`-v`/`-n` and * keeping a subscript target (`unset arr[1]`, quoted or not) as one word. * A redirect among or before the words is no operand. Mirrors Python's * `get_unset_args`. */ export declare function getUnsetArgs(node: TSNodeLike): string[]; /** The command a `!` negates; null for a bare `!`, which negates the empty command. */ export declare function getNegatedCommand(node: TSNodeLike): TSNodeLike | null; export declare function getProcessSubDirection(node: TSNodeLike): ProcessSubDirection | null; /** * Bash's single-file command substitution, measured against 5.2.37. * Only a lone foreground `< file` (optionally `0<`) reads input into * the substitution. Extra redirects, commands, heredocs and descriptor * duplication retain ordinary redirect-only semantics. */ export declare function inputSubstitutionRedirect(node: TSNodeLike): Redirect | null; /** A process substitution's command text, with the heredoc bodies the line * reads after it moved inside it. */ export declare function getProcessSubBody(node: TSNodeLike): string; export declare function getFunctionName(node: TSNodeLike): string; /** * Get function body commands: the compound_statement's children, or any * other compound command (`f() ( ... )`) as the one statement. The redirects * a definition carries, its own and those of a statement it is the body of * (`f() { ...; } >o 2>&1`), apply at every call, as bash's do, so then the * body is one statement: the group under them. Mirrors Python's * get_function_body. */ /** * The redirects a function definition carries: its own, and those of a * statement it is the body of (`f() { ...; } >o 2>&1`, whose second * redirect the parser hangs on a redirected_statement around it). */ export declare function getFunctionRedirects(node: TSNodeLike): TSNodeLike[]; /** The definition's source, including redirects and heredoc bodies. */ export declare function getFunctionSource(node: TSNodeLike): string; /** Parse one stored definition inside the caller's owned parse scope. */ export declare function parseFunction(source: string, parse: (source: string) => TSNodeLike): TSNodeLike[]; export declare function getFunctionBody(node: TSNodeLike): TSNodeLike[] | null; /** * What an unquoted plain word parses as: the only words bash checks for an * alias, a name of digits included. Mirrors Python's ALIAS_WORD_TYPES. */ export declare const ALIAS_WORD_TYPES: ReadonlySet<string>; /** * A command with its alias words replaced as bash reads it, and the aliases * being expanded at each unit of the result. An insertion carries the * replaced word's guards and its own name, so no alias expands inside its own * text, while the words around it keep theirs. A value ending in a blank * checks the command's next word, the next child of the command, which an * unquoted word must be. Mirrors Python's alias_rewrite. */ export declare function aliasRewrite(node: TSNodeLike, head: TSNodeLike, value: (name: string, blocked: ReadonlySet<string>) => string | null, guards: readonly ReadonlySet<string>[]): [string, ReadonlySet<string>[]] | null; //# sourceMappingURL=helpers.d.ts.map