6090508bad
- Add curly braces to all if/else/for/while statements - Fix indentation and trailing spaces - Auto-fixed 372 linting errors using eslint --fix - Remaining issues are warnings only (non-null assertions, explicit any types)
151 lines
4.7 KiB
TypeScript
151 lines
4.7 KiB
TypeScript
import type { Command } from 'commander';
|
|
import { mkdirSync, writeFileSync } from 'fs';
|
|
import { resolve } from 'path';
|
|
import { homedir } from 'os';
|
|
|
|
const SUBCOMMANDS = ['start', 'tui', 'send', 'sessions', 'doctor', 'config', 'setup', 'completion'];
|
|
|
|
const SUBCOMMAND_OPTIONS: Record<string, string[]> = {
|
|
start: ['-c', '--config'],
|
|
tui: ['-c', '--config', '-f', '--fullscreen'],
|
|
send: ['-c', '--config', '--no-tools'],
|
|
config: ['-c', '--config', '--raw'],
|
|
setup: ['-c', '--config'],
|
|
completion: ['--install'],
|
|
};
|
|
|
|
export function generateBashCompletion(): string {
|
|
const subcmds = SUBCOMMANDS.join(' ');
|
|
const cases = Object.entries(SUBCOMMAND_OPTIONS)
|
|
.map(([cmd, opts]) => ` ${cmd}) COMPREPLY=( $(compgen -W "${opts.join(' ')}" -- "$cur") ) ;;`)
|
|
.join('\n');
|
|
|
|
return `# Flynn bash completion — generated by 'flynn completion bash'
|
|
_flynn_completions() {
|
|
local cur prev subcmd
|
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
|
|
if [[ \${COMP_CWORD} -eq 1 ]]; then
|
|
COMPREPLY=( $(compgen -W "${subcmds} --help --version" -- "$cur") )
|
|
return
|
|
fi
|
|
|
|
subcmd="\${COMP_WORDS[1]}"
|
|
case "$subcmd" in
|
|
${cases}
|
|
completion) COMPREPLY=( $(compgen -W "bash zsh fish --install" -- "$cur") ) ;;
|
|
*) COMPREPLY=() ;;
|
|
esac
|
|
}
|
|
complete -F _flynn_completions flynn
|
|
`;
|
|
}
|
|
|
|
export function generateZshCompletion(): string {
|
|
const subcmds = SUBCOMMANDS.map(c => `'${c}:${c} subcommand'`).join(' ');
|
|
const cases = Object.entries(SUBCOMMAND_OPTIONS)
|
|
.map(([cmd, opts]) => {
|
|
const flags = opts.filter(o => o.startsWith('--')).map(o => `'${o}'`).join(' ');
|
|
return ` ${cmd}) compadd ${flags} ;;`;
|
|
})
|
|
.join('\n');
|
|
|
|
return `#compdef flynn
|
|
# Flynn zsh completion — generated by 'flynn completion zsh'
|
|
_flynn() {
|
|
local -a subcmds
|
|
subcmds=(${subcmds})
|
|
|
|
if (( CURRENT == 2 )); then
|
|
_describe 'command' subcmds
|
|
return
|
|
fi
|
|
|
|
case "\${words[2]}" in
|
|
${cases}
|
|
completion) compadd bash zsh fish '--install' ;;
|
|
*) ;;
|
|
esac
|
|
}
|
|
compdef _flynn flynn
|
|
`;
|
|
}
|
|
|
|
export function generateFishCompletion(): string {
|
|
const lines = [
|
|
'# Flynn fish completion — generated by \'flynn completion fish\'',
|
|
'# Disable file completions by default',
|
|
'complete -c flynn -f',
|
|
'',
|
|
'# Subcommands',
|
|
];
|
|
|
|
for (const cmd of SUBCOMMANDS) {
|
|
lines.push(`complete -c flynn -n '__fish_use_subcommand' -a '${cmd}' -d '${cmd} subcommand'`);
|
|
}
|
|
lines.push('complete -c flynn -n \'__fish_use_subcommand\' -l help -d \'Show help\'');
|
|
lines.push('complete -c flynn -n \'__fish_use_subcommand\' -l version -d \'Show version\'');
|
|
lines.push('');
|
|
lines.push('# Subcommand options');
|
|
|
|
for (const [cmd, opts] of Object.entries(SUBCOMMAND_OPTIONS)) {
|
|
for (const opt of opts) {
|
|
const flag = opt.replace(/^-+/, '');
|
|
const short = opt.startsWith('--') ? '' : ` -s ${flag}`;
|
|
const long = opt.startsWith('--') ? ` -l ${flag}` : '';
|
|
lines.push(`complete -c flynn -n '__fish_seen_subcommand_from ${cmd}'${short}${long}`);
|
|
}
|
|
}
|
|
|
|
lines.push('complete -c flynn -n \'__fish_seen_subcommand_from completion\' -a \'bash zsh fish\' -d \'Shell type\'');
|
|
lines.push('');
|
|
|
|
return lines.join('\n');
|
|
}
|
|
|
|
function getInstallPath(shell: string): string {
|
|
const home = homedir();
|
|
switch (shell) {
|
|
case 'bash': return resolve(home, '.local/share/bash-completion/completions/flynn');
|
|
case 'zsh': return resolve(home, '.zfunc/_flynn');
|
|
case 'fish': return resolve(home, '.config/fish/completions/flynn.fish');
|
|
default: throw new Error(`Unknown shell: ${shell}`);
|
|
}
|
|
}
|
|
|
|
export function registerCompletionCommand(program: Command): void {
|
|
program
|
|
.command('completion')
|
|
.description('Generate shell completion script')
|
|
.argument('<shell>', 'Shell type: bash, zsh, or fish')
|
|
.option('--install', 'Install to standard location')
|
|
.action((shell: string, opts: { install?: boolean }) => {
|
|
const generators: Record<string, () => string> = {
|
|
bash: generateBashCompletion,
|
|
zsh: generateZshCompletion,
|
|
fish: generateFishCompletion,
|
|
};
|
|
|
|
const generator = generators[shell];
|
|
if (!generator) {
|
|
console.error(`Unknown shell: ${shell}. Supported: bash, zsh, fish`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const script = generator();
|
|
|
|
if (opts.install) {
|
|
const installPath = getInstallPath(shell);
|
|
mkdirSync(resolve(installPath, '..'), { recursive: true });
|
|
writeFileSync(installPath, script, 'utf-8');
|
|
console.log(`Completion script installed to: ${installPath}`);
|
|
if (shell === 'zsh') {
|
|
console.log('Ensure ~/.zfunc is in your fpath: fpath=(~/.zfunc $fpath)');
|
|
}
|
|
} else {
|
|
process.stdout.write(script);
|
|
}
|
|
});
|
|
}
|