> -----Original Message-----
> From: git-ow...@vger.kernel.org 
> [mailto:git-ow...@vger.kernel.org] On Behalf Of Manlio Perillo
> Sent: Friday, December 21, 2012 11:55 AM
> To: git@vger.kernel.org
> Cc: sze...@ira.uka.de; felipe.contre...@gmail.com; Manlio Perillo
> Subject: [PATCH v4] git-completion.bash: add support for path 
> completion
> 
> The git-completion.bash script did not implemented full, git aware,
> support to complete paths, for git commands that operate on 
> files within
> the current working directory or the index.

I think this is a great improvement!  Very nice.

I've been playing with it but I'm not getting the expected 
behavior when I cd to a sub-directory.  Instead I get all files
in the repo as proposals.  I'm trying it in the git git-repository
itself.  Here is a sample:

> git status
# On branch pu
nothing to commit, working directory clean
> source contrib/completion/git-completion.bash
> touch contrib/test1
> touch contrib/test2
> git status
# On branch pu
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       contrib/test1
#       contrib/test2
nothing added to commit but untracked files present (use "git add" to track)
> git add <TAB> # this works as expected and I get: contrib/test1  
> contrib/test2  
> cd contrib/
> git add <TAB>
Display all 387 possibilities? (y or n)  # That is not right. Shouldn't I get
                                         # the same two files only?

Maybe I mis-understood what should happen?

Besides that, without looking at the patch in detail, I put just a couple
of minor points below.

> As an example:
> 
>       git add <TAB>
> 
> will suggest all files in the current working directory, including
> ignored files and files that have not been modified.
> 
> Support path completion, for git commands where the 
> non-option arguments
> always refer to paths within the current working directory or 
> the index, as the follow:

s/as the follow/as follows/

> * the path completion for the "git rm" and "git ls-files"
>   commands will suggest all cached files.
> 
> * the path completion for the "git add" command will suggest all
>   untracked and modified files.  Ignored files are excluded.
> 
> * the path completion for the "git clean" command will suggest all
>   untracked files.  Ignored files are excluded.
> 
> * the path completion for the "git mv" command will suggest all cached
>   files when expanding the first argument, and all untracked 
> and cached
>   files for subsequent arguments.  In the latter case, empty 
> directories
>   are included and ignored files are excluded.
> 
> * the path completion for the "git commit" command will suggest all
>   files that have been modified from the HEAD, if HEAD 
> exists, otherwise
>   it will suggest all cached files.
> 
> For all affected commands, completion will always stop at directory
> boundary.  Only standard ignored files are excluded, using the
> --exclude-standard option of the ls-files command.
> 
> Signed-off-by: Manlio Perillo <manlio.peri...@gmail.com>
> ---
> 
> Changes from version 3:
> 
>       * Fixed quoting issues
>       * Fixed default parameters handling
>       * Fixed a typo in the commit message: the affected 
> command was ls-files,
>         not ls-tree.
>       * Fixed incorrect behavior when expanding a path in "git commit"
>         command, for a newly created repository (when HEAD does not
>         exists).
>       * Make sure to always execute git commands with stderr 
> redirected to
>         /dev/null.
>       * Improved path completion for the git mv command.
>         This required a small refactorization of the __git_index_files
>         function, in order to support multiple options for ls-files.
> 
>  contrib/completion/git-completion.bash | 140 
> +++++++++++++++++++++++++++++----
>  1 file changed, 124 insertions(+), 16 deletions(-)
> 
> diff --git a/contrib/completion/git-completion.bash 
> b/contrib/completion/git-completion.bash
> index 0b77eb1..c8c6464 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -13,6 +13,7 @@
>  #    *) .git/remotes file names
>  #    *) git 'subcommands'
>  #    *) tree paths within 'ref:path/to/file' expressions
> +#    *) file paths within current working directory and index
>  #    *) common --long-options
>  #
>  # To use these routines:
> @@ -233,6 +234,62 @@ __gitcomp_nl ()
>       COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- 
> "${3-$cur}"))
>  }
>  
> +# Process path list returned by "ls-files" and "diff-index 
> --name-only"
> +# commands, in order to list only file names relative to a specified
> +# directory, and append a slash to directory names.
> +# It accepts 1 optional argument: a directory path.  The 
> path must have
> +# a trailing slash.
> +__git_index_file_list_filter ()
> +{
> +     local pfx="${1-}" offset=${#pfx} path
> +
> +     while read -r path; do
> +             path="${path:$offset}"
> +
> +             case "$path" in
> +             ?*/*) echo "${path%%/*}/" ;;
> +             *) echo $path ;;
> +             esac
> +     done
> +}
> +
> +# __git_index_files accepts 1 or 2 arguments:
> +# 1: Options to pass to ls-files (required).
> +#    Supported options are --cached, --modified, --deleted, --others,
> +#    and --directory.
> +# 2: A directory path (optional).
> +#    If provided, only files within the specified directory 
> are listed.
> +#    Sub directories are never recursed.  Path must have a trailing
> +#    slash.
> +__git_index_files ()
> +{
> +     local dir="$(__gitdir)"
> +
> +     if [ -d "$dir" ]; then
> +             # NOTE: $1 is not quoted in order to support 
> multiple options
> +             git --git-dir="$dir" ls-files 
> --exclude-standard $1 ${2+"$2"} 2>/dev/null |
> +                     __git_index_file_list_filter ${2+"$2"} |
> +                     uniq

Will the output piped to uniq always be sorted?  It has to be.
If it is not, you must use
  sort | uniq

> +     fi
> +}
> +
> +# __git_diff_index_files accepts 1 or 2 arguments:
> +# 1) The id of a tree object.
> +# 2) A directory path (optional).
> +#    If provided, only files within the specified directory 
> are listed.
> +#    Sub directories are never recursed.  Path must have a trailing
> +#    slash.
> +__git_diff_index_files ()
> +{
> +     local dir="$(__gitdir)"
> +
> +     if [ -d "$dir" ]; then
> +             git --git-dir="$dir" diff-index --name-only 
> "$1" 2>/dev/null |
> +                     __git_index_file_list_filter ${2+"$2"} |
> +                     uniq

Will the output piped to uniq always be sorted?  It has to be.
If it is not, you must use
  sort | uniq

> +     fi
> +}
> +
>  __git_heads ()
>  {
>       local dir="$(__gitdir)"
> @@ -430,6 +487,46 @@ __git_complete_revlist_file ()
>  }
>  
>  
> +# __git_complete_index_file requires 1 argument: the options 
> to pass to
> +# ls-file
> +__git_complete_index_file ()
> +{
> +     local pfx cur_="$cur"
> +
> +     case "$cur_" in
> +     ?*/*)
> +             pfx="${cur_%/*}"
> +             cur_="${cur_##*/}"
> +             pfx="${pfx}/"
> +
> +             __gitcomp_nl "$(__git_index_files "$1" "$pfx")" 
> "$pfx" "$cur_" ""
> +             ;;
> +     *)
> +             __gitcomp_nl "$(__git_index_files "$1")" "" "$cur_" ""
> +             ;;
> +     esac
> +}
> +
> +# __git_complete_diff_index_file requires 1 argument: the id 
> of a tree
> +# object
> +__git_complete_diff_index_file ()
> +{
> +     local pfx cur_="$cur"
> +
> +     case "$cur_" in
> +     ?*/*)
> +             pfx="${cur_%/*}"
> +             cur_="${cur_##*/}"
> +             pfx="${pfx}/"
> +
> +             __gitcomp_nl "$(__git_diff_index_files "$1" 
> "$pfx")" "$pfx" "$cur_" ""
> +             ;;
> +     *)
> +             __gitcomp_nl "$(__git_diff_index_files "$1")" 
> "" "$cur_" ""
> +             ;;
> +     esac
> +}
> +
>  __git_complete_file ()
>  {
>       __git_complete_revlist_file
> @@ -770,8 +867,6 @@ _git_apply ()
>  
>  _git_add ()
>  {
> -     __git_has_doubledash && return
> -
>       case "$cur" in
>       --*)
>               __gitcomp "
> @@ -780,7 +875,9 @@ _git_add ()
>                       "
>               return
>       esac
> -     COMPREPLY=()
> +
> +     # XXX should we check for --update and --all options ?
> +     __git_complete_index_file "--others --modified"
>  }
>  
>  _git_archive ()
> @@ -930,15 +1027,15 @@ _git_cherry_pick ()
>  
>  _git_clean ()
>  {
> -     __git_has_doubledash && return
> -
>       case "$cur" in
>       --*)
>               __gitcomp "--dry-run --quiet"
>               return
>               ;;
>       esac
> -     COMPREPLY=()
> +
> +     # XXX should we check for -x option ?
> +     __git_complete_index_file "--others"
>  }
>  
>  _git_clone ()
> @@ -969,8 +1066,6 @@ _git_clone ()
>  
>  _git_commit ()
>  {
> -     __git_has_doubledash && return
> -
>       case "$cur" in
>       --cleanup=*)
>               __gitcomp "default strip verbatim whitespace
> @@ -998,7 +1093,13 @@ _git_commit ()
>                       "
>               return
>       esac
> -     COMPREPLY=()
> +
> +     if git rev-parse --verify --quiet HEAD 1>/dev/null; then
> +             __git_complete_diff_index_file "HEAD"
> +     else
> +             # This is the first commit
> +             __git_complete_index_file "--cached"
> +     fi
>  }
>  
>  _git_describe ()
> @@ -1216,8 +1317,6 @@ _git_init ()
>  
>  _git_ls_files ()
>  {
> -     __git_has_doubledash && return
> -
>       case "$cur" in
>       --*)
>               __gitcomp "--cached --deleted --modified 
> --others --ignored
> @@ -1230,7 +1329,10 @@ _git_ls_files ()
>               return
>               ;;
>       esac
> -     COMPREPLY=()
> +
> +     # XXX ignore options like --modified and always suggest 
> all cached
> +     # files.
> +     __git_complete_index_file "--cached"
>  }
>  
>  _git_ls_remote ()
> @@ -1362,7 +1464,14 @@ _git_mv ()
>               return
>               ;;
>       esac
> -     COMPREPLY=()
> +
> +     if [ $cword -gt 2 ]; then
> +             # We need to show both cached and untracked 
> files (including
> +             # empty directories) since this may not be the 
> last argument.
> +             __git_complete_index_file "--cached --others 
> --directory"
> +     else
> +             __git_complete_index_file "--cached"
> +     fi
>  }
>  
>  _git_name_rev ()
> @@ -2068,15 +2177,14 @@ _git_revert ()
>  
>  _git_rm ()
>  {
> -     __git_has_doubledash && return
> -
>       case "$cur" in
>       --*)
>               __gitcomp "--cached --dry-run --ignore-unmatch --quiet"
>               return
>               ;;
>       esac
> -     COMPREPLY=()
> +
> +     __git_complete_index_file "--cached"
>  }
>  
>  _git_shortlog ()
> -- 
> 1.8.1.rc1.18.g9db0d25
> 
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> --
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to