所以,讓我們看到了水銀的bash腳本完成如何做到這一點。
這是important part:
_hg_status()
{
local files="$(_hg_cmd status -n$1 .)"
local IFS=$'\n'
COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
}
它被調用here:
_hg_command_specific()
{
case "$cmd" in
[...]
diff)
_hg_status "mar"
;;
[...]
esac
return 0
}
因此,它是一個簡單的hg status -nmar
通話,並使用輸出作爲完成的文件列表。
我想會不會太硬修補相似到git completion script的東西 - 我們將不得不修改__git_diff
這裏不做一個普通的文件名+分公司完成,但調用git status
代替。
命令
git status --porcelain | grep '^.[^ ?]' | cut -b 4-
(用於git diff --cached
)和
git status --porcelain | grep '^[^ ?]' | cut -b 4-
(爲git diff
)似乎輸出正確的事情(如果沒有改名)。
儘管如此,它們在區分HEAD以外的任何東西時都沒有用處。
一個更普遍的方式是使用
git diff --relative --name-only [--cached] [commit1] [commit2]]
其中commit1
和commit2
(也許--cached
)來自已經給diff命令行。
我在bash中實現了上述概念,並修補爲git-completion.bash
。如果您不想更改git-completion.bash
,請將這兩個函數添加到某個bash文件,並在原始git-completion.bash
之後將其源代碼。現在應該用命令工作就像
git diff -- <tab>
git diff --cached -- <tab>
git diff HEAD^^ -- <tab>
git diff origin/master master -- <tab>
我submitted this作爲補丁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
}
更新:貌似這個補丁不以這種形式通緝,因爲當前的方式來完成的文件是更有益需要檢查某個子目錄是否有變化的人(例如,在差異輸出可能爲空時完成)。如果鏈接到某個配置變量(默認爲當前行爲),則可能會被接受。此外,縮進應適應標準(請參閱Junio C Hamano的答案)。
我可能會再試一試,但不能保證在不久的將來。如果其他人想要這樣做,請隨時取走我的代碼,更改並重新提交。
我通常首先使用'git status',然後知道要爲'git diff'輸入什麼內容。 (但大多數情況下,我使用'gitk'查看差異。) – 2011-05-17 18:35:46