Đoạn mã sau, được điều chỉnh từ câu trả lời Stack Overflow này và chuỗi thảo luận về Diễn đàn Ubuntu này sẽ thêm các phần hoàn chỉnh cho tất cả các bí danh đã xác định của bạn:
# 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
Đối với các bí danh đơn giản (chỉ lệnh, không có đối số), nó sẽ gán hàm hoàn thành ban đầu cho bí danh; đối với các bí danh có đối số, nó tạo ra một hàm bao bọc để chèn các đối số phụ vào hàm hoàn thành ban đầu.
Không giống như các tập lệnh mà nó đã phát triển từ, hàm này tôn trọng cả trích dẫn cho lệnh bí danh và các đối số của nó (nhưng trước đây phải được khớp với lệnh hoàn thành và không thể lồng nhau), và nó đáng tin cậy nên lọc ra các bí danh cho danh sách lệnh và các đường ống (được bỏ qua, vì không thể tìm ra những gì cần hoàn thành trong chúng mà không tạo lại logic phân tích cú pháp dòng lệnh shell hoàn chỉnh).
Sử dụng
Lưu mã dưới dạng tệp tập lệnh shell và nguồn trong hoặc sao chép hàm bán buôn vào, .bashrc
(hoặc tệp dấu chấm thích hợp của bạn ). Điều quan trọng là gọi hàm sau khi cả hai hoàn thành bash và các định nghĩa bí danh đã được thiết lập (đoạn mã trên gọi hàm ngay sau định nghĩa của nó, trong một nguồn trên mạng và quên tinh thần, nhưng bạn có thể di chuyển cuộc gọi xuống bất cứ nơi nào nếu điều đó phù hợp với bạn hơn). Nếu bạn không muốn chức năng trong môi trường của mình sau khi nó thoát, bạn có thể thêm unset -f alias_completion
sau khi gọi nó.
Ghi chú
Nếu bạn đang sử dụng bash
4.1 trở lên và sử dụng các hoàn thành được tải động, tập lệnh sẽ cố gắng tải các hoàn thành cho tất cả các lệnh bí danh của bạn để nó có thể xây dựng các hàm bao cho các bí danh của bạn.
bash --version
để có được điều này (không sử dụng-v
, đầu ra khác nhau).