bashがディレクトリ名を完成させる方法を構成することは可能ですか?


8

特定のディレクトリ名で補完を実行する特別な方法を使用するようにbashに指示したいのですが。たとえば、bashはパスが "$$"で始まる場合に完了を実行するために私のプログラムを呼び出し、それ以外の場合は通常に完了を実行します。

これはまったく可能ですか?どのように実装しますか?

バウンティ:その質問への回答を本当に感謝します。目標は、ユーザーが特定の接頭辞を付けて開始したときに、autojumpがすべてのコマンドのパスを完了することを許可することです。たとえば、farディレクトリからファイルをコピーする場合は、次のように入力できます。

cp $$patern + <Tab>

自動ジャンプが完了する

cp /home/user/CompliCatedDireCTOry/long/path/bla/bla

ファイルを置きたい場所を追加するだけです。もちろん、ottのコメントを使用して、いくつかの特定のコマンドにコメントを追加できますが、誰かがより良いアイデアを持っている場合、私は非常に感謝します。


bash manページの「Programmable Completion」のセクションを参照してください。

私の質問を閉じるために投票した場合は、その理由を説明してください。
ペルティエ

2
"complete"は、$$の先頭に一致する "-Gパターン"と、独自の関数を呼び出す "-F func"をサポートしていますが、機能するには1つ以上のコマンド名が必要です。

なぜ環境変数を使用しないのですか?例:cp $ prefix / file / path / to / dest /
Xenoactive

@Xenoactive:autojumpは完全に自動化されており、複数のパスで機​​能します。手動で設定した環境変数を使用しても効果はありません。それとも私には理解できない強力なアイデアがあるのでしょうか?
ペルチェ2010

回答:


3

これを行うには、TAB(^ i)のデフォルトのバインディングをオーバーライドします。最初にTABバインディングをオーバーライドする必要があります。次に、コマンドを呼び出す関数を作成する必要があります。最後に、そのコマンドから出力を取得し、現在のコマンドラインを含む変数を更新する必要があります。

この関数は、現在のコマンドラインを受け取り、最後の2文字を「ハグ」に変更します。

function my_awesome_tab_completion_function () {
  set -- $READLINE_LINE
  command="$1"
  shift
  argument="$*"
  argument_length=$(echo -n $argument | wc -c)
  if echo $argument | grep '^$$' >/dev/null 2>&1; then
    new_argument=$(echo $argument | sed 's/..$/huugs/') # put your autojump here
  else
    new_argument=$(compgen -d $argument)
  fi
  new_argument_length=$(echo -n $new_argument | wc -c)
  READLINE_POINT=$(( $new_argument_length - $argument_length + $READLINE_POINT ))
  READLINE_LINE="$command $new_argument"
}

あなたの例では、おそらくnew_argument行を次のように変更したいと思うでしょう:

  new_argument=$(autojump $argument)

^ iバインディングをオーバーライドします。

$ bind -x '"\C-i"':'my_awesome_tab_completion_function'

次に、それが機能することをテストします。

$ cd /ro<TAB>
changes my command to:
$ cd /root

通常の補完は引き続き機能するので、cd $$ ...などを実行して$$部分をテストできます

問題が発生した場合は、詳細モードをオンにします。

$ set -x

関数が実行しているすべてを出力します。

私はbash 4.2.8(1)-release(デフォルト)を使用してUbuntu 11でこれをテストしました。


これはコマンドの最初のパラメーターでのみ機能するようですが、タブが予期しない方法で使用された場合(たとえば、$$$の後やコマンド名の後)に奇妙なことを行うことができますか、それとも間違っていますか?
harrymc '10 / 09/11

まあ、それは$ *を渡していますので、最初のパラメーターだけで「機能」します(autojumpはまったくわからないので、複数の引数を取ることができるかどうかはわかりません)。最後にシフトして最後をautojumpに送信するか、READLINE_POINTを使用してカーソルがコマンド引数のどこにあるかを判別し、その「単語」のみをautojumpにも送信できます。
多項式

あなたの解決策は興味深いですが、タブキーを引き継ぐことは少し極端であることを認めなければなりません。考えられるすべてのケースを予測できる方法はありません。
harrymc '12

あなたの答えをありがとう、それは素晴らしい代替ソリューションです、そしてそれは私の質問の「すべてのコマンド」の部分に対処します。私はそれが少し極端だとハリーマックに同意します...しかし、誰もより良い解決策を考え出せないなら、私はそれを試して、それが実行可能であるかどうかを確認するでしょう。
ペルティエ

はい私もハリーマックに同意しますが、尋ねられた質問に答えようとしていました。個人的には、これを^ Gなどの別のコントロールキーにバインドするだけで、タブをそのままにしてこの機能を使用できます。
多項式

1

bash完了ルーチンは、シェルスクリプトとしてプログラムできます。

ここでは任意のパラメータで置き換えますシェル・スクリプトの例である$$[Tab]ことでmy replacement stringはなく、唯一の特定のコマンドのmycommandパラメータが正確である場合にのみ、「$$」:

_mycomplete()
{
        if [ ${COMP_WORDS[COMP_CWORD]} == \$\$ ]
        then
                COMPREPLY='my replacement string'
        fi
}
complete -o default -o bashdefault -F _mycomplete mycommand

スクリプトを実行してスクリプトを実行し、source <file-name>(またはドットコマンドで)bashを実行します。

mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)

一部またはすべてのユーザーに対して常に機能するようにするには、これをbashプロファイルルーチンの 1つに含めます

completeコマンドの問題は、パラメーターとして指定されているコマンドの1つ以上の名前に対してのみ機能することです。ユーザーが使用できる可能性のあるすべてのコマンドのリストを単純に与えることもできますし、必死の場合は展開することもできます/bin/* /usr/bin/* ~/bin/*

CentOS 5.5でテスト済み。

この簡単なスクリプトは、他の回答でリストしたソースに基づいています。モデレーターのstudiohackによって削除されたものです。興味がある場合は、削除を取り消すように依頼してください。


ご回答有難うございます。私の質問は、それが可能だったのでそれについてはそれほどではありませんでしたが、すべてのコマンドを完了することはできません。ただし、多項式の解が受け入れられない場合は、そのようなものを実装して、最も一般的なコマンドを対象とするようにします。
ペルティエ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.