コンマ区切り値のbash補完


16

コンマ区切りのパラメーターリストの完了規則を作成したいと思います。たとえば、サーバー名のリストを受け取るコマンドがあります:

myscript -s name1,name2,name3

この瞬間、私は次の完了を書くことができました:

_myscript () {
  local cur prev opts

  _get_comp_words_by_ref cur prev

  opts='-s'

  servers='name1 name2 name3'

  if [[ ${cur} == -* ]] ; then
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  else
    case "${prev}" in
      -s)
        if [[ "$cur" == *,* ]]; then
          local realcur prefix
          realcur=${cur##*,}
          prefix=${cur%,*}
          COMPREPLY=( $(compgen -W "${servers}" -P "${prefix}," -- ${realcur}) )
        else
          COMPREPLY=( $(compgen -W "${servers}" -- ${cur}) )
        fi
        ;;
      *)
        # do nothing
        ;;
    esac
  fi
}

ただし、少なくとも2つの問題があります。

  1. 現在の値の提案には、接頭辞に以前のすべての値が含まれます。
  2. 値の重複は考慮されません。

そのような場合のベストプラクティスは何ですか?たぶんbash-completionsにはcsv-list用のいくつかのバンドルされた関数がありますか?


3
役立つのは、コンマ区切りの値を次のような反復可能なリストに分割できることIFS=, LIST=("$VARIABLE")です。$ VARIABLEにはコンマ区切りの値が含まれます。
マイケルエーレンライヒ

2
@MichaelEhrenreichの素晴らしいアイデアですが、を引用して$VARIABLEはいけません。そうしないと、単語の区切りが発生しません。使用するだけIFS=, LIST=($VARIABLE)です。
グス14年

回答:


6

bashはCOMPREPLYディスプレイの値を直接使用し、ユーザーのテキストを置き換えるため、説明する問題を修正する方法は基本的にありません-必要なものを取得するために、可能な補完を最初に生成する必要があります(追加のサーバー名、プレフィックスなし)bashを表示するため、bashがユーザーテキストを最長の競合しない文字列に置き換えようとしている場合、スクリプトを再度呼び出してプレフィックス付きのテキストを生成する必要があります-およびbashそのための機能はありません。

私が思いつく最善の方法COMPREPLYは、プレフィックス全体(COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) ))を持つ最初の単語のみで生成されるようにすることです。これにより、可能な補完が1つしかない場合は自動的に正しく完了し、補完が複数ある場合は自動的に完了します、bashはこれまでに入力されたものを削除しません(最初の単語にCOMPREPLYは接頭辞全体があり、したがって現在入力されたテキストと一致し、bashによって選択されてユーザーのテキストを置き換えるため)、接頭辞なしのオプションを表示します-既にプレフィックスが含まれている1つの単語の場合、出力は次のようになります。

$ command -s banana,a
ananas     apricot    banana,apple

補完オプションの最後にソートされた「apple」は、「b」で始まるプレフィックスを持っているため、非常に混乱します。だから、そうすることはお勧めしません。

重複について-重複を表示しないためには、$prefixその部分に侵入し(簡単IFS="," prefix_parts=($prefix):)、それらを繰り返して$servers、まだリストされていない名前のみを残す必要があります。入力するのは退屈なので、ここでは表示しませんが、比較的簡単なので、管理できると確信しています:-)。

要約すると、少なくともbashが補完に役立つと予想される場合は、入力オプションにコンマ区切り値を使用する必要はないと思います。

次のようなオプション形式をサポートできます:command -s <server> [<server> [..]]そして、-sオプションの直後のエントリ以外のエントリを完了するには、オプション(に一致する文字列)が見つかるまで$COMP_WORDSから配列をスキャンバックし$COMP_CWORDます。-*サーバー名の補完を行う必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.