The bash completion script for git diff completes either for references or for file names. If there was a -- given, it uses the default bash filename completion. The completion for hg diff completes only changed file names here - this is quite useful if we want to see changes in only some file (or directory). (This was mentioned on stackoverflow, which gave me the idea: http://stackoverflow.com/q/6034472/600500 ) I ported this idea to git. Now git diff -- <tab> will complete any changed files. It also works for the other ways of calling git diff, except the .. and ... notations (as I'm not sure how to do this). Signed-off-by: PaÅlo Ebermann <Paul-Ebermann@xxxxxx> --- Hello, this is my first contribution to git at all, and I only joined the mailing list some hours ago (right before starting to code this), so I hope I'm not making any mistakes here. (I read the SubmittingPatches document, though.) I only made this work after the --, while the usual file completion already seems to work if there is no --. I'm not really sure what is wanted here. I'm checking the non-option arguments on being commits (or tags), and pass only the matching ones to the nested `git diff` call. It might be easier to ommit this check and pass everything that does not start with a `-`. Then it would also easily work for the .. and ... syntax, I think. Opinions? The same completion function or a variation might also be useful for other commands like git add (completing changed or new files) or git rm (completing already removed files). Input is welcome here. This patch is based on the current master branch, I hope this is the right one. contrib/completion/git-completion.bash | 72 +++++++++++++++++++++++++++++++- 1 files changed, 70 insertions(+), 2 deletions(-) diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index bb8d7d0..c529bdf 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -663,6 +663,69 @@ __git_compute_merge_strategies () : ${__git_merge_strategies:=$(__git_list_merge_strategies)} } + +# 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_complete_revlist_file () { local pfx ls ref cur_="$cur" @@ -1314,10 +1377,14 @@ __git_diff_common_options="--stat --numstat --shortstat --summary --dirstat-by-file= --cumulative " + _git_diff () { - __git_has_doubledash && return - + 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 @@ -1328,6 +1395,7 @@ _git_diff () ;; esac __git_complete_revlist_file + fi } __git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html