Bash

bash 中任何目錄的 ~/bin/* 文件名的命令參數完成

  • September 10, 2015

一個基本的 bash 功能是完成儲存在各種 bin 目錄中的命令,而不管目前工作目錄如何。這允許使用者保持命令和二進製文件的組織,而不需要他們從需要執行的任何目錄中指定完整路徑。

在我執行這些 bin 文件之前,bash 究竟是如何提供這個命令完成的,我認為,從設計的角度來看,在我編輯它們之前期望相同的命令完成是有意義的。

在我的特殊情況下,這意味著修改我的編輯器的完成功能vi,因此它不僅包括來自我目前工作目錄的文件名,還包括來自我的文件名~/bin/(我實際上並不關心從其他 bin 添加命令)。

對此SO答案的簡單修改可以做到這一點:

$ 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;
}

最簡單的方法是避免將路徑從$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/開始變得有意義。

引用自:https://unix.stackexchange.com/questions/228672