使用 zsh 自动加载完成管理尾随字符

使用 zsh 自动加载完成管理尾随字符

我正在尝试创建一个自动加载完成文件对于 zsh。为此,我_myprog在 fpath 中的文件夹中添加了一个文件。

这个文件大致是这样的:

#compdef myprog
_myprog () {
    local cmd
    if (( CURRENT > 2)); then
        cmd=${words[2]}
        curcontext="${curcontext%:*:*}:myprog-$cmd"
        (( CURRENT-- ))
        shift words
        case "${cmd}" in
          list|ls)
            _arguments : "--limit[Max depth]" "--folders[Print flat list of folders]"
            _describe -t commands "myprog list" subcommands
          ;;
          insert)
            _arguments : "--force[Overwrite file]" "--append[Append to existing data]"
            _describe -t commands "myprog insert" subcommands
            _myprog_complete_folders
          ;;
        esac
    else
        local -a subcommands
        subcommands=(
          "insert:Insert a new file"
          "list:List existing files"
        )
        _describe -t command 'myprog' subcommands
        _arguments : "--yes[Assume yes]" 
        _myprog_complete_files
    fi
}

_myprog_complete_files () {
    _values 'files' $(myprog ls)
}

_myprog_complete_folders () {
    _values 'folders' $(myprog ls --folders)
}

_myprog

所以,我的程序有两种我想要自动完成的场景:

  1. 当不使用子命令时,我想指定远程位置的路径。这是由函数完成的,_myprog_complete_files感谢函数_value。文件列表是通过运行提供的myprog ls,它在新行上打印每个远程文件。

  2. 插入新的远程文件时,我希望能够自动完成文件夹名称,这也是在_myprog_complete_folders使用函数中完成的_value,但这次文件夹列表是使用生成的myprog ls --folder,它只打印文件夹。

到目前为止一切顺利...除了当我用来<tab><tab>显示值列表并且我试图在文件夹名称后面键入文件名时,zsh 在文件夹名称后面插入一个空格。

例如:

$ myprog insert web<tab><tab><tab>
 -- folders --
web/                          web/foo/                web/bar/

应该选择web/foo,它有效地执行了此操作并自动完成,myprog insert web/foo/ 但请注意尾随空格!因此,如果我在选择要使用的文件夹后尝试直接键入要插入的文件的名称(<tab>假设我想调用它)baz,那么我最终会发现myprog insert web/foo/ baz这根本不是我的目标。

我尝试浏览 zsh 文档,但没有成功。例如,我尝试 zstyle ':completion::complete:myprog-insert:' add-space false在 .zshrc 和文件中进行设置,但均无济于事_myprog。设置与未设置时我什至看不出有什么区别。

我猜我一定错过了一些东西,因为能够在自动完成后直接键入以指定参数等似乎是一个理想的功能。

答案1

add-space中的代码似乎$fpath[-1]/_expand与您通过 ; 的完成无关_values。这可以通过add-space在所有地方设置为 false 来检查,或者通过调用_complete_debug并查看完成过程经历了哪些代码:

% bindkey -M viins "^t" _complete_debug
% foo 
Trace output left in /tmp/zsh438foo2 (up-history to view)

一种解决方案是使用-s ...的功能_values,它可以选择插入通常用于连接多个值的分隔符,然后在使用分隔符时禁用该功能:

#compdef foo
local curcontext="$curcontext" state line

choices=(aaa bbb ccc)

_arguments '1:dir:->folders' && return 0

case "$state" in
  folders)
    if ! compset -P '*/'; then
      _values -s / folders $choices
    fi
  ;;
esac

其中 afoo atab应该附加一个斜杠,然后从/现在开始compset测试应该阻止额外的完成。

相关内容