
COMPREPLYはデフォルトでスペースで区切られた単語のリストを返しますが、1行に1つの単語を返したいと思います。単語の末尾に改行を追加しようとし、compgenとCompleteのドキュメントを見てみましたが、何も見つかりませんでした。
可能ですか?
編集する:
申し訳ありませんが、私は説明を本当に不都合にしました。 Complete -Fを介してオートコンプリート機能にバインドするスクリプトがあります。ユーザーがスクリプトを実行しているときに Tab キーを 2 回押すと、compgen で可能なオプションのリストが表示されます。これで、関数には次のコード行があります。
COMPREPLY=( $(compgen -W '$( ls ~/work/dev/jobs/ | cat )' -- $curword ) )
ユーザーがタブをクリックすると、これらのディレクトリが次のように表示されます。
directory0 directory1 directory2 directory3
しかし、私は彼らが次のように現れることを望みます。
directory0
directory1
directory2
directory3
/r/bashに同様の投稿を投稿しましたが、誰かがこれを提案しました。
bind 'set completion-display-width 0'
これが完了するとキャンセルできます。
bind 'set completion-display-width -1'
今の問題は、関数全体が返される前に設定を解除すると効果がないため、ユーザーがEnterキーを押した後にスクリプトから設定を解除することです。これはうまく機能しますが、ユーザーがオートコンプリートを使用し始めた後、心を変えて入力した内容を削除してシェルに戻ると、完成表示幅はまだゼロに設定されます。
この問題を解決する他の方法はありますか?
答え1
completion-display-width
私はreadline変数の変更を提案した人でした。/r/配布ただし、この1つの完成関数でのみ機能することを指定していません。
TABいずれにせよ、完了関数で(COMP_TYPE == 9)または(COMP_TYPE == 63)によってトリガーされているかどうかを検出できますTABTAB。端末。これは私が考えることができる最もハッキーなことです。次のようになります。
_foo_complete() {
local i file files
files=( ~/work/dev/jobs/"$2"* )
[[ -e ${files[0]} || -L ${files[0]} ]] || return 0
if (( COMP_TYPE == 63 )); then
for file in "${files[@]}"; do
printf -v 'COMPREPLY[i++]' '%*s' "-$COLUMNS" "${file##*/}"
done
else
COMPREPLY=( "${files[@]##*/}" )
fi
}
complete -F _foo_complete foo
しかし、あなたは本物してはいけないls 出力の解析。
答え2
特定の完成関数に対してのみreadline変数を変更したい場合は、関数の実行中にreadline変数を設定してから$PROMPT_COMMAND
再度変更できます。
_foo_complete() {
# retrieve the original value
local width=$(bind -v | sed -n 's/^set completion-display-width //p')
if [[ $width -ne 0 ]]; then
# change the readline variable
bind "set completion-display-width 0"
# set up PROMPT_COMMAND to reset itself to its current value
PROMPT_COMMAND="PROMPT_COMMAND=$(printf %q "$PROMPT_COMMAND")"
# set up PROMPT_COMMAND to reset the readline variable
PROMPT_COMMAND+="; bind 'set completion-display-width $width'"
fi
# whatever the function normally does follows
COMPREPLY=(aa bb)
}
complete -F _foo_complete foo