如何从任意目录对脚本应用制表符补全?

如何从任意目录对脚本应用制表符补全?

我有一个 bash 自动完成功能_customcomplete,我想将其应用于名为 的脚本run.sh。如果我调用complete -F _customcomplete ./run.sh,那么只要我在同一个目录中并使用 调用它,自动完成脚本就可以正常工作./run.sh。但是,如果我上一级并使用 调用它./scripts/run.sh,自动完成脚本就不起作用。更重要的是,如果我在与另一个名为 的脚本不同的目录中run.sh,自动完成脚本就会在该脚本上工作,而它不应该工作。

简而言之,是否可以将 bash 自动完成函数绑定到特定的可执行文件而不是调用字符串?

这是一个完整简化的示例:

completion.sh是一个非常简单的完成脚本,它总是返回三个选项one two three::

_customcomplete() {
  local word="${COMP_WORDS[COMP_CWORD]}"
  COMPREPLY=( $(compgen -W "one two three" -- "$word") )
}

我可以使用以下资源source completion.sh并可以验证它是否来源于type _customcomplete

_customcomplete is a function
_customcomplete() {
  local word="${COMP_WORDS[COMP_CWORD]}"
  COMPREPLY=( $(compgen -W "one two three" -- "$word") )
}

在一个目录中,我有两个文件夹scriptsother,它们都包含一个名为的脚本run.sh。每个都只回显命令行参数以及一条唯一的消息来区分两者。

现在让我们尝试将补全函数注册到 中,run.sh方法scripts是进入脚本目录并运行complete -F _customcomplete ./run.sh。现在我可以调用./run.sh并使用制表符补全来查看 的可能性one two three。但是,如果我尝试从上面的目录中将其调用为./scripts/run.sh,我会得到默认的文件系统制表符补全建议。此外,如果我cd进入other,自定义制表符补全也适用于该脚本。

仅当使用与调用字符串完全相同的全局路径时,将命令更改complete为链接到任何类型的全局路径才允许自定义 Tab 键补全。我想要的是能够通过任何相对路径调用脚本,并让自定义 Tab 键补全按预期工作。

答案1

似乎您想为命令的特定实例创建补全,而不管它是如何调用的(通过绝对路径或相对路径),但不希望为其他可能共享相同名称但位于其他地方的实例创建补全。例如,您可能希望为位于 的脚本创建补全~/bin/example.sh,但不希望为 创建补全/usr/bin/example.sh

根据Bash 参考手册8.6 可编程完成,bashcomplete没有内置您想要的功能。但是,在您的_customcomplete函数中,您可以使用找到被调用脚本的位置readlink,然后进行COMPREPLY相应的自定义:

_customcomplete() {
    local CMD_NAME=`readlink -f "$1"`
    local word="${COMP_WORDS[COMP_CWORD]}"

    if [[ $CMD_NAME == '/home/user/bin/example.sh' ]] ; then
        COMPREPLY=( $(compgen -W "one two three" -- "$word") )
    fi
} &&

complete -F _customcomplete example.sh

相关内容