このオプションは、bashでシェル補完を作成するときに-C
非常に強力で一般的に見えます。これは次のように定義されます。
-氏 注文する
注文する サブシェル環境で実行すると、その出力は可能な完成として使用されます。
これは本当に簡単だと思います。しかし、奇妙なことではありません。私がするなら:
$ complete -C "echo one two three" test.sh
その後、[tab]を一度入力しtest.sh
てクリックすると、行が埋められます。
$ test.sh one two three test.sh test.sh
退いてください。何? !比較しようと、
$ complete -W "one two three" test.sh
私が期待していたものとまったく一致しています。一つ、サムまたは二つできるだけ書いてください(もちろん並べ替えられた順序で)。
どこでも良い文書が見つからないので試してみてください。セミコロンが役に立ちますか?complete -C "echo one two three;" test.sh
...ああ、わかりました、役に立ちました。一部test.sh
、最後の奇妙な部分を削除するためです。しかし、まだ完全な文字列を埋めますone two three
。上記の説明が「可能な完成」、複数形で間違いなく出ているので、これは奇妙です。 ...では、まあ、ああ、改行文字は?やってみようcomplete -C "echo -e 'one\ntwo\nthree';" test.sh
。
そうですね、希望はあります。これを入力するとtest.sh [tab]
戻ってきますone three two
。しかし、状況が間違っています。o
あいまいさを解決するために1つを追加するのでtest.sh o[tab]
、それ返品
o one three two
これは謎です。実際、私が入力したすべての文字列がリストに追加されます。これにより応答がtest.sh wtf[tab]
届きます。one three two wtf
何か複雑なことをしなければならないようだと思ったがcompgen
、やはり予想通りだ-W
。そして事実
$ complete -W '$(echo one two three)' test.sh
echo
うまくいきます(変更可能な結果を生成できるよりも複雑な作業を行う場合は、早期の拡張/実行を防ぐために単一引用符に注意してください)。
私がここで何を見逃しているのでしょうか?
答え1
このコマンドの役割は、-C
完了要求に応答して挿入するテキストを決定することです。インターフェイスが少し奇妙です。
引数は
-C
bash スクリプトの断片として解釈されます。 Bashは、このコードスニペットに正しく引用された3つの文字列を追加します。- 引数が完了するコマンドです。
- カーソルが位置する単語のプレフィックス(カーソルまで)。
- カーソルの前の単語です。
一部の変数が環境に追加されます。
COMP_LINE
実行が完了した行全体を含みます。COMP_POINT
これにはカーソル位置COMP_LINE
(0から計算)が含まれます。COMP_TYPE
正常完成は9番、曖昧な完成の代替リストは33番、メニュー完成は37番、曖昧な完成間の切り替えは63番、部分完了後、リスト完了は64番だ。COMP_KEY
完了をトリガーしたキーが含まれます(たとえば、ユーザーが押された場合はtab Tab)。
- コマンドの出力は、現在の単語を置き換えるテキストとして解釈されます。これは追加されたサフィックスではなく代替サフィックスです。コマンドは、指定されたプレフィックスに基づいてフィルタリングする必要があります。これには複数の行を含めることができます。この場合、各行は可能な代替行と見なされます。
これは提供されたメカニズムとほぼ同じですが、より良いです。録音された、がある関数の場合-F
。関数のインターフェースがよりきれいになりました。現在のコマンドの単語リストを読むことができます。COMP_WORDS
変数と現在の単語の開始位置COMP_CWORD
;彼らは結果を次のように書く。COMPREPLY
大量に。
便利な引数(特に完成するプレフィックス)がコマンドの最後に渡されるため、これは-C
ほとんど外部コマンドでのみ使用できます。もちろん同様のものを使用することもできますが、sh -c …
きれいではありません。
complete -C 'sh -c '\'for x in one two three; do case $x in "$1"*) echo "$x";; esac''\'
答え2
complete
面倒な外部スクリプトや関数なしで定義内で補完機能を維持したい場合は、complete -C
このオプションを使用する最も簡単な方法は、コマンド文字列内でハンドラ関数を定義することです。組み込みcomplete
関数は、次のようにコマンド文字列を実行した直後に3つの文字列を追加します。@Gilles「だから邪悪な行動はやめなさい」彼の答えで、彼はこう言いました。
- 引数が完了するコマンドです。
- カーソルが位置する単語のプレフィックス(カーソルまで)。
- カーソルの前の単語です。
元の質問のサンプルコードでは、可能な補完をプレフィックスとして$2
含めるには位置引数のみが必要です。行く方法は次のとおりです。grep
$2
complete -C 'makelist() { echo one; echo two; echo three; }; filter() { makelist | grep "^$2" | sort -u; }; filter' test.sh
test.sh t<tab>
と入力すると、complete
スペースを含むコマンド文字列が最後の文字列に「test.sh」、「t」、および「test.sh」が追加されて実行されますfilter
。このコマンドは次のことを行います。
makelist
機能定義filter
機能定義filter
追加の文字列を引数として使用して関数を呼び出すfilter
通知されますmakelist
makelist
可能なすべての完了リストを返します。grep
カーソルの下の単語の接頭辞をカーソルまで一致させて完成- 珍しい点は
sort
これです。 - また返す
complete