(theme: ThemeName)
| 78 | * shell's rc file. Returns a user-facing status message. |
| 79 | */ |
| 80 | export async function setupShellCompletion(theme: ThemeName): Promise<string> { |
| 81 | const shell = detectShell() |
| 82 | if (!shell) { |
| 83 | return '' |
| 84 | } |
| 85 | |
| 86 | // Ensure the cache directory exists |
| 87 | try { |
| 88 | await mkdir(dirname(shell.cacheFile), { recursive: true }) |
| 89 | } catch (e: unknown) { |
| 90 | logError(e) |
| 91 | return `${EOL}${color('warning', theme)(`Could not write ${shell.name} completion cache`)}${EOL}${chalk.dim(`Run manually: ncode completion ${shell.shellFlag} > ${shell.cacheFile}`)}${EOL}` |
| 92 | } |
| 93 | |
| 94 | // Generate the completion script by writing directly to the cache file. |
| 95 | // Using --output avoids piping through stdout where process.exit() can |
| 96 | // truncate output before the pipe buffer drains. |
| 97 | const ncodeBin = process.argv[1] || 'ncode' |
| 98 | const result = await execFileNoThrow(ncodeBin, [ |
| 99 | 'completion', |
| 100 | shell.shellFlag, |
| 101 | '--output', |
| 102 | shell.cacheFile, |
| 103 | ]) |
| 104 | if (result.code !== 0) { |
| 105 | return `${EOL}${color('warning', theme)(`Could not generate ${shell.name} shell completions`)}${EOL}${chalk.dim(`Run manually: ncode completion ${shell.shellFlag} > ${shell.cacheFile}`)}${EOL}` |
| 106 | } |
| 107 | |
| 108 | // Check if rc file already sources completions |
| 109 | let existing = '' |
| 110 | try { |
| 111 | existing = await readFile(shell.rcFile, { encoding: 'utf-8' }) |
| 112 | if ( |
| 113 | existing.includes('ncode completion') || |
| 114 | existing.includes(shell.cacheFile) |
| 115 | ) { |
| 116 | return `${EOL}${color('success', theme)(`Shell completions updated for ${shell.name}`)}${EOL}${chalk.dim(`See ${formatPathLink(shell.rcFile)}`)}${EOL}` |
| 117 | } |
| 118 | } catch (e: unknown) { |
| 119 | if (!isENOENT(e)) { |
| 120 | logError(e) |
| 121 | return `${EOL}${color('warning', theme)(`Could not install ${shell.name} shell completions`)}${EOL}${chalk.dim(`Add this to ${formatPathLink(shell.rcFile)}:`)}${EOL}${chalk.dim(shell.completionLine)}${EOL}` |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | // Append source line to rc file |
| 126 | try { |
| 127 | const configDir = dirname(shell.rcFile) |
| 128 | await mkdir(configDir, { recursive: true }) |
| 129 | |
| 130 | const separator = existing && !existing.endsWith('\n') ? '\n' : '' |
| 131 | const content = `${existing}${separator}\n# NCode shell completions\n${shell.completionLine}\n` |
| 132 | await writeFile(shell.rcFile, content, { encoding: 'utf-8' }) |
| 133 | |
| 134 | return `${EOL}${color('success', theme)(`Installed ${shell.name} shell completions`)}${EOL}${chalk.dim(`Added to ${formatPathLink(shell.rcFile)}`)}${EOL}${chalk.dim(`Run: source ${shell.rcFile}`)}${EOL}` |
| 135 | } catch (error) { |
| 136 | logError(error) |
| 137 | return `${EOL}${color('warning', theme)(`Could not install ${shell.name} shell completions`)}${EOL}${chalk.dim(`Add this to ${formatPathLink(shell.rcFile)}:`)}${EOL}${chalk.dim(shell.completionLine)}${EOL}` |
no test coverage detected