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