Ant*_*nko 18 bash autocomplete
我希望能够掌握给定部分命令的一系列可能的补全。例如,partial 命令service um有以下可能的补全:
$ service um<TAB><TAB>
umountfs umountnfs.sh umountroot
Run Code Online (Sandbox Code Playgroud)
我想要一个completions具有以下行为的函数:
$ for x in $(completions 'service um'); do
> echo $x
> done
umountfs
umountnfs.sh
umountroot
Run Code Online (Sandbox Code Playgroud)
这是我认为可以成为完整答案的方法。我绝对希望看到完整的答案,但鉴于相对简单<TAB><TAB>以非编程方式提供相同的功能,感觉也可能有更灵活的解决方案。
我可以发现service命令的完成机制是_service函数:
$ complete -p service
complete -F _service service
Run Code Online (Sandbox Code Playgroud)
当这个完成函数_service被调用时,一堆环境变量被设置(即COMP_{LINE,POINT,KEY,TYPE,WORDS,CWORD};参见bash 手册页),该函数作为参数给出正在完成的命令、正在完成的单词和前一个单词,并填充COMPREPLY可能的完成. 所以我想要的completions函数可以这样定义:
function completions() {
# Produce an array of tokens in the input.
read -a words <<< $1
# Use "complete -p ${words[0]}" to determine how the
# completions are computed. This could be complicated
# if complete is given flags other than -F.
completion_func=???
# Set all those COMP_* environment variables appropriately.
# Run the function to populate COMPREPLY. This version
# assumes words has length at least 2, but that can be
# fixed.
$completion_func ${words[0]} ${words[-1]} ${words[-2]}
echo ${COMPREPLY[@]}
}
Run Code Online (Sandbox Code Playgroud)
除了相对复杂度之外<TAB><TAB>,这种方法的一个缺点是它改变了环境。
这是我认为可以作为起点的基本功能。它可能会以多种方式失败,希望这里的其他人可以改进:
completions () (
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
IFS="$COMP_WORDBREAKS" read -a words <<<"$1"
complete_setting=($(complete -p "${words[0]}"))
complete_optstring=":abcdefgjksuvprDEo:A:G:W:F:C:X:P:S:"
while getopts "$complete_optstring" option "${complete_setting[@]:1}"
do
case $option in
F) complete_functon="$OPTARG"
;;
*) # Run around screaming!
;;
esac
done
COMP_WORDS=("${words[@]}")
COMP_LINE="$1"
COMP_POINT="${#COMP_LINE}"
COMP_CWORD=$((${#COMP_WORDS[@]} - 1))
"$complete_functon"
printf "%s\n" "${COMPREPLY[@]}"
)
Run Code Online (Sandbox Code Playgroud)
笔记:
complete查找使用 拆分的单词COMP_WORDBREAKS,因此我们将IFS其设置为read。complete -p 以可重用的方式打印出当前的完成设置,因此我们可以按照它的方式解析选项。()而不是{}),因此不应干扰您当前的环境。