如何在 Bash 安裝新的自動補齊手稿

作為開發者,在開發的時候一定常常會使用很多第三方的工具,但有些工具並非使用系統套件管理安裝的,所以就不會有自動補齊(例如 Laravel 核心的 artisan)。

雖然新版已經有內建產生自動補齊手稿(已知 8 版開始有多了一個 artisan completion),可是之前嘗試過都失敗了。而這次則是在研究 kind 的時候發現它也有自動補齊功能,又開始研究要怎麼弄(不然 Kubernetes 東西已經夠複雜了,實在記不起來)。沒想到居然成功了!所以寫一篇文章記錄一下到底要怎麼弄。

教學

TL;DR

確認以下資料夾存在,沒有的話可自己 mkdir 一下:

1
${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions

通常會是 ~/.local/share/bash-completion/completions

接著把要安裝的自動補齊手稿存在這資料夾底下,並命名成和執行檔名稱相同。以 kind 作為範例:

1
kind completion bash > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/kind

之後再使用 exec bash 就可以看到生效了:

1
2
3
4
hms5232@hhming-moe:~$ exec bash
hms5232@hhming-moe:~$ kind
build completion create delete export get help load version
hms5232@hhming-moe:~$ kind

原理說明

記得剛剛在前面有看到一串很怪異的路徑嗎?是從 __load_completion 來的,可以用 type __load_completion 看一下:

1
2
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 指令

接著:

1
php artisan completion > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/artisan

tada!

1
2
3
4
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 也可以比照辦理:

1
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 的部分:

1
kubectl completion bash > ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions/kubectl

kubectl on RPi4

看來也是能動呢。

參考資料