function writeCompletionRegistrationWarning(message: string): void {
process.stderr.write(`[completion] ${message}\n`);
}
async function registerSubcommandsForCompletion(program: Command): Promise<void> { const entries = getSubCliEntries(); for (const entry of entries) { if (entry.name === "completion") { continue;
} try {
await registerSubCliByName(program, entry.name);
} catch (error) {
writeCompletionRegistrationWarning(
`skipping subcommand \`${entry.name}\` while building completion cache: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
}
export function registerCompletionCli(program: Command) {
program
.command("completion")
.description("Generate shell completion script")
.addHelpText( "after",
() =>
`\n${theme.muted("Docs:")} ${formatDocsLink("/cli/completion", "docs.openclaw.ai/cli/completion")}\n`,
)
.addOption( new Option("-s, --shell <shell>", "Shell to generate completion for (default: zsh)").choices(
COMPLETION_SHELLS,
),
)
.option("-i, --install", "Install completion script to shell profile")
.option( "--write-state", "Write completion scripts to $OPENCLAW_STATE_DIR/completions (no stdout)",
)
.option("-y, --yes", "Skip confirmation (non-interactive)", false)
.action(async (options) => { // Route logs to stderr so plugin loading messages do not corrupt // the completion script written to stdout.
routeLogsToStderr(); const shell = options.shell ?? "zsh";
// Completion needs the full Commander command tree (including nested subcommands). // Our CLI defaults to lazy registration for perf; force-register core commands here. const ctx = getProgramContext(program); if (ctx) { for (const name of getCoreCliCommandNames()) {
await registerCoreCliByName(program, ctx, name);
}
}
// Eagerly register all subcommands except completion itself to build the full tree.
await registerSubcommandsForCompletion(program);
case $state in
(args) case $line[1] in
${program.commands.map((cmd) => `(${cmd.name()}) _${rootCmd}_${cmd.name().replace(/-/g, "_")} ;;`).join("\n ")}
esac
;;
esac
}
${generateZshSubcommands(program, rootCmd)}
_${rootCmd}_register_completion() { if (( ! $+functions[compdef] )); then return0
fi
_${rootCmd}_register_completion if (( ! $+functions[compdef] )); then
typeset -ga precmd_functions if [[ -z "\${precmd_functions[(r)_${rootCmd}_register_completion]}" ]]; then
precmd_functions+=(_${rootCmd}_register_completion)
fi
fi
`; return script;
}
function generateBashCompletion(program: Command): string { // Simplified Bash completion using dynamic iteration logic (often hardcoded in static scripts) // For a robust implementation, usually one maps out the tree. // This assumes a simple structure. const rootCmd = program.name();
// We can use a recursive function to build the case statements return `
_${rootCmd}_completion() {
local cur prev opts
COMPREPLY=()
cur="\${COMP_WORDS[COMP_CWORD]}"
prev="\${COMP_WORDS[COMP_CWORD-1]}"
# Simple top-level completion for now
opts="${program.commands.map((c) => c.name()).join("")} ${program.options.map((o) => o.flags.split("")[0]).join("")}"
case"\${prev}" in
${program.commands.map((cmd) => generateBashSubcommand(cmd)).join("\n ")}
esac
if [[ \${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) ) return0
fi
function generateBashSubcommand(cmd: Command): string { // This is a naive implementation; fully recursive bash completion is complex to generate as a single string without improved state tracking. // For now, let's provide top-level command recognition. return `${cmd.name()})
opts="${cmd.commands.map((c) => c.name()).join("")} ${cmd.options.map((o) => o.flags.split("")[0]).join("")}"
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) ) return0
;;`;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.