bash-completion:スペースを含む引用候補を追加する

bash-completion:スペースを含む引用候補を追加する

既存のツールに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 ...) )

compgenprintを使用して文字列を暗黙的に分割し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'と同じように出力を設定して分割できますが、関数期間中にワイルドカードを無効にする必要があります。これは、保存して復元する別のグローバル状態です。

おすすめ記事