15

3 つの部分からなる形式で引数を取るコマンド ライン ツールがあります。

$ t first_second_third

の有効な値のfirstセット、 の有効な値secondのセット、および の有効な値のセットがありますthird。次の例のように、Bash の完全な機能を使用して、オプション値の各部分を完成させたいと考えています。

$ t [tab][tab]           # shows options for first part
walk run skip bike
$ t w[tab]               # completes first part and appends delimiter
$ t walk_[tab][tab]      # shows options for second part
home work park
$ t walk_h[tab]          # completes second part and appends delimiter
$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_a[tab]     # completes second part and appends space
$ t walk_home_afternoon

私はこのコードを持っています:

_tool () {
  local cur="${COMP_WORDS[COMP_CWORD]}"

  local first="walk run skip bike"
  local second="home work park"
  local third="morning afternoon evening"

  case "${cur}" in
    *_*_*)
      COMPREPLY=( $(compgen -W "${third}" -- "") ); return 0;;
    *_*)
      COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
    *)
      COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
  esac
}

complete -F _tool t

最初の節はうまく機能します。特別なことは何もありません。しかし、2 番目の句にはオプションや補完がありません。

$ t [tab][tab]
bike_  run_   skip_  walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells

2 番目の句を次のように置き換えました (つまり${cur}、呼び出しで空の文字列に置き換えましたCOMPREPLY)。

COMPREPLY=( $(compgen -W "${second}" -S "_" -- "") ); compopt -o nospace; return 0;;

コマンドラインですべてのオプションのリストを取得しますが、補完はありません。

$ t bike_[tab][tab]
home_  park_  work_
$ t bike_h[tab][tab]
home_  park_  work_
$ t bike_ho[tab][tab]
home_  park_  work_

${cur}単語リストとの相互作用が悪いのではないかと考えたCOMPREPLYので、2 番目の句を再度変更し、現在の単語の最初の部分に一致する接頭辞を追加しました。

local prefix=( $(expr "${cur}" : '\(.*_\)') )
COMPREPLY=( $(compgen -W "${second}" -P "${prefix}" -S "_" -- "") ); compopt -o nospace; return 0;;

これはあまり役に立ちませんでした。コマンドが${cur}まだ残っているCOMPREPLYので、オプションも補完もありません。代わりに空の文字列を使用すると、(現在の部分だけでなく) 完全なオプションが得られます。ただし、タブを押すと、入力した内容が消去されます。

$ t bike_[tab][tab]
bike_home_  bike_park_  bike_work_
$ t bike_ho[tab]
$ t bike_ # "ho" was erased

もちろん、第3部でも同じ問題があります。

  1. Bashに現在の単語を部分的に完成させるにはどうすればよいですか?
  2. オプションが選択されるまでBashに区切り文字を追加させないようにするにはどうすればよいですか?

これは別の Bash complete questionに似ていますが、値のすべての可能な順列をリストしたくなく、ファイル名としてフォーマットされていません (ファイル名のパターンが違いを生むかどうかはわかりません)。

助けてくれてありがとう!
--ap

4

1 に答える 1

5

ご希望のものが作成できました。以下の私のコードを参照してください:

_tool () {
  local cur="${COMP_WORDS[COMP_CWORD]}"

  local first="walk run skip bike"

  case "${cur}" in
    *_*_*)
      local firstsecond=`echo ${cur} | awk -F '_' '{print $1"_"$2}'`
      local third="${firstsecond}_morning ${firstsecond}_afternoon ${firstsecond}_evening"
      COMPREPLY=( $(compgen -W "${third}" -- ${cur}) ); return 0;;
    *_*)
      local firstcomp=`echo ${cur} | awk -F '_' '{print $1}'`
      local second="${firstcomp}_home ${firstcomp}_work ${firstcomp}_park"
      COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
    *)
      COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
  esac
}

complete -F _tool t

私はオートコンプリートにあまり詳しくなく、初めて使用しcompgenたり、completeということで、理論についてのご質問にお答えできるかどうかわかりません。この文書化が不十分な関数がどのように機能するかを理解するのに役立つ場合は、私が何をしたかをお伝えできます。まず、あなたが何を持っているかを理解しようとしました。問題を再現しました。次に、すべての順列を自分でコードにリストしたくない場合でも、ローカル変数を使用して、順列があるかのように模倣できるという考えを思いつきました。私が最初にしたことは、最初のアンダースコアを取得した後に「最初の」要素を取得し、それに 2 番目の要素を追加して、それを compgen にフィードすることでした。驚いたことに、うまくいきました。それから、第 3 レベルでも同じことをしようとしましたが、問題が発生しました。2 番目の部分が思ったほどうまく機能していないことがわかりました。最初の単語を完成させた後、2 番目の単語の提案を受け取ります。

$ t [tab][tab]           # shows options for first part
bike_ run_ skip_ walk_
$ t w[tab]               # completes first part and appends delimiter
$ t walk_[tab][tab]      # shows options for second part
walk_home_ walk_park_ walk_work_
$ t walk_h[tab]          # completes second part and appends delimiter
$ t walk_home_[tab][tab] # screws up with it
$ t walkhome_            

アンダースコアを awk に移動しようとしましたが、成功しませんでした:

      local first=`echo ${cur} | awk -F '_' '{print $1"_"}'`
      local second="${first}home ${first}work ${first}park"

何らかの理由で、変数名を「最初」とは異なる名前に変更する必要があり、機能し始めました。次に、3番目の要素で、最後に説明したのと同じ問題が発生しました.3番目の要素に入力したものはすべて消えますが、[タブ] [タブ]はオプションを提供します:

$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_aft[tab]     # erases what I typed
$ t walk_home_

${cur}3番目の単語でcompgenに追加したところ、うまくいきました。これは私がやったことの要約にすぎません...しかし、私は動作するバージョンを手に入れたので、それに満足しています. :-)

于 2013-05-04T02:45:41.357 に答える