与えられた部分命令に対して可能な完了範囲を得ることができるようにしたい。たとえば、一部のコマンドでは、service um
次のような完成が可能です。
$ service um<TAB><TAB>
umountfs umountnfs.sh umountroot
completions
次の動作を持つ関数が必要です。
$ for x in $(completions 'service um'); do
> echo $x
> done
umountfs
umountnfs.sh
umountroot
進捗状況の一部:これまでに学んだこと
私はこれが完全な答えになることができる1つのアプローチだと思います。私は間違いなく完全な答えを見たいのですが、<TAB><TAB>
プログラムではなく同じ機能を提供する比較的簡単なアプローチを考えると、より柔軟な解決策があるかもしれません。
service
このコマンドの完了メカニズムは_service
次の関数であることがわかります。
$ complete -p service
complete -F _service service
このコンプリート関数が呼び出されると、_service
複数の環境変数が設定されます(例COMP_{LINE,POINT,KEY,TYPE,WORDS,CWORD}
:;を参照)。バッシュのマニュアルページ)、この関数は完成したコマンド、完成した単語、前の単語を引数として取り、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[@]}
}
相対的な複雑さに加えて、<TAB><TAB>
このアプローチの欠点は環境を変えることです。
ベストアンサー1
ここに出発点として使用できると考えられる基本機能があります。さまざまな方法で失敗する可能性があります。ここで他の誰かがこれを改善できることを願っています。
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[@]}"
)
メモ:
- 対話型シェルで関数として使用する場合、初期ソースは必要ありません。
complete
検索語 Split を使用するので for に設定しましたCOMP_WORDBREAKS
。IFS
read
complete -p
再利用可能な方法で現在の完了設定を印刷すると、元の方法でオプションを解析できます。()
この関数は(代わりに)サブシェルを使用するため、{}
現在の環境が邪魔にならないようにしてください。