Skip to content

Instantly share code, notes, and snippets.

@xymopen
Last active July 27, 2024 08:22
Show Gist options
  • Save xymopen/554fbb170c3f0b68810d283a19f1c9b9 to your computer and use it in GitHub Desktop.
Save xymopen/554fbb170c3f0b68810d283a19f1c9b9 to your computer and use it in GitHub Desktop.
print source-able pwsh completion script for Node.js
import { execFile as childProcessExecFile } from "node:child_process"
import { execPath, stdout } from "node:process"
import { promisify } from "node:util"
const execFile = promisify(childProcessExecFile)
const pwshCompletionTemplatePrefix =
`using namespace System.Management.Automation
using namespace System.Management.Automation.Language
$options = `
const pwshCompletionTemplateSuffix = `
Register-ArgumentCompleter -Native -CommandName 'node' -ScriptBlock {
param($wordToComplete)
if ($wordToComplete -like '-*') {
$options | Where-Object {
$_.StartsWith($wordToComplete)
} | ForEach-Object {
Write-Output -InputObject (New-Object -Type System.Management.Automation.CompletionResult -ArgumentList $_, $_, "ParameterValue", $_)
}
}
}`
// @see {@link https://github.com/nodejs/node/blob/v20.16.0/src/node_exit_code.h#L8}
const kNoFailure = 0
// @see {@link https://github.com/nodejs/node/blob/v20.16.0/src/node_options.cc#L1132-L1168}
const prefix =
"_node_complete() {\n" +
" local cur_word options\n" +
" cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n" +
" if [[ \"${cur_word}\" == -* ]] ; then\n" +
" COMPREPLY=( $(compgen -W '"
const suffix =
"' -- \"${cur_word}\") )\n" +
" return 0\n" +
" else\n" +
" COMPREPLY=( $(compgen -f \"${cur_word}\") )\n" +
" return 0\n" +
" fi\n" +
"}\n" +
"complete -o filenames -o nospace -o bashdefault " +
"-F _node_complete node node_g" +
// An additional LF is appended during `printf()`
// @see {@link https://github.com/nodejs/node/blob/v20.16.0/src/node.cc#L1040}
"\n"
const nodeProcessPromise = execFile(execPath, ['--completion-bash'], {
encoding: 'utf8'
})
const { child: nodeProcess } = nodeProcessPromise
const { stdout: nodeOut } = await nodeProcessPromise
// EOL is dependent on the platform and we need to normalize it
const nodeBashCompletion = nodeOut.replace(/\r?\n|\r(?!\n)/g, '\n')
if (nodeProcess.exitCode !== kNoFailure || !nodeBashCompletion.startsWith(prefix) || !nodeBashCompletion.endsWith(suffix)) {
throw new Error('Unsupported node bash complete output')
} else {
const items = nodeBashCompletion.slice(prefix.length, -suffix.length).split(' ')
stdout.write(
pwshCompletionTemplatePrefix +
items.map(item => `"${item}"`).join(', ') +
pwshCompletionTemplateSuffix
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment