3

ずっと欲しかったコマンドライン機能があり、それをどうやって実現するかを考えましたが、何も得られませんでした...

したがって、ファイル名を入力してタブを押すと、次のようになります。

# git add Foo<tab>

find . -name "*$1*"を実行し、基本的に、コマンドラインに一致するファイルへの完全なパスをオートコンプリートしたいと思います。

私がこれまでに持っているもの:

たとえば、必要なパラメータを使用してアプリを呼び出す関数を作成する必要があることはわかっていますgit add。その後、タブキーストロークイベントをキャッチして上記の検索を実行し、結果が多い場合は表示するか、結果があれば入力する必要があります。

私が理解できなかったこと:

関数内の関数内でタブキーイベントをキャッチする方法。

したがって、基本的に擬似コードでは:

gadd() {git add autocomplete_file_search($1)}

autocomplete_file_search(keyword) {
  if( tab-key-pressed ){
    files = find . -name "*$1*";
    if( filecount > 1 ) {
      show list;
    }
    if( files == 1 ) {
      return files
    }
  }
}

何か案は?

ありがとう。

4

4 に答える 4

2

ファイル名の任意の場所での照合はかなり複雑であり、それが本当に役立つかどうかはわかりません。ファイル名の先頭での一致は、再帰的であっても、より理にかなっており、実装がはるかに簡単です。

ここで、要件としてfindについて言及しましたが、bash(バージョン4.0以降)でもファイルを再帰的に検索できるため、bashにその部分を実行させる方が効率的です。bashで再帰的に一致させるには、を実行してglobstarシェルオプションを有効にしますshopt -s globstar。その後、2つの連続するアスタリスク、**が再帰的に一致します。

次に、gitリポジトリ内でファイルを再帰的に照合する場合、実際にgitリポジトリ内にあることを検出する方法が最適です。そうしないと、たとえば誤ってトリガーした/場合、待機中にプロンプ​​トがハングします。 bashでファイルシステム全体を検索します。次の関数は、gitリポジトリ内にいるかどうかを判断するのにかなり効率的です。たとえば/foo/bar/baz、現在の作業ディレクトリを指定すると、、、を検索し/foo/bar/baz/.git、見つかった場合はtrueを返し、それ以外の場合はfalseを返します/foo/bar/.git/foo/.git/.git

isgit() {
    local p=$PWD
    while [[ $p ]]; do
        [[ -d $p/.git ]] && return
        p=${p%/*}
    done
    return 1
}

簡単にするためgaddに、補完を追加するコマンドを作成します。完了機能は、コマンドの最初の単語にのみ適用できます。たとえば、の補完を追加することはできますが、追加することはできgitません。したがって、 1つの単語git addに変わる新しいコマンドを作成します。git add

gadd() {
    git add "$@"
}

次に、実際の完了関数について説明します。TABを押すことによってトリガーされると、関数は3つの引数で呼び出されます。$1は完了しているコマンド、$2は完了しているコマンドラインの現在の単語、は行$3の前の単語です。したがって、検索するファイルはglobと一致し**/"$2"*ます。で始まるすべてのファイル"$2"。これらのファイル名を繰り返し、COMPREPLY配列に追加します。関数の実行時にCOMPREPLY配列に含まれる値が1つだけの場合、単語はその値に置き換えられます。複数の値が含まれている場合は、もう一度タブを押して、すべての一致のリストを取得します。

shopt -s globstar
_git_add_complete() {
    local file
    isgit || return
    for file in **/"$2"*; do
        # If the glob doesn't match, we'll get the glob itself, so make sure
        # we have an existing file
        [[ -e $file ]] || continue

        # If it's a directory, add a trailing /
        [[ -d $file ]] && file+=/
        COMPREPLY+=( "$file" )
    done
}
complete -F _git_add_complete gadd

上記の3つのコードブロックをに追加してから~/.bashrc、新しいターミナルを開き、gitリポジトリに入り、を試してくださいgadd something<tab>

于 2012-08-19T10:27:10.807 に答える
1

このbash 補完の概要 をご覧ください。簡単に言うと、bash にはタブ補完を構成および拡張するためのシステムがあります。他のシェルもこれを行い、それぞれに異なる設定方法があります。このシステムを使用すると、自分ですべてを行う必要はなく、カスタム引数補完をコマンドに追加するのは比較的簡単です。

于 2011-01-25T11:09:00.853 に答える
0

これは機能しますか?

$ cat .bash_completion
_foo()
{
    local files
    cur=${COMP_WORDS[COMP_CWORD]}
    local files=$(for x in `find -type f`; do echo ${x}; done)
    COMPREPLY=( $( compgen -W "${files}" -- ${cur} ) )
    return 0
}
complete -F _foo foo

$ . /etc/bash_completion
$ foo ./[tab]
于 2012-08-19T09:40:10.697 に答える
0

gitにファイルを指定するときにタブを押さなくてもいいようにgit-numberを書きました。

git-number を使用すると、数値を使用して、git で処理するファイル名を表すことができます。

于 2011-04-05T14:35:13.197 に答える