16

ファイルアップロードのセマンティクスをcurlと共有するツール用のbash完了スクリプトを作成しています。

curl を使用すると、次のことができます。

curl -F var=@file

ファイルをアップロードします。

私のアプリケーションには同様のセマンティクスがあり、「@」が押された後に可能なファイルを表示できるようにしたいと考えています。残念ながら、これは難しいことがわかっています。

cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ "$cur" == @* && "$prev" == '=' ]]; then
    COMPREPLY=( $(compgen -f ${cur:1}) )
    return 0
fi 

したがって、(これまでの) コマンドが次のように終了する場合:

abc=@

現在のディレクトリ内のファイルが表示されます。

 var=@/usr/                                                                                                                       
 /usr/bin      /usr/games 

問題は、実際にタブを押して完了すると、「@」が消えてしまうことです!

 var=/usr/bin

そのため、bash は現在の単語全体をタブ付きの COMPREPLY に置き換えているようです。

これを回避する唯一の方法は、次のようにすることです。

        COMPREPLY=( $(compgen -f ${cur:1}) )
        for (( i=0; i<${#COMPREPLY[@]}; i++ )); 
        do 
            COMPREPLY[$i]='@'${COMPREPLY[$i]} 
        done                                                                                                                       

しかし、控えめに言っても、タブ補完は奇妙に見えます。

@/usr/bin      @/usr/games

通常のファイル タブ補完 (「@」プレフィックスなし) を表示する方法はありますが、タブを押すときに「@」を保持しますか?

4

2 に答える 2

5

それで、これに興味をそそられたので、bash 補完ソース (/etc/bash_completion で入手可能) を読んでいます。

この変数に出くわしました:${COMP_WORDBREAKS}は、単語を区切るために使用される文字を制御できるように見えます。

_get_cword私はまた、この関数と補完的なに出くわしました。どちらもとそれぞれ_get_pwordの代わりに使用することをお勧めします。${COMP_WORDS[COMP_CWORD]}${COMP_WORDS[COMP_CWORD-1]}

それで、これらすべてをまとめて、私はいくつかのテストを行いました。これが私が思いついたものです:これは私にとってはうまくいくようです.

# maintain the old value, so that we only affect ourselves with this
OLD_COMP_WORDBREAKS=${COMP_WORDBREAKS}
COMP_WORDBREAKS="${COMP_WORDBREAKS}@"

cur="$(_get_cword)"
prev="$(_get_pword)"

if [[ "$cur" == '=@' ]]; then
    COMPREPLY=( $(compgen -f ${cur:2}) )

    # restore the old value
    COMP_WORDBREAKS=${OLD_COMP_WORDBREAKS}
    return 0
fi

if [[ "$prev" == '=@' ]]; then
    COMPREPLY=( $(compgen -f ${cur}) )

    # restore the old value
    COMP_WORDBREAKS=${OLD_COMP_WORDBREAKS}
    return 0

fi

さて、分割ifケースが少し汚れていることを認めます。間違いなくもっと良い方法がありますが、もっとカフェインが必要です.

-P <prefix>さらに、あなたにとって価値のあるものは何でも、 への引数の途中で発見しました。これにより、を呼び出した後に配列compgenをループする必要がなくなります。$COMPREPLY[*]}compgen

COMPREPLY=( $(compgen -P @ -f ${cur:1}) )

ただし、完全なソリューションに直面すると、これは少し冗長です。

于 2012-05-15T15:30:08.150 に答える
0

これを試して ....

function test
{
  COMPREPLY=()
  local cur="${COMP_WORDS[COMP_CWORD]}"
  local opts="Whatever sort of tabbing options you want to have!"
  COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
}
complete -F "test" -o "default" "test"
# complete -F "test" -o "nospace" "sd" ## Use this if you do not want a space after the completed word
于 2012-05-15T23:29:22.687 に答える