ZSH 完成取决于提供的参数

ZSH 完成取决于提供的参数

有没有办法在 ZSH 完成脚本中访问已提供的参数作为变量?

这是例子:

#compdef test

_test_comp(){
 t=($(cat /tmp/file_with_opts))
 _wanted t expl "availavle options" compadd -a t
}

_arguments -C -S  \
 '-f[input file]:filename:_files' \
 '*:test_autocomplete:_test_comp'

test脚本将从硬编码文件中选取选项/tmp/file_with_opts,我希望能够从通过定义的文件中选取自动完成选项-f。或者更确切地说,如果-f <filename>已定义,我想解析此文件而不是默认文件。有任何提示如何执行此操作吗?

答案1

这看起来有点像 XY 问题;究竟是什么促使通过提供的选项改变完成方式?就像可以通过环境变量来完成更改一样,或者为什么完成需要改变?

无论如何,在选项处理过程中的某个时刻,文件可能会导致问题,具体取决于-f ...相对于命令行上其他内容的显示位置。此外,完成代码将被重复调用,因此在对命令的相同实例和新实例的不同调用之间维护状态可能会很棘手。而且也$(cat /tmp/file_with_opts)很糟糕,因为它不必要地分叉cat然后分割内容......好吧,谁知道呢。

考虑到这些问题,找出可用选项的一种方法是set > ~/tmp/what-is-set在完成代码的适当部分添加类似内容,然后在有和没有选项的不同位置用光标点击 Tab -f ...,然后检查输出文件查看完成脚本可以使用哪些内容:

% grep file_ what-is-set
BUFFER='foo  -f file_with_opts '
RBUFFER=' -f file_with_opts '
opt_args=( [-f]=file_with_opts )
words=( foo '' -f file_with_opts )

在这种情况下,我在之后foo和之前进行制表符补全-f ...,因此为了改变补全行为,可以检查BUFFER或更好地检查words数组,因为BUFFER-f ...程序无关的其他命令可能会混淆补全脚本。

因此,如果我们循环words,我们可以根据选项是否存在(无需太多错误检查)来改变读取的文件,-f ...如下所示:

#compdef foo

local curcontext="$curcontext" state line ret=1

_arguments -C -S  \
  '-f[input file]:filename:_files' \
  '*:options:->vary' \
  && ret=0

case "$state" in
  vary)
    integer i
    local optsfile
    #set > ~/tmp/what-is-set
    # default filename
    optsfile=~/tmp/file_with_opts
    for (( i = 1; i <= $#words - 1; i++ )); do
      if [[ $words[$i] == -f ]]; then
        optsfile=$words[$((i+1))]
        break
      fi
    done
    # cat-free read of file with split on newlines
    t=(${(f)"$(<$optsfile)"})
    _wanted t expl "available options" compadd -a t
  ;;
esac

return $ret

研究该$fpath[-1]目录下现有的完成情况可能会有所帮助。

相关内容