bash 中任何目录中“~/bin/*”文件名的命令参数补全

bash 中任何目录中“~/bin/*”文件名的命令参数补全

bash 的一个基本功能是完成存储在各个 bin 目录中的命令,无论当前工作目录如何。这允许用户保持命令和二进制文件的组织,而不需要他们指定需要运行的目录的完整路径。

在我之前 bash 到底是如何提供这个命令完成的跑步我认为,从设计的角度来看,这些 bin 文件,在我之前期望相同的命令完成是有意义的编辑他们。

在我的特定情况下,这意味着修改我的编辑器的完成功能,vi因此它不仅包含来自我当前工作目录的文件名,还包含来自我的文件名~/bin/(我实际上并不关心添加来自其他容器的命令)。

一个简单的修改所以答案是这样的:

$ source _vi 
$ complete -f -F _vi vi

其中 _vi 定义为:

_vi () 
{
    local word=${COMP_WORDS[COMP_CWORD]};
    local pat="~/bin/*"

    COMPREPLY=($(compgen -f -G "$pat" -- "~/bin/${word}"));

    i=0
    for item in "${COMPREPLY[@]}"; do
        COMPREPLY[$i]="${item##*/}"
        i+=1
    done;
    return 0;
}

但是 vi 需要传递完整路径才能打开文件!

所以我的问题是:我怎样才能制表符完整文件名来自~/bin/但仍然经过的完整路径vi?这只是一个|梦吗?我应该尝试一种完全不同的方法吗?

~/bin/*我用vi (TAB)(TAB)!

编辑:

下面是我正在使用的函数,基于 @roaima 的答案和他们对下面概括的建议。为除我关心的两个目录(二进制文件和配置文件)之外的目录中的文件添加独立于目录的完成访问权限很容易。

_vi () 
{
    local word=${COMP_WORDS[COMP_CWORD]};
    local bin_dir="~/bin/"
    local dot_dir="~/dotfiles/"

    COMPREPLY=($(compgen -f -G "$bin_dir*" -- "$bin_dir${word}"));
    COMPREPLY+=($(compgen -f -G "$dot_dir*" -- "$dot_dir${word}"));
    return 0;
}

答案1

最简单的方法是避免$item在将路径添加到时剥离路径$COMPREPLY[$i]

_vi () 
{
    local word=${COMP_WORDS[COMP_CWORD]};
    local pat="~/bin/*"

    COMPREPLY=($(compgen -f -G "$pat" -- "~/bin/${word}"));
    return 0;
}

显示的可能列表没有路径组件,但成功完成后将插入路径。

另一种方法是使用 shell 脚本扩展vi自身,该脚本在当前目录中查找文件名,如果找不到,则检查~/bin/.但此时开始有意义的是,让编辑器相当于$CDPATH完成目录,而不是将代码限制为搜索~/bin/。

相关内容