EdgeAIG/opencode / .opencode /node_modules /effect /dist /unstable /cli /internal /completions /zsh.js
| // --------------------------------------------------------------------------- | |
| // Helpers | |
| // --------------------------------------------------------------------------- | |
| const escapeZsh = s => s.replace(/\\/g, "\\\\").replace(/'/g, "'\\''").replace(/:/g, "\\:"); | |
| const sanitize = s => s.replace(/[^a-zA-Z0-9_]/g, "_"); | |
| /** | |
| * All forms of a flag (--name, -alias, --no-name) for the exclusion group. | |
| */ | |
| const allForms = flag => { | |
| const forms = [`--${flag.name}`]; | |
| for (const alias of flag.aliases) { | |
| forms.push(alias.length === 1 ? `-${alias}` : `--${alias}`); | |
| } | |
| if (flag.type._tag === "Boolean") { | |
| forms.push(`--no-${flag.name}`); | |
| } | |
| return forms; | |
| }; | |
| const valueAction = type => { | |
| switch (type._tag) { | |
| case "Boolean": | |
| return ""; | |
| case "Choice": | |
| return `:value:(${type.values.join(" ")})`; | |
| case "Path": | |
| return type.pathType === "directory" ? `:directory:_directories` : `:file:_files`; | |
| case "Integer": | |
| return `:integer:`; | |
| case "Float": | |
| return `:float:`; | |
| case "Date": | |
| return `:date:`; | |
| default: | |
| return `:value:`; | |
| } | |
| }; | |
| const argAction = type => { | |
| switch (type._tag) { | |
| case "Choice": | |
| return `(${type.values.join(" ")})`; | |
| case "Path": | |
| return type.pathType === "directory" ? `_directories` : `_files`; | |
| default: | |
| return ``; | |
| } | |
| }; | |
| /** | |
| * Produce _arguments optspecs for a single flag. Each spec is a complete, | |
| * single-quoted string — no brace expansion, no line continuations. | |
| */ | |
| const flagSpecs = flag => { | |
| const specs = []; | |
| const desc = flag.description ? `[${escapeZsh(flag.description)}]` : ""; | |
| const action = valueAction(flag.type); | |
| const excl = `(${allForms(flag).join(" ")})`; | |
| // Primary long name | |
| specs.push(`'${excl}--${flag.name}${desc}${action}'`); | |
| // Aliases | |
| for (const alias of flag.aliases) { | |
| const prefix = alias.length === 1 ? "-" : "--"; | |
| specs.push(`'${excl}${prefix}${alias}${desc}${action}'`); | |
| } | |
| // Boolean negation | |
| if (flag.type._tag === "Boolean") { | |
| const negDesc = flag.description ? `[${escapeZsh(`Disable ${flag.name}`)}]` : ""; | |
| specs.push(`'${excl}--no-${flag.name}${negDesc}'`); | |
| } | |
| return specs; | |
| }; | |
| const argSpec = arg => { | |
| const desc = arg.description ? escapeZsh(arg.description) : arg.name; | |
| const action = argAction(arg.type); | |
| const prefix = arg.variadic ? "*" : ""; | |
| return `'${prefix}:${desc}:${action}'`; | |
| }; | |
| // --------------------------------------------------------------------------- | |
| // Generator | |
| // --------------------------------------------------------------------------- | |
| const generateFunction = (descriptor, parentPath, lines) => { | |
| const currentPath = [...parentPath, descriptor.name]; | |
| const funcName = `_${currentPath.map(sanitize).join("_")}`; | |
| lines.push(`${funcName}() {`); | |
| if (descriptor.subcommands.length > 0) { | |
| // _arguments -C requires these locals for the state machine | |
| lines.push(` local context state state_descr line`); | |
| lines.push(` typeset -A opt_args`); | |
| lines.push(``); | |
| // Subcommand list | |
| lines.push(` local -a commands`); | |
| lines.push(` commands=(`); | |
| for (const sub of descriptor.subcommands) { | |
| const desc = sub.description ? escapeZsh(sub.description) : ""; | |
| lines.push(` '${sub.name}:${desc}'`); | |
| } | |
| lines.push(` )`); | |
| lines.push(``); | |
| // Build specs array to avoid brace expansion / line continuation issues | |
| lines.push(` local -a specs`); | |
| lines.push(` specs=(`); | |
| for (const flag of descriptor.flags) { | |
| for (const spec of flagSpecs(flag)) { | |
| lines.push(` ${spec}`); | |
| } | |
| } | |
| for (const arg of descriptor.arguments) { | |
| lines.push(` ${argSpec(arg)}`); | |
| } | |
| lines.push(` '1:command:->command'`); | |
| lines.push(` '*::arg:->args'`); | |
| lines.push(` )`); | |
| lines.push(``); | |
| lines.push(` _arguments -C "\${specs[@]}"`); | |
| lines.push(``); | |
| // State dispatch | |
| lines.push(` case "$state" in`); | |
| lines.push(` command)`); | |
| lines.push(` _describe -t commands 'commands' commands`); | |
| lines.push(` ;;`); | |
| lines.push(` args)`); | |
| lines.push(` case "$words[1]" in`); | |
| for (const sub of descriptor.subcommands) { | |
| const subFunc = `_${[...currentPath, sub.name].map(sanitize).join("_")}`; | |
| lines.push(` ${sub.name})`); | |
| lines.push(` ${subFunc}`); | |
| lines.push(` ;;`); | |
| } | |
| lines.push(` esac`); | |
| lines.push(` ;;`); | |
| lines.push(` esac`); | |
| } else { | |
| // Leaf command — no subcommands | |
| const allSpecs = []; | |
| for (const flag of descriptor.flags) { | |
| allSpecs.push(...flagSpecs(flag)); | |
| } | |
| for (const arg of descriptor.arguments) { | |
| allSpecs.push(argSpec(arg)); | |
| } | |
| if (allSpecs.length > 0) { | |
| lines.push(` local -a specs`); | |
| lines.push(` specs=(`); | |
| for (const spec of allSpecs) { | |
| lines.push(` ${spec}`); | |
| } | |
| lines.push(` )`); | |
| lines.push(` _arguments "\${specs[@]}"`); | |
| } | |
| } | |
| lines.push(`}`); | |
| lines.push(``); | |
| for (const sub of descriptor.subcommands) { | |
| generateFunction(sub, currentPath, lines); | |
| } | |
| }; | |
| /** @internal */ | |
| export const generate = (executableName, descriptor) => { | |
| const lines = []; | |
| const safeName = sanitize(executableName); | |
| lines.push(`#compdef ${executableName}`); | |
| lines.push(`###-begin-${executableName}-completions-###`); | |
| lines.push(`#`); | |
| lines.push(`# Static completion script for Zsh`); | |
| lines.push(`#`); | |
| lines.push(`# Installation:`); | |
| lines.push(`# ${executableName} --completions zsh > ~/.zsh/completions/_${executableName}`); | |
| lines.push(`# then add ~/.zsh/completions to your fpath`); | |
| lines.push(`#`); | |
| lines.push(``); | |
| generateFunction(descriptor, [], lines); | |
| lines.push(`# Handle both direct invocation and autoload`); | |
| lines.push(`if [[ "\${zsh_eval_context[-1]}" == "loadautofunc" ]]; then`); | |
| lines.push(` _${safeName} "$@"`); | |
| lines.push(`else`); | |
| lines.push(` compdef _${safeName} ${executableName}`); | |
| lines.push(`fi`); | |
| lines.push(`###-end-${executableName}-completions-###`); | |
| return lines.join("\n"); | |
| }; | |
| //# sourceMappingURL=zsh.js.map |
Xet Storage Details
- Size:
- 6.15 kB
- Xet hash:
- 67997f03dbd845d8242070bca3c68a24a19ea5285899d837b81d88a55dbad680
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.