RE: [PATCH v4] git-completion.bash: add support for path completion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: git-owner@xxxxxxxxxxxxxxx 
> [mailto:git-owner@xxxxxxxxxxxxxxx] On Behalf Of Manlio Perillo
> Sent: Friday, December 21, 2012 11:55 AM
> To: git@xxxxxxxxxxxxxxx
> Cc: szeder@xxxxxxxxxx; felipe.contreras@xxxxxxxxx; 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.perillo@xxxxxxxxx>
> ---
> 
> 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 majordomo@xxxxxxxxxxxxxxx
> 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]