
既存のツールにbashコンプリート機能を追加しています。
誰かが-s
フラグを渡した後、bashの完了に関連するいくつかのオプションを提供したいと思います。
Closed
Feedback
"In Progress"
New
Rejected
Resolved
内部空間が"In Progress"
問題を引き起こしました。
#!/usr/bin/env bash
_remote-redmine()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[$COMP_CWORD]}
case "${COMP_WORDS[($COMP_CWORD-1)]}" in
-s)
s_opts=( "New" "In Progress" "Resolved" "Feedback" "Closed" "Rejected" )
COMPREPLY=( $( compgen -W "${s_opts[*]}" -- "$cur") )
;;
esac
return 0
}
complete -F _remote-redmine remote-redmine
ツールを実行すると、次のような結果が得られます。
$ remote-redmine -s <tab><tab>
Closed Feedback In New Progress Rejected Resolved
しかし、私は以下を得たいと思います:
$ remote-redmine -s <tab><tab>
Closed Feedback "In Progress" New Rejected Resolved
または
$ remote-redmine -s <tab><tab>
Closed Feedback In\ Progress New Rejected Resolved
私が試したこと:
s_opts=( ... "In\ Progress" ... )
:違いなしs_opts( ... "In\\ Progress" ...)
:違いなしs_opts( ... "In\\\ Progress" ...)
:2つのオプションはIn\
次のとおりです。Progress
s_opts( ... "\"In Progress\"" ...)
:違いなしcompgen -o nospace ...
:違いなしcompgen -o noquote ...
:違いなし少なくとも1行を
compgen
入れることはできますが、In Progress
次のように翻訳されません。complete
$ compgen -W 'New "In Progress"' New In Progress
追加の引用符をエスケープすると役に立ちますが、
compgen
次のように変換されませんcomplete
。$ compgen -W 'New "\"In Progress\""' New "In Progress"
スペースを3回エスケープすると役に立ちますが、それでも次のように変換されるわけではありません
complete
。$ compgen -W 'New In\\\ Progress' New In\ Progress
私はスペースを7回逃げることが
complete
これらの問題のいくつかを解決できるので有望だと思いましたが、それも役に立ちません。$ compgen -W 'New In\\\\\\\ Progress' New In\\\ Progress ... $ remote-redmine -s <tab><tab> ... In\\\ New Progress ...
バイパスは
compgen
機能しますが、シングルタップの自動塗りつぶしとダブルタップのフィルタリングは失われます。COMPREPLY=( ... 'In\ Progress' ... ) COMPREPLY=( ,,, '"In Progress"' ... )
答え1
これはトークン化とIFSのデフォルトに関連していますが、これは驚くべきことではありません。
存在する
compgen -W "${s_opts[*]}"
配列拡張は、最初の文字を区切り文字として使用して、配列[*]
要素を単一の文字列に連結します。IFS
デフォルトでは空白なので、値の空白と区切り文字としての空白の区切りが失われます。幸いなことにcompgen -W
、引数は文字で区切られた値の文字列として解釈されるため、同様の値や値に表示されない他の値にのみ変更するとうまくIFS
機能します。[*]
IFS
:
それから
COMPREPLY=( $( compgen ...) )
compgen
printを使用して文字列を暗黙的に分割しIFS
(ワイルドカードを介して渡す)、compgen
特に改行で区切られた値を印刷するようです。分割してこれを行うには、改行を設定する必要がありますIFS
が、readarray
とにかく改行を使用し、ワイルドカードを使用しないため、実際に読み取るために使用することをお勧めします。
だから、あなたはこれを行うことができます
_remote-redmine() {
local cur
local IFS=:
COMPREPLY=()
cur=${COMP_WORDS[$COMP_CWORD]}
case "${COMP_WORDS[($COMP_CWORD-1)]}" in
-s)
s_opts=( "New" "In Progress" "Resolves" "Feedback" "Closed" "Rejected" )
readarray -t COMPREPLY < <( printf "%q\n" $(compgen -W "${s_opts[*]}" -- "$cur"))
;;
esac
return 0
}
あるいは、改行は両方の場所で有効であるため、以前IFS=$'\n'
と同じように出力を設定して分割できますが、関数期間中にワイルドカードを無効にする必要があります。これは、保存して復元する別のグローバル状態です。
答え2
これは私にとって効果的です。使用するcompgen
代わりに$cur
:
_remote-redmine()
{
local cur
local item
COMPREPLY=()
cur=${COMP_WORDS[$COMP_CWORD]}
case "${COMP_WORDS[($COMP_CWORD-1)]}" in
-s)
local s_opts=( "New" "In\ Progress" "Resolved" "Feedback" "Closed" "Rejected" )
for item in "${s_opts[@]}"; do
case "$item" in
( "$cur"* )
COMPREPLY+=( "$item" )
;;
esac
done
;;
esac
return 0
}
complete -F _remote-redmine remote-redmine
私が追加したバックスラッシュに注意してください"In\ Progress"
。これは文字通りプロジェクトの一部です。を入力しIn
てクリックすると、コマンドラインが入力されます。これで、エスケープ文字が二重引用符の外側にあるので有効になります。つまり、単語の分割を防ぎますTab。In\ Progress