zsh 完成调用触发命令生成参数

zsh 完成调用触发命令生成参数

cmd我有一个运行任务的脚本。cmd存在于多个目录中。每个实例都cmd定义了自己的任务,这些任务成为参数。

我希望每个副本cmd都能根据需要生成自己的补全内容。

./cmd tasks将输出脚本的每个副本中可用的换行符分隔参数的列表。

$./cmd tasks
delete 
dump
help
other

以下 zsh_cmd在运行时根据需要工作./cmd

#compdef cmd

args=( $(./cmd tasks) )
_arguments '*: :(${args})'

但由于该定义中的路径是静态的,因此当我运行或任何路径变体./cmd时,完成会失败。/somedir/cmd

完成定义中似乎缺少诸如 a 之类的$0可用触发命令_cmd

我可以看到有某些方法可以调用_arguments返回控件并填充一些额外的状态:

  local context state line state_descr
  _arguments -C '*::arg:->args'

但同样,我还没有看到任何类似的$0传入命令被填充。我之前没有创建过完成,所以使用_arguments事件可能不是执行此操作的正确方法,这只是我在尝试此操作时遇到的第一个可行的解决方案。

如何定义 zsh 完成,从触发完成的命令生成可用参数?

答案1

该命令及其参数位于words大批。所以打电话$words[1]

而不是直接调用它,而是通过_call_program,它负责一些细节,例如允许替换和设置区域设置C(即英语消息、默认美国日期格式等)。

编写优秀、复杂的补全函数所需的大部分信息都在手册中,但通常很难找到包含所需信息的半句话,或者更糟糕的是,将多个地方所需的信息拼凑在一起每一个都很难找到。弄清楚某些事情的最简单方法通常是寻找执行类似操作的现有完成函数,阅读它的功能,并使用手册获取有关它使用的函数和变量的信息。但即便如此也并不理想,因为并非 zsh 附带的所有功能都能正常工作。例如,我首先检查了_gitwhich 非常大并且有很多东西的示例,但是对于这个特定任务它做错了,调用git$path.所以这里有一个很好的例子_gpg

allopts=( $(_call_program options $words[1] --dump-options) )

因此,在您的情况下, ifcmd接受多个参数,每个参数都是任务名称(例如您可以调用cmd dump dump tasks other):

tasks=($(_call_program tasks $words[1] tasks))
_arguments "*:task:($tasks)"

或者,如果它的第一个参数是cmd任务名称,并且后续参数是该任务名称,则让我们_arguments进行解析。它将数组设置line为非选项参数。

local context state state_descr line
typeset -A opt_args
tasks=($(_call_program tasks $words[1] tasks))
_arguments \
  '--global-option[This is an example global option that goes before the task name]' \
  "1:task:($tasks)" \
  "*:arg:->args"
case $state in
  args)
    … # here $line[1] is the task name
    ;;
esac

相关内容