Kode berikut, diadaptasi dari jawaban Stack Overflow ini dan utas diskusi Forum Ubuntu ini akan menambah penyelesaian untuk semua alias yang Anda tentukan:
# Automatically add completion for all aliases to commands having completion functions
function alias_completion {
local namespace="alias_completion"
# parse function based completion definitions, where capture group 2 => function and 3 => trigger
local compl_regex='complete( +[^ ]+)* -F ([^ ]+) ("[^"]+"|[^ ]+)'
# parse alias definitions, where capture group 1 => trigger, 2 => command, 3 => command arguments
local alias_regex="alias ([^=]+)='(\"[^\"]+\"|[^ ]+)(( +[^ ]+)*)'"
# create array of function completion triggers, keeping multi-word triggers together
eval "local completions=($(complete -p | sed -Ene "/$compl_regex/s//'\3'/p"))"
(( ${#completions[@]} == 0 )) && return 0
# create temporary file for wrapper functions and completions
rm -f "/tmp/${namespace}-*.tmp" # preliminary cleanup
local tmp_file; tmp_file="$(mktemp "/tmp/${namespace}-${RANDOM}XXX.tmp")" || return 1
local completion_loader; completion_loader="$(complete -p -D 2>/dev/null | sed -Ene 's/.* -F ([^ ]*).*/\1/p')"
# read in "<alias> '<aliased command>' '<command args>'" lines from defined aliases
local line; while read line; do
eval "local alias_tokens; alias_tokens=($line)" 2>/dev/null || continue # some alias arg patterns cause an eval parse error
local alias_name="${alias_tokens[0]}" alias_cmd="${alias_tokens[1]}" alias_args="${alias_tokens[2]# }"
# skip aliases to pipes, boolean control structures and other command lists
# (leveraging that eval errs out if $alias_args contains unquoted shell metacharacters)
eval "local alias_arg_words; alias_arg_words=($alias_args)" 2>/dev/null || continue
# avoid expanding wildcards
read -a alias_arg_words <<< "$alias_args"
# skip alias if there is no completion function triggered by the aliased command
if [[ ! " ${completions[*]} " =~ " $alias_cmd " ]]; then
if [[ -n "$completion_loader" ]]; then
# force loading of completions for the aliased command
eval "$completion_loader $alias_cmd"
# 124 means completion loader was successful
[[ $? -eq 124 ]] || continue
completions+=($alias_cmd)
else
continue
fi
fi
local new_completion="$(complete -p "$alias_cmd")"
# create a wrapper inserting the alias arguments if any
if [[ -n $alias_args ]]; then
local compl_func="${new_completion/#* -F /}"; compl_func="${compl_func%% *}"
# avoid recursive call loops by ignoring our own functions
if [[ "${compl_func#_$namespace::}" == $compl_func ]]; then
local compl_wrapper="_${namespace}::${alias_name}"
echo "function $compl_wrapper {
(( COMP_CWORD += ${#alias_arg_words[@]} ))
COMP_WORDS=($alias_cmd $alias_args \${COMP_WORDS[@]:1})
(( COMP_POINT -= \${#COMP_LINE} ))
COMP_LINE=\${COMP_LINE/$alias_name/$alias_cmd $alias_args}
(( COMP_POINT += \${#COMP_LINE} ))
$compl_func
}" >> "$tmp_file"
new_completion="${new_completion/ -F $compl_func / -F $compl_wrapper }"
fi
fi
# replace completion trigger by alias
new_completion="${new_completion% *} $alias_name"
echo "$new_completion" >> "$tmp_file"
done < <(alias -p | sed -Ene "s/$alias_regex/\1 '\2' '\3'/p")
source "$tmp_file" && rm -f "$tmp_file"
}; alias_completion
Untuk alias sederhana (hanya perintah, tanpa argumen), ia akan menetapkan fungsi penyelesaian asli ke alias; untuk alias dengan argumen, itu menciptakan fungsi wrapper yang menyisipkan argumen tambahan ke fungsi penyelesaian asli.
Tidak seperti skrip tempat ia berevolusi, fungsinya menghormati tanda kutip untuk perintah alias dan argumennya (tetapi yang pertama harus dicocokkan dengan perintah penyelesaian, dan tidak dapat disarangkan), dan ia harus dapat dengan baik menyaring alias ke daftar perintah dan pipa (yang dilewati, karena tidak mungkin untuk menemukan apa yang harus diselesaikan di dalamnya tanpa membuat ulang logika parsing baris perintah shell lengkap).
Pemakaian
Simpan kode sebagai file skrip shell dan sumber yang ada di, atau salin fungsi grosir ke, .bashrc
(atau file dot terkait Anda ). Yang penting adalah memanggil fungsi setelah selesai bash dan alias definisi telah diatur (kode di atas memanggil fungsi tepat setelah definisinya, dalam semangat "sumber dan lupa", tetapi Anda dapat memindahkan panggilan ke mana saja di hilir jika itu lebih cocok untukmu). Jika Anda tidak ingin fungsi di lingkungan Anda setelah keluar, Anda dapat menambahkan unset -f alias_completion
setelah memanggilnya.
Catatan
Jika Anda menggunakan bash
4.1 atau lebih dan menggunakan penyelesaian yang dimuat secara dinamis, skrip akan mencoba memuat penyelesaian untuk semua perintah alias Anda sehingga dapat membangun fungsi pembungkus untuk alias Anda.
bash --version
untuk mendapatkan ini (jangan gunakan-v
, output berbeda).