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
/。