16

bash のオートコンプリートを Cisco IOS シェルのように見せることはできますか?

次のように、各補完に短い説明を追加することを意味します。

telnet 10.10.10. (TAB Pressed)
 10.10.10.10 - routerA
 10.10.10.11 - routerB

ここで、10.10.10.10 と 10.10.10.11 は可能な補完であり、routerA と routerB は単なる説明です (実行されません)。

bash が「complete -W」でコマンドを完了できることは知っていますが、コマンドの説明を出力できますか?

4

5 に答える 5

14

TABを2回以上押したり、追加情報をエコーし​​たりする必要がない、これに対する解決策があります。重要なのは、補完が1つしかないかどうかを確認してから、その補完を有効な部分まで削除することです。通常は、「コメント」区切り文字の後に一致する最大の接尾辞を削除します。OPの例を実行するには:

_telnet() {
  COMPREPLY=()
  local cur
  cur=$(_get_cword)
  local completions="10.10.10.10 - routerA
10.10.10.11 - routerB
10.20.1.3 - routerC"

  local OLDIFS="$IFS"
  local IFS=$'\n'
  COMPREPLY=( $( compgen -W "$completions" -- "$cur" ) )
  IFS="$OLDIFS"
  if [[ ${#COMPREPLY[*]} -eq 1 ]]; then #Only one completion
    COMPREPLY=( ${COMPREPLY[0]%% - *} ) #Remove ' - ' and everything after
  fi
  return 0
}
complete -F _telnet -A hostnames telnet

これにより、探している正確な出力が得られます。可能な完了が1つしかない場合は、完了する前にコメントが削除されます。

于 2012-04-12T19:00:09.830 に答える
3

単純なケースでは (@bonsaiviking で示されているように) 候補の数が 1 つになるかどうかに基づいて変換を使用し、ユーザーに表示する内容にさらに柔軟性が必要な場合は次のようにします。

__foo () {
    local WORDS
    WORDS=("1|10.10.10.10|routerA" "2|10.10.10.11|routerB")

    local FOR_DISPLAY=1
    if [ "${__FOO_PREV_LINE:-}" != "$COMP_LINE" ] ||
            [ "${__FOO_PREV_POINT:-}" != "$COMP_POINT" ]; then
        __FOO_PREV_LINE=$COMP_LINE
        __FOO_PREV_POINT=$COMP_POINT
        FOR_DISPLAY=
    fi

    local IFS=$'\n'
    COMPREPLY=($(
        for WORD in "${WORDS[@]}"; do
            IFS=\| read -ra SP <<<"$WORD"
            if [ "${SP[1]:0:${#2}}" == "$2" ]; then
                if [ -n "$FOR_DISPLAY" ]; then
                    printf "%-*s\n" "$COLUMNS" "${SP[0]}: ${SP[1]} - ${SP[2]}"
                else
                    echo "${SP[1]}"
                fi
            fi
        done
    ))
}
complete -F __foo x

注: おそらくBash 4.x でCOMP_TYPE設定するために使用できますがFOR_DISPLAY、Bash 3.x もサポートする必要がありました。

これは次のように動作します。

$ x 1

Tab

$ x 10.10.10.1

TabTab

1: 10.10.10.10 - routerA
2: 10.10.10.11 - routerB
$ x 10.10.10.1
于 2012-07-24T08:30:56.427 に答える
1

いくつかの調査の後、私は解決策を見つけました。Cisco でどのように見えるかはわかりませんが、Vyatta でどのように機能するかは知っています。唯一の欠点は、このバリアントではTAB、初めて詳細なヘルプを取得するために 3 回押す必要があることです (最初の 2 回は通常の完了が出力されます)。詳細なヘルプが表示されたら、次TABの s で通常の補完と詳細な補完が切り替わります。

comment_show_last_detailed=1
comment_show_last_position=0

_comment_show()
{
  local cur opts i opt comment opts comments

  opts="result1
result2"
  comments="comment1
comment2"
  [ $comment_show_last_position -gt $COMP_POINT ] &&
    comment_show_last_position=0

  if [ $comment_show_last_detailed = 0 ] &&
     [ $comment_show_last_position = $COMP_POINT ]; then
    for ((i=1; ;++i)); do
      opt=`echo "$opts" | cut -f$i -d$'\n'`
      [ -z "$opt" ] && break
      comment=`echo "$comments" | cut -f$i -d$'\n'`
      echo
      echo -n "$opt - $comment"
    done
    comment_show_last_detailed=1
    COMPREPLY=
  else
    cur="${COMP_WORDS[COMP_CWORD]}"
    SAVEIFS="$IFS"
    IFS=$'\n'
    COMPREPLY=( $(compgen -W "${opts}" ${cur}) )
    IFS="$SAVEIFS"
    comment_show_last_detailed=0
  fi
  comment_show_last_position=$COMP_POINT
}
complete -F _comment_show comment

TAB変数を使用してプレスを2つだけに減らすことさえできましCOMP_TYPEたが、最初のプレス後にいくつかのシンボルが挿入された場合、bashが現在のコマンドラインを最下部の行に再表示しないという問題があるTABため、さらに調査する余地があります。

于 2012-01-22T09:19:13.207 に答える
1

はい。ただし、そのようなシステムを構築するには、bash kung foo が少し必要です。通常、補完が機能する方法は、通常の機能を補完したいコマンドにバインドすることです。補完がどのように機能するかをよりよく理解し、補完関数の開発を開始するために、いくつかの基本的な例を見つけることができます。また、たまたまbash-completionパッケージがインストールされている場合は、現在シェルで補完を実行している他の多くの例をシステムで検索できます。

公式の bash マニュアルの完了セクションも参照してください。


編集

私はいくつかの実験を試みましたが、私の結論は、あなたが求めていることを正確に行うことはできないcompleteということです.bashは結果の横にあるヘルプテキストをサポートしていません. できることは、提供された補完単語の凡例を追加することです。_myfooこれは、として使用されるbash 関数、または完了する前に凡例を出力するcomplete -F _myfooを介したコマンドのいずれかで実行できます。complete -C myfoo

主な違いは、関数を使用すると Bash にバインドされるのに対し、コマンドは、必要な環境変数を設定できる限り、選択した任意の言語で記述できることです。

以下に少し例を示します。

skuro$ touch ~/bin/myfoo
skuro$ chmod +x ~/bin/myfoo
skuro$ _myfoo(){
> echo "result1 -- number one"
> echo "result2 -- number two"
> local cur prev
> _get_comp_words_by_ref cur prev
> COMPREPLY=( $(compgen -W "result1 result2" "$cur") )
> return 0
> }
skuro$ complete -F _myfoo myfoo
skuro$ myfoo result<TAB>
result1 -- number one
result2 -- number two

result1  result2  
于 2011-09-01T07:33:51.993 に答える