import { CommandSchema, ErasedCommand } from "../schema/command.mjs"; import { FlagLookupEntry, ParseOptions } from "../parse/index.mjs"; //#region src/core/cli/dispatch.d.ts /** * Flag lookup (spelling → {@link FlagLookupEntry}) used to make the * command-name scan aware of value-flag arity. Built from the flags valid at * the current dispatch level via {@link buildFlagLookup}. * * @internal */ type ValueFlagLookup = ReadonlyMap; /** Successful dispatch — target command found with argv path. */ interface DispatchMatch { /** Discriminant — a command name in argv matched a registered command. */ readonly kind: 'match'; /** The matched (target) command. */ readonly command: ErasedCommand; /** Root → target (inclusive). Used for `collectPropagatedFlags()`. */ readonly commandPath: readonly CommandSchema[]; /** argv after consuming command name segments. */ readonly remainingArgv: readonly string[]; } /** Target has subcommands but no handler and no subcommand was specified/matched. */ interface DispatchNeedsSubcommand { /** Discriminant — command group reached without a subcommand or handler. */ readonly kind: 'needs-subcommand'; /** The group command that needs a subcommand. */ readonly command: ErasedCommand; /** Root → group (inclusive). */ readonly commandPath: readonly CommandSchema[]; } /** Unknown command name at this dispatch level. */ interface DispatchUnknown { /** Discriminant — no registered command matched the input token. */ readonly kind: 'unknown'; /** The unrecognised input token. Empty string when no token present. */ readonly input: string; /** Commands available at the level where matching failed. */ readonly candidates: readonly ErasedCommand[]; /** Ancestor path up to (but not including) the unknown level. */ readonly parentPath: readonly CommandSchema[]; } /** Discriminated result of recursive command dispatch. */ type DispatchResult = DispatchMatch | DispatchNeedsSubcommand | DispatchUnknown; /** * Recursively walk argv, consuming command name segments from the front. * * At each level, the first non-flag token is tested as a command name * against the provided command map. If matched and the matched command * has subcommands, dispatch recurses into the child level with the * remaining argv. * * Ambiguity resolution for commands that have both an action handler AND * subcommands (e.g. `git remote` lists remotes, `git remote add` dispatches): * - If the next token matches a subcommand → descend * - If the next token is unknown and the command has a handler → match here * - If the next token is unknown and no handler → propagate unknown error * - If no next token and command has a handler → match here * - If no next token and no handler → needs-subcommand * * @param argv - Remaining argv tokens (command names + flags + args). * @param commands - Command map at the current tree level. * @param ancestorPath - Schema path from root to current level (exclusive). * @param valueFlags - Lookup of flags valid at this level, used so a * space-separated value-flag's value (`--region eu`) is not mistaken for a * command name. Empty by default (arity-unaware, legacy behaviour). * @param parseOptions - Parser toggles (case parity) applied to descent-level * flag lookups built inside dispatch. * @returns Discriminated dispatch result. * * @internal */ declare function dispatch(argv: readonly string[], commands: ReadonlyMap, ancestorPath?: readonly CommandSchema[], valueFlags?: ValueFlagLookup, parseOptions?: ParseOptions): DispatchResult; /** * Whether a flag token consumes the following argv token as its value. * * Mirrors the parser's value-consumption rules (`parseLongFlag` / * `parseShortFlags`) so the command-name scan skips exactly the tokens the * parser would treat as flag values: * - `--flag value` → consumes when `--flag` is a known value-flag. * - `--flag=value` → self-contained, consumes nothing. * - `-abc value` → consumes only when the trailing short flag is a value-flag; * an earlier value-flag char takes the rest of the group as an inline value. * * Unknown flags conservatively consume nothing (the parser reports them later). * * @internal */ declare function consumesFollowingToken(token: string, valueFlags: ValueFlagLookup): boolean; /** * Levenshtein distance between two strings. * @internal */ declare function levenshtein(a: string, b: string): number; /** * Find the closest command name match for a "did you mean?" suggestion. * * Searches command names and aliases. Returns `undefined` if no * sufficiently close match exists (threshold: 3). * * @internal */ declare function findClosestCommand(input: string, commands: readonly ErasedCommand[]): string | undefined; /** * Deduplicate commands from a name+alias map. * * A map keyed by name *and* alias contains duplicate entries for aliased * commands. This returns unique commands (by schema identity). * * @internal */ declare function uniqueCommands(commands: ReadonlyMap): readonly ErasedCommand[]; //#endregion export { type DispatchMatch, type DispatchNeedsSubcommand, type DispatchResult, type DispatchUnknown, type ValueFlagLookup, consumesFollowingToken, dispatch, findClosestCommand, levenshtein, uniqueCommands };