作為開發者,在開發的時候一定常常會使用很多第三方的工具,但有些工具並非使用系統套件管理安裝的,所以就不會有自動補齊(例如 Laravel 核心的 artisan)。
雖然新版已經有內建產生自動補齊手稿(已知 8 版開始有多了一個 artisan completion),可是之前嘗試過都失敗了。而這次則是在研究 kind 的時候發現它也有自動補齊功能,又開始研究要怎麼弄(不然 Kubernetes 東西已經夠複雜了,實在記不起來)。沒想到居然成功了!所以寫一篇文章記錄一下到底要怎麼弄。
教學
TL;DR
確認以下資料夾存在,沒有的話可自己 mkdir 一下:
|  | ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions
 | 
通常會是 ~/.local/share/bash-completion/completions。
接著把要安裝的自動補齊手稿存在這資料夾底下,並命名成和執行檔名稱相同。以 kind 作為範例:
|  | kind completion bash > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/kind
 | 
之後再使用 exec bash 就可以看到生效了:
|  | hms5232@hhming-moe:~$ exec bashhms5232@hhming-moe:~$ kind
 build       completion  create      delete      export      get         help        load        version
 hms5232@hhming-moe:~$ kind
 
 | 
原理說明
記得剛剛在前面有看到一串很怪異的路徑嗎?是從 __load_completion 來的,可以用 type __load_completion 看一下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 
 | hms5232@hhming-moe:~$ type __load_completion__load_completion 是一個函數
 __load_completion ()
 {
 local -a dirs=(${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions);
 local ifs=$IFS IFS=: dir cmd="${1##*/}" compfile;
 [[ -n $cmd ]] || return 1;
 for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share};
 do
 dirs+=($dir/bash-completion/completions);
 done;
 IFS=$ifs;
 if [[ $BASH_SOURCE == */* ]]; then
 dirs+=("${BASH_SOURCE%/*}/completions");
 else
 dirs+=(./completions);
 fi;
 local backslash=;
 if [[ $cmd == \\* ]]; then
 cmd="${cmd:1}";
 $(complete -p "$cmd" 2>/dev/null || echo false) "\\$cmd" && return 0;
 backslash=\\;
 fi;
 for dir in "${dirs[@]}";
 do
 [[ -d $dir ]] || continue;
 for compfile in "$cmd" "$cmd.bash" "_$cmd";
 do
 compfile="$dir/$compfile";
 if [[ -f $compfile ]] && . "$compfile" &> /dev/null; then
 [[ -n $backslash ]] && $(complete -p "$cmd") "\\$cmd";
 return 0;
 fi;
 done;
 done;
 [[ -v _xspecs[$cmd] ]] && complete -F _filedir_xspec "$cmd" "$backslash$cmd" && return 0;
 return 1
 }
 
 | 
細節是什麼不太重要,除非你要自己寫一個自動補齊的手稿。可以注意一下第 5 行,就是這個路徑的出處。
而各個指令的自動補齊 script 在寫什麼,有興趣的可以自己去查一下那些內容所代表的涵義(會需要對應的 shell 編寫基礎)。
而最後的 exec 在這邊是使用新的行程(process)取代舊的,達到不需要關閉 terminal 就可以生效的效果。
動手做
kind
kind 的部分就是上面所提及的那樣,真的就是這麼簡單。
Laravel artisan
那麼接著就來試試 artisan 吧!

確認有 completion 指令
接著:
|  | php artisan completion > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/artisan
 | 
tada!
|  | hms5232@hhming-moe:~/project/laravel$ ./artisan make:cast          command       controller    exception     job           mail          migration     notification  policy        request       rule          test
 channel       component     event         factory       listener      middleware    model         observer      provider      resource      seeder
 hms5232@hhming-moe:~/project/laravel$ ./artisan make:
 
 | 
可惜需要直接用 ./artisan。如果要能使用 php artisan 的方式網路上有 bash-completion、/etc/bash_completion.d/ 或是其他人自己撰寫的 script 可用。
composer
很常用到的 PHP 好朋友 composer 也可以比照辦理:
|  | composer completion > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/composer
 | 

kubectl
雖然本文是講 Ubuntu,但基本上應該都能通,所以特地拿了手邊的樹梅派(OS 是 Raspberry Pi OS 64 bit)來測試 kubectl 的部分:
|  | kubectl completion bash > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/kubectl
 | 

kubectl on RPi4
看來也是能動呢。
參考資料