gpt4 book ai didi

node.js - 使用 --experimental-specifier-resolution=node 时如何让 yargs 自动完成工作

转载 作者:行者123 更新时间:2023-12-05 05:50:39 26 4
gpt4 key购买 nike

我的目标是在 Typescript/node.js 中编写一个 CLI,它使用 --experimental-specifier-resolution=node,用 yargs 编写,支持自动完成。

为了完成这项工作,我使用了这个 entry.sh 文件,多亏了这个有用的 SO anwswer (并且 package.json 中的 bin: {eddy: "./entry.sh"} 选项指向这个文件)

#!/usr/bin/env bash

full_path=$(realpath $0)
dir_path=$(dirname $full_path)
script_path="$dir_path/dist/src/cli/entry.js"

# Path is made thanks to: https://code-maven.com/bash-shell-relative-path
# Combined with knowledge from: https://stackoverflow.com/questions/68111434/how-to-run-node-js-cli-with-experimental-specifier-resolution-node

/usr/bin/env node --experimental-specifier-resolution=node $script_path "$@"

效果很好,我可以使用 CLI。但是,自动完成不起作用。根据 yargs,我应该能够通过将 ./entry.sh completion 的结果输出到 ~/.bashrc 配置文件来获得自动完成功能。然而,这似乎不起作用。

./entry.sh 完成的输出:

###-begin-entry.js-completions-###
#
# yargs command completion script
#
# Installation: ./dist/src/cli/entry.js completion >> ~/.bashrc
# or ./dist/src/cli/entry.js completion >> ~/.bash_profile on OSX.
#
_entry.js_yargs_completions()
{
local cur_word args type_list

cur_word="${COMP_WORDS[COMP_CWORD]}"
args=("${COMP_WORDS[@]}")

# ask yargs to generate completions.
type_list=$(./dist/src/cli/entry.js --get-yargs-completions "${args[@]}")

COMPREPLY=( $(compgen -W "${type_list}" -- ${cur_word}) )

# if no match was found, fall back to filename completion
if [ ${#COMPREPLY[@]} -eq 0 ]; then
COMPREPLY=()
fi

return 0
}
complete -o default -F _entry.js_yargs_completions entry.js
###-end-entry.js-completions-###

我尝试修改 completion 输出,但我还不太了解 bash - 只是还不懂 😎

更新

正在研究可重现的示例 (WIP)。 repo 是 here .

目前最大的区别之一是 npm link 在 2 个不同的环境中工作不一样。只有在我试图重现 /usr/local/share/npm-global/bin/ 的 repo 中才实际更新。目前正试图对此进行调查。

最佳答案

您可以尝试指定 scriptName在您的 entry.js 文件中添加到包装器脚本的名称。这可能会强制使用它生成完成名称。我还没有尝试过,但是查看 yargs 的源代码,似乎可以使用 scriptName 更改 $0 参数,这反过来会影响完成方式-生成函数生成完成代码:

yargs-factor.ts 中:

  scriptName(scriptName: string): YargsInstance {
this.customScriptName = true;
this.$0 = scriptName;
return this;
}

completion.ts 中:

  generateCompletionScript($0: string, cmd: string): string {
let script = this.zshShell
? templates.completionZshTemplate
: templates.completionShTemplate;
const name = this.shim.path.basename($0);

// add ./ to applications not yet installed as bin.
if ($0.match(/\.js$/)) $0 = `./${$0}`;

script = script.replace(/{{app_name}}/g, name);
script = script.replace(/{{completion_command}}/g, cmd);
return script.replace(/{{app_path}}/g, $0);
}

我也不确定 "bin" 配置是如何工作的,但可能是因为 scriptName 你不再需要包装器了。

确保您使用的 yargs 版本支持这一点。

此外,作为旁注,我考虑过建议直接修改生成的完成脚本,但除了骇人听闻之外,还可能导致脚本名称在完成期间无法识别。无论如何,我只是先看看正确的方法。

修改后的版本是这样的:

_entry.sh_yargs_completions()
{
local cur_word args type_list

cur_word="${COMP_WORDS[COMP_CWORD]}"
args=("${COMP_WORDS[@]}")

# ask yargs to generate completions.
type_list=$(/path/to/entry.sh --get-yargs-completions "${args[@]}")

COMPREPLY=( $(compgen -W "${type_list}" -- ${cur_word}) )

# if no match was found, fall back to filename completion
if [ ${#COMPREPLY[@]} -eq 0 ]; then
COMPREPLY=()
fi

return 0
}
complete -o default -F _entry.sh_yargs_completions entry.sh

另一个注意事项:如果脚本名称需要根据其调用者的名称动态变化,您可以通过环境变量使其可识别,因此在 entry.sh 中您可以这样声明:

export ENTRY_JS_SCRIPT_NAME=entry.sh
node ...

然后在entry.js的某处,你可以通过这个访问变量名:

process.env.ENTRY_JS_SCRIPT_NAME

甚至可以指定 $0${0##*/} 任何有效:

export ENTRY_JS_SCRIPT_NAME=$0

关于node.js - 使用 --experimental-specifier-resolution=node 时如何让 yargs 自动完成工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70496353/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com