それでは、Mercurialのbash完了スクリプトがこれをどのように行うかを見てみましょう。
これは重要な部分です:
_hg_status()
{
local files="$(_hg_cmd status -n$1 .)"
local IFS=$'\n'
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
}
ここで呼ばれます:
_hg_command_specific()
{
case "$cmd" in
[...]
diff)
_hg_status "mar"
;;
[...]
esac
return 0
}
したがって、これは単にの呼び出しでありhg status -nmar
、出力を完了用のファイルのリストとして使用します。
git完了スクリプトに似たようなものをパッチするのはそれほど難しいことではないと思います-__git_diff
プレーンファイル名+ブランチ完了を行わず、代わりに呼び出すようにここで変更する必要がありますgit status
。
コマンド
git status --porcelain | grep '^.[^ ?]' | cut -b 4-
(のgit diff --cached
)と
git status --porcelain | grep '^[^ ?]' | cut -b 4-
(for git diff
)は正しいものを出力しているようです(名前の変更がない場合)。
ただし、HEAD以外のものと比較する場合はどちらも役に立ちません。
より一般的な方法は、
git diff --relative --name-only [--cached] [commit1] [commit2]]
ここでcommit1
、commit2
(そして多分--cached
)はすでに与えられたdiffコマンドラインから来ています。
上記で概説したアイデアをbashで実装し、にパッチを適用しましgit-completion.bash
た。を変更したくない場合はgit-completion.bash
、これら2つの関数をbashファイルに追加し、元のファイルの後にソースを設定しますgit-completion.bash
。これで、次のようなコマンドで動作するはずです。
git diff -- <tab>
git diff --cached -- <tab>
git diff HEAD^^ -- <tab>
git diff origin/master master -- <tab>
これをパッチとしてgitメーリングリストに送信しました。これからどのような結果になるか見てみましょう。(フィードバックがあり次第、この回答を更新します。)
# Completion for the file argument for git diff.
# It completes only files actually changed. This might be useful
# as completion for other commands as well.
#
# The idea comes from the bash completion for Mercurial (hg),
# which does something similar (but more simple, only difference of
# working directory to HEAD and/or index, if I understand right).
# It (the idea) was brought to us by the question
# http://stackoverflow.com/q/6034472/600500
# from "olt".
__git_complete_changed_files()
{
#
# We use "git diff --name-only --relative" to generate the list,
# but this needs the same --cached and <commit> arguments as the
# command line being constructed.
#
# first grab arguments like --cached and any commit arguments.
local -a args=()
local finish=false
for (( i=1 ; i < cword ; i++)) do
local current_arg=${words[$i]}
# echo checking $current_arg >&2
case $current_arg in
--cached)
args+=( $current_arg )
;;
--)
# finish parsing arguments, the rest are file names
break
;;
-*)
# other options are ignored
;;
*)
if git cat-file -e $current_arg 2> /dev/null
then
case $( git cat-file -t $current_arg ) in
commit|tag)
# commits and tags are added to the command line.
args+=( $current_arg )
# echo adding $current_arg >&2
;;
*)
esac
fi
;;
esac
done
# now we can call `git diff`
COMPREPLY=( $( compgen \
-W "$( git diff --name-only --relative "${args[@]}" -- )" -- $cur ) )
}
_git_diff ()
{
if __git_has_doubledash
then
# complete for the file part: only changed files
__git_complete_changed_files
else
case "$cur" in
--*)
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
--base --ours --theirs --no-index
$__git_diff_common_options
"
return
;;
esac
__git_complete_revlist_file
fi
}
更新:このフォームでは、このパッチは必要ないようです。ファイルを完成させる現在の方法は、サブディレクトリに変更があるかどうかを確認したい人にとってより便利です(たとえば、diff出力が空になる可能性があるときに完了する)。いくつかの構成変数にリンクされている場合は受け入れられる可能性があります(デフォルトは現在の動作です)。また、インデントは標準に適合させる必要があります(Junio C Hamanoの回答を参照)。
もう一度やり直すかもしれませんが、近い将来これを保証することはできません。他の誰かがやりたい場合は、私のコードを自由に取り、変更して、もう一度送信してください。