git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3/RFC 0/2] Make git-completion Bash 4 compatible.
@ 2010-10-30 20:42 Peter van der Does
  2010-10-30 20:42 ` [PATCH v3/RFC 1/2] Introduce functions from bash-completion project Peter van der Does
  2010-10-30 20:42 ` [PATCH v3/RFC 2/2] Use the new functions to get the current cword Peter van der Does
  0 siblings, 2 replies; 4+ messages in thread
From: Peter van der Does @ 2010-10-30 20:42 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: Peter van der Does, git, SZEDER Gábor, Jonathan Nieder,
	Marc Branchaud, Brian Gernhardt, Kevin Ballard, Mathias Lafeldt

I've made the following changes based on replies to v2:
* Split the commit up in two commits. One for the introduction of the new functions and one for the implementation of the new functions.
* Removed a function from the introduced bash-completion functions.
* Added acknowledgment for the bash-completion-project.

Peter van der Does (2):
  Introduce functions from bash-completion project.
  Use the new functions to get the current cword.

 contrib/completion/git-completion.bash |  446 ++++++++++++++++++++++++++------
 1 files changed, 363 insertions(+), 83 deletions(-)

-- 
1.7.3.2

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v3/RFC 1/2] Introduce functions from bash-completion project.
  2010-10-30 20:42 [PATCH v3/RFC 0/2] Make git-completion Bash 4 compatible Peter van der Does
@ 2010-10-30 20:42 ` Peter van der Does
  2010-11-01 13:35   ` Marc Branchaud
  2010-10-30 20:42 ` [PATCH v3/RFC 2/2] Use the new functions to get the current cword Peter van der Does
  1 sibling, 1 reply; 4+ messages in thread
From: Peter van der Does @ 2010-10-30 20:42 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: Peter van der Does, git, SZEDER Gábor, Jonathan Nieder,
	Marc Branchaud, Brian Gernhardt, Kevin Ballard, Mathias Lafeldt

The completion script does not work as expected under Bash 4.
Bash: 3
output:
$ git log --pretty=<tab><tab>
email     full      medium    raw
format:   fuller    oneline   short

Bash: 4
output:
$ git log --pretty=<tab><tab>
.bash_logout         .local/
.bash_profile        Music/
--More--

With Bash 4 the way word breaking is done in the programmable completion
code has changed. The documentation at the bash project is not very
clear what was changed, the only reference found is in the NEWS section:

i.  The programmable completion code now uses the same set of characters
as readline when breaking the command line into a list of words.

The word breaking problem occurs with certain characters, like double
colon and equal sign.

The bash-completion project (http://bash-completion.alioth.debian.org/)
has written several functions to overcome this problem. By using these
functions within the git-completion.bash script the word breaking
problem is solved.

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
 contrib/completion/git-completion.bash |  223 ++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 168669b..e0f5893 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -82,6 +82,229 @@ case "$COMP_WORDBREAKS" in
 *)   COMP_WORDBREAKS="$COMP_WORDBREAKS:"
 esac
 
+# If the function _get_comp_words_by_ref does not exists, we can assume the
+# bash_completion 1.2 script isn't loaded and therefor we're defining the
+# necessary functions ourselves.
+# The functions come from the bash_completion 1.2 script.
+# See: http://bash-completion.alioth.debian.org/
+if ! type _get_comp_words_by_ref &> /dev/null ; then
+	# The bash_completion 1.2 library wasn't loaded,
+	# we have to define some functions from it ourselves.
+
+	# Assign variables one scope above the caller
+	# Usage: local varname [varname ...] &&
+	#        _upvars [-v varname value] | [-aN varname [value ...]] ...
+	# Available OPTIONS:
+	#     -aN  Assign next N values to varname as array
+	#     -v   Assign single value to varname
+	# Return: 1 if error occurs
+	# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
+	_upvars() {
+	    if ! (( $# )); then
+	        echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
+	            "value] | [-aN varname [value ...]] ..." 1>&2
+	        return 2
+	    fi
+	    while (( $# )); do
+	        case $1 in
+	            -a*)
+	                # Error checking
+	                [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
+	                    "number specifier" 1>&2; return 1; }
+	                printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
+	                    "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
+	                    return 1; }
+	                # Assign array of -aN elements
+	                [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
+	                shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
+	                    "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
+	                ;;
+	            -v)
+	                # Assign single value
+	                [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
+	                shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
+	                "argument(s)" 1>&2; return 1; }
+	                ;;
+	            *)
+	                echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
+	                return 1 ;;
+	        esac
+	    done
+	}
+
+
+	# Reassemble command line words, excluding specified characters from the
+	# list of word completion separators (COMP_WORDBREAKS).
+	# @param $1 chars  Characters out of $COMP_WORDBREAKS which should
+	#     NOT be considered word breaks. This is useful for things like scp where
+	#     we want to return host:path and not only path, so we would pass the
+	#     colon (:) as $1 here.
+	# @param $2 words  Name of variable to return words to
+	# @param $3 cword  Name of variable to return cword to
+	#
+	__reassemble_comp_words_by_ref() {
+	    local exclude i j ref
+	    # Exclude word separator characters?
+	    if [[ $1 ]]; then
+	        # Yes, exclude word separator characters;
+	        # Exclude only those characters, which were really included
+	        exclude="${1//[^$COMP_WORDBREAKS]}"
+	    fi
+
+	    # Default to cword unchanged
+	    eval $3=$COMP_CWORD
+	    # Are characters excluded which were former included?
+	    if [[ $exclude ]]; then
+	        # Yes, list of word completion separators has shrunk;
+	        # Re-assemble words to complete
+	        for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+	            # Is current word not word 0 (the command itself) and is word not
+	            # empty and is word made up of just word separator characters to be
+	            # excluded?
+	            while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&
+	                ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}
+	            ]]; do
+	                [ $j -ge 2 ] && ((j--))
+	                # Append word separator to current word
+	                ref="$2[$j]"
+	                eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+	                # Indicate new cword
+	                [ $i = $COMP_CWORD ] && eval $3=$j
+	                # Indicate next word if available, else end *both* while and for loop
+	                (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
+	            done
+	            # Append word to current word
+	            ref="$2[$j]"
+	            eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
+	            # Indicate new cword
+	            [ $i = $COMP_CWORD ] && [[ ${COMP_WORDS[i]} ]] && eval $3=$j
+	        done
+	    else
+	        # No, list of word completions separators hasn't changed;
+	        eval $2=\( \"\${COMP_WORDS[@]}\" \)
+	    fi
+	} # __reassemble_comp_words_by_ref()
+
+	# @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
+	#     considered word breaks. This is useful for things like scp where
+	#     we want to return host:path and not only path, so we would pass the
+	#     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
+	#     ensures we get the same word on both bash-3 and bash-4.
+	# @param $2 words  Name of variable to return words to
+	# @param $3 cword  Name of variable to return cword to
+	# @param $4 cur  Name of variable to return current word to complete to
+	# @see ___get_cword_at_cursor_by_ref()
+	__get_cword_at_cursor_by_ref() {
+	    local cword words=()
+	    __reassemble_comp_words_by_ref "$1" words cword
+
+	    local i cur2
+	    local cur="$COMP_LINE"
+	    local index="$COMP_POINT"
+	    for (( i = 0; i <= cword; ++i )); do
+	        while [[
+	            # Current word fits in $cur?
+	            "${#cur}" -ge ${#words[i]} &&
+	            # $cur doesn't match cword?
+	            "${cur:0:${#words[i]}}" != "${words[i]}"
+	        ]]; do
+	            # Strip first character
+	            cur="${cur:1}"
+	            # Decrease cursor position
+	            ((index--))
+	        done
+
+	        # Does found word matches cword?
+	        if [[ "$i" -lt "$cword" ]]; then
+	            # No, cword lies further;
+	            local old_size="${#cur}"
+	            cur="${cur#${words[i]}}"
+	            local new_size="${#cur}"
+	            index=$(( index - old_size + new_size ))
+	        fi
+	    done
+
+	    if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
+	        # We messed up. At least return the whole word so things keep working
+	        cur2=${words[cword]}
+	    else
+	        cur2=${cur:0:$index}
+	    fi
+
+	    local "$2" "$3" "$4" &&
+	        _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
+	}
+
+
+	# Get the word to complete and optional previous words.
+	# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
+	# where the user is completing in the middle of a word.
+	# (For example, if the line is "ls foobar",
+	# and the cursor is here -------->   ^
+	# Also one is able to cross over possible wordbreak characters.
+	# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
+	# Available VARNAMES:
+	#     cur         Return cur via $cur
+	#     prev        Return prev via $prev
+	#     words       Return words via $words
+	#     cword       Return cword via $cword
+	#
+	# Available OPTIONS:
+	#     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be
+	#                 considered word breaks. This is useful for things like scp
+	#                 where we want to return host:path and not only path, so we
+	#                 would pass the colon (:) as -n option in this case.  Bash-3
+	#                 doesn't do word splitting, so this ensures we get the same
+	#                 word on both bash-3 and bash-4.
+	#     -c VARNAME  Return cur via $VARNAME
+	#     -p VARNAME  Return prev via $VARNAME
+	#     -w VARNAME  Return words via $VARNAME
+	#     -i VARNAME  Return cword via $VARNAME
+	#
+	# Example usage:
+	#
+	#    $ _get_comp_words_by_ref -n : cur prev
+	#
+	_get_comp_words_by_ref()
+	{
+	    local exclude flag i OPTIND=1
+	    local cur cword words=()
+	    local upargs=() upvars=() vcur vcword vprev vwords
+
+	    while getopts "c:i:n:p:w:" flag "$@"; do
+	        case $flag in
+	            c) vcur=$OPTARG ;;
+	            i) vcword=$OPTARG ;;
+	            n) exclude=$OPTARG ;;
+	            p) vprev=$OPTARG ;;
+	            w) vwords=$OPTARG ;;
+	        esac
+	    done
+	    while [[ $# -ge $OPTIND ]]; do
+	        case ${!OPTIND} in
+	            cur)   vcur=cur ;;
+	            prev)  vprev=prev ;;
+	            cword) vcword=cword ;;
+	            words) vwords=words ;;
+	            *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
+	                1>&2; return 1
+	        esac
+	        let "OPTIND += 1"
+	    done
+
+	    __get_cword_at_cursor_by_ref "$exclude" words cword cur
+
+	    [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
+	    [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
+	    [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
+	        "${words[cword - 1]}"); }
+	    [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
+	        "${words[@]}"); }
+
+	    (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
+	}
+fi
+
 # __gitdir accepts 0 or 1 arguments (i.e., location)
 # returns location of .git repo
 __gitdir ()
-- 
1.7.3.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v3/RFC 2/2] Use the new functions to get the current cword.
  2010-10-30 20:42 [PATCH v3/RFC 0/2] Make git-completion Bash 4 compatible Peter van der Does
  2010-10-30 20:42 ` [PATCH v3/RFC 1/2] Introduce functions from bash-completion project Peter van der Does
@ 2010-10-30 20:42 ` Peter van der Does
  1 sibling, 0 replies; 4+ messages in thread
From: Peter van der Does @ 2010-10-30 20:42 UTC (permalink / raw)
  To: Shawn O. Pearce
  Cc: Peter van der Does, git, SZEDER Gábor, Jonathan Nieder,
	Marc Branchaud, Brian Gernhardt, Kevin Ballard, Mathias Lafeldt

Change the completion functions to use the newly introduced functions to
get the current and/or previous cword and to reassemble the COMP_CWORDS,
making sure the options are correctly split.

Signed-off-by: Peter van der Does <peter@avirtualhome.com>
---
 contrib/completion/git-completion.bash |  223 ++++++++++++++++++++------------
 1 files changed, 140 insertions(+), 83 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index e0f5893..3115377 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -554,7 +554,8 @@ __gitcomp_1 ()
 # generates completion reply with compgen
 __gitcomp ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	if [ $# -gt 2 ]; then
 		cur="$3"
 	fi
@@ -613,7 +614,8 @@ __git_tags ()
 __git_refs ()
 {
 	local i is_hash=y dir="$(__gitdir "${1-}")"
-	local cur="${COMP_WORDS[COMP_CWORD]}" format refs
+	local cur format refs
+	_get_comp_words_by_ref cur
 	if [ -d "$dir" ]; then
 		case "$cur" in
 		refs|refs/*)
@@ -711,7 +713,8 @@ __git_compute_merge_strategies ()
 
 __git_complete_file ()
 {
-	local pfx ls ref cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx ls ref cur
+	_get_comp_words_by_ref -n ":" cur
 	case "$cur" in
 	?*:*)
 		ref="${cur%%:*}"
@@ -759,7 +762,8 @@ __git_complete_file ()
 
 __git_complete_revlist ()
 {
-	local pfx cur="${COMP_WORDS[COMP_CWORD]}"
+	local pfx cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	*...*)
 		pfx="${cur%...*}..."
@@ -779,11 +783,13 @@ __git_complete_revlist ()
 
 __git_complete_remote_or_refspec ()
 {
-	local cmd="${COMP_WORDS[1]}"
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur words cword
+	_get_comp_words_by_ref -n ":" cur words cword
+	local cmd="${words[1]}"
 	local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
 		--all)
@@ -851,13 +857,15 @@ __git_complete_remote_or_refspec ()
 
 __git_complete_strategy ()
 {
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
 	__git_compute_merge_strategies
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-s|--strategy)
 		__gitcomp "$__git_merge_strategies"
 		return 0
 	esac
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+
 	case "$cur" in
 	--strategy=*)
 		__gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
@@ -1017,10 +1025,11 @@ __git_aliased_command ()
 # __git_find_on_cmdline requires 1 argument
 __git_find_on_cmdline ()
 {
-	local word subcommand c=1
+	local word subcommand c=1 words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		word="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cword ]; do
+		word="${words[c]}"
 		for subcommand in $1; do
 			if [ "$subcommand" = "$word" ]; then
 				echo "$subcommand"
@@ -1033,9 +1042,10 @@ __git_find_on_cmdline ()
 
 __git_has_doubledash ()
 {
-	local c=1
-	while [ $c -lt $COMP_CWORD ]; do
-		if [ "--" = "${COMP_WORDS[c]}" ]; then
+	local c=1, words cword
+	_get_comp_words_by_ref words cword
+	while [ $c -lt $cwords ]; do
+		if [ "--" = "${words[c]}" ]; then
 			return 0
 		fi
 		c=$((++c))
@@ -1047,7 +1057,9 @@ __git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur dir="$(__gitdir)"
+
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ]; then
 		__gitcomp "--skip --continue --resolved --abort"
 		return
@@ -1071,7 +1083,8 @@ _git_am ()
 
 _git_apply ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
@@ -1094,7 +1107,8 @@ _git_add ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1108,7 +1122,8 @@ _git_add ()
 
 _git_archive ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1152,10 +1167,11 @@ _git_bisect ()
 
 _git_branch ()
 {
-	local i c=1 only_local_ref="n" has_r="n"
+	local i c=1 only_local_ref="n" has_r="n" cur words cword
+	_get_comp_words_by_ref cur words cword
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-m)	only_local_ref="y" ;;
 		-r)	has_r="y" ;;
@@ -1163,7 +1179,7 @@ _git_branch ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD]}" in
+	case "$cur" in
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
@@ -1183,8 +1199,10 @@ _git_branch ()
 
 _git_bundle ()
 {
-	local cmd="${COMP_WORDS[2]}"
-	case "$COMP_CWORD" in
+	local words cword
+	_get_comp_words_by_ref words cword
+	local cmd="${words[2]}"
+	case "$cword" in
 	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
@@ -1205,7 +1223,8 @@ _git_checkout ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
@@ -1229,7 +1248,8 @@ _git_cherry ()
 
 _git_cherry_pick ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --no-commit"
@@ -1244,7 +1264,8 @@ _git_clean ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run --quiet"
@@ -1256,7 +1277,8 @@ _git_clean ()
 
 _git_clone ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1283,7 +1305,8 @@ _git_commit ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--cleanup=*)
 		__gitcomp "default strip verbatim whitespace
@@ -1318,7 +1341,8 @@ _git_commit ()
 
 _git_describe ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1350,7 +1374,8 @@ _git_diff ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
@@ -1371,7 +1396,8 @@ _git_difftool ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
@@ -1396,7 +1422,8 @@ __git_fetch_options="
 
 _git_fetch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1408,7 +1435,8 @@ _git_fetch ()
 
 _git_format_patch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1440,7 +1468,8 @@ _git_format_patch ()
 
 _git_fsck ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1455,7 +1484,8 @@ _git_fsck ()
 
 _git_gc ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--prune --aggressive"
@@ -1474,7 +1504,8 @@ _git_grep ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1497,7 +1528,8 @@ _git_grep ()
 
 _git_help ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--all --info --man --web"
@@ -1515,7 +1547,8 @@ _git_help ()
 
 _git_init ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1535,7 +1568,8 @@ _git_ls_files ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --deleted --modified --others --ignored
@@ -1589,7 +1623,8 @@ _git_log ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	local g="$(git rev-parse --git-dir 2>/dev/null)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
@@ -1648,7 +1683,8 @@ _git_merge ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_merge_options"
@@ -1659,7 +1695,8 @@ _git_merge ()
 
 _git_mergetool ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--tool=*)
 		__gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"
@@ -1680,7 +1717,8 @@ _git_merge_base ()
 
 _git_mv ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--dry-run"
@@ -1697,13 +1735,14 @@ _git_name_rev ()
 
 _git_notes ()
 {
-	local subcommands="edit show"
+	local subcommands="edit show" prev
+	_get_comp_words_by_ref prev
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
 		__gitcomp "$subcommands"
 		return
 	fi
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -1717,7 +1756,8 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1733,8 +1773,9 @@ _git_pull ()
 
 _git_push ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	local cur prev
+	_get_comp_words_by_ref -n "=" cur prev
+	case "$prev" in
 	--repo)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1757,7 +1798,9 @@ _git_push ()
 
 _git_rebase ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	local cur
+	local dir="$(__gitdir)"
+	_get_comp_words_by_ref -n "=" cur
 	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
@@ -1787,7 +1830,8 @@ __git_send_email_suppresscc_options="author self cc bodycc sob cccmd body all"
 
 _git_send_email ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--confirm=*)
 		__gitcomp "
@@ -1829,9 +1873,10 @@ _git_stage ()
 
 __git_config_get_set_variables ()
 {
-	local prevword word config_file= c=$COMP_CWORD
-	while [ $c -gt 1 ]; do
-		word="${COMP_WORDS[c]}"
+	local prevword word config_file= words cword
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $cword -gt 1 ]; do
+		word="${words[cword]}"
 		case "$word" in
 		--global|--system|--file=*)
 			config_file="$word"
@@ -1843,7 +1888,7 @@ __git_config_get_set_variables ()
 			;;
 		esac
 		prevword=$word
-		c=$((--c))
+		cword=$((--cword))
 	done
 
 	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
@@ -1859,9 +1904,9 @@ __git_config_get_set_variables ()
 
 _git_config ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	local prv="${COMP_WORDS[COMP_CWORD-1]}"
-	case "$prv" in
+	local cur prev
+	_get_comp_words_by_ref cur prev
+	case "$prev" in
 	branch.*.remote)
 		__gitcomp "$(__git_remotes)"
 		return
@@ -1871,13 +1916,13 @@ _git_config ()
 		return
 		;;
 	remote.*.fetch)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		__gitcomp "$(__git_refs_remotes "$remote")"
 		return
 		;;
 	remote.*.push)
-		local remote="${prv#remote.}"
+		local remote="${prev#remote.}"
 		remote="${remote%.push}"
 		__gitcomp "$(git --git-dir="$(__gitdir)" \
 			for-each-ref --format='%(refname):%(refname)' \
@@ -2268,7 +2313,8 @@ _git_reset ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--merge --mixed --hard --soft --patch"
@@ -2280,7 +2326,8 @@ _git_reset ()
 
 _git_revert ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
@@ -2294,7 +2341,8 @@ _git_rm ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur=
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
@@ -2308,7 +2356,8 @@ _git_shortlog ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2326,7 +2375,8 @@ _git_show ()
 {
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref -n "=" cur
 	case "$cur" in
 	--pretty=*)
 		__gitcomp "$__git_log_pretty_formats
@@ -2350,7 +2400,8 @@ _git_show ()
 
 _git_show_branch ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2367,10 +2418,11 @@ _git_show_branch ()
 
 _git_stash ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local save_opts='--keep-index --no-keep-index --quiet --patch'
 	local subcommands='save list show apply clear drop pop create branch'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
+	_get_comp_words_by_ref cur
 	if [ -z "$subcommand" ]; then
 		case "$cur" in
 		--*)
@@ -2412,7 +2464,8 @@ _git_submodule ()
 
 	local subcommands="add status init update summary foreach sync"
 	if [ -z "$(__git_find_on_cmdline "$subcommands")" ]; then
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$cur" in
 		--*)
 			__gitcomp "--quiet --cached"
@@ -2456,7 +2509,8 @@ _git_svn ()
 			--edit --rmdir --find-copies-harder --copy-similarity=
 			"
 
-		local cur="${COMP_WORDS[COMP_CWORD]}"
+		local cur
+		_get_comp_words_by_ref cur
 		case "$subcommand,$cur" in
 		fetch,--*)
 			__gitcomp "--revision= --fetch-all $fc_opts"
@@ -2527,9 +2581,10 @@ _git_svn ()
 
 _git_tag ()
 {
-	local i c=1 f=0
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	local i c=1 f=0 words cword prev
+	_get_comp_words_by_ref prev words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		-d|-v)
 			__gitcomp "$(__git_tags)"
@@ -2542,7 +2597,7 @@ _git_tag ()
 		c=$((++c))
 	done
 
-	case "${COMP_WORDS[COMP_CWORD-1]}" in
+	case "${prev}" in
 	-m|-F)
 		COMPREPLY=()
 		;;
@@ -2566,15 +2621,16 @@ _git_whatchanged ()
 
 _git ()
 {
-	local i c=1 command __git_dir
+	local i c=1 command __git_dir words cword
 
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
-	while [ $c -lt $COMP_CWORD ]; do
-		i="${COMP_WORDS[c]}"
+	_get_comp_words_by_ref -n "=" words cword
+	while [ $c -lt $cword ]; do
+		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
@@ -2586,7 +2642,7 @@ _git ()
 	done
 
 	if [ -z "$command" ]; then
-		case "${COMP_WORDS[COMP_CWORD]}" in
+		case "${words[cword]}" in
 		--*)   __gitcomp "
 			--paginate
 			--no-pager
@@ -2617,19 +2673,20 @@ _git ()
 
 _gitk ()
 {
-	if [[ -n ${ZSH_VERSION-} ]]; then
+	if [[ -n $ZSH_VERSION ]]; then
 		emulate -L bash
 		setopt KSH_TYPESET
 	fi
 
 	__git_has_doubledash && return
 
-	local cur="${COMP_WORDS[COMP_CWORD]}"
+	local cur
 	local g="$(__gitdir)"
 	local merge=""
 	if [ -f "$g/MERGE_HEAD" ]; then
 		merge="--merge"
 	fi
+	_get_comp_words_by_ref cur
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -2657,7 +2714,7 @@ complete -o bashdefault -o default -o nospace -F _git git.exe 2>/dev/null \
 	|| complete -o default -o nospace -F _git git.exe
 fi
 
-if [[ -n ${ZSH_VERSION-} ]]; then
+if [[ -n $ZSH_VERSION ]]; then
 	shopt () {
 		local option
 		if [ $# -ne 2 ]; then
-- 
1.7.3.2

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v3/RFC 1/2] Introduce functions from bash-completion project.
  2010-10-30 20:42 ` [PATCH v3/RFC 1/2] Introduce functions from bash-completion project Peter van der Does
@ 2010-11-01 13:35   ` Marc Branchaud
  0 siblings, 0 replies; 4+ messages in thread
From: Marc Branchaud @ 2010-11-01 13:35 UTC (permalink / raw)
  To: Peter van der Does
  Cc: Shawn O. Pearce, git, SZEDER Gábor, Jonathan Nieder,
	Brian Gernhardt, Kevin Ballard, Mathias Lafeldt

On 10-10-30 04:42 PM, Peter van der Does wrote:
> The completion script does not work as expected under Bash 4.
> Bash: 3
> output:
> $ git log --pretty=<tab><tab>
> email     full      medium    raw
> format:   fuller    oneline   short
> 
> Bash: 4
> output:
> $ git log --pretty=<tab><tab>
> .bash_logout         .local/
> .bash_profile        Music/
> --More--
> 
> With Bash 4 the way word breaking is done in the programmable completion
> code has changed. The documentation at the bash project is not very
> clear what was changed, the only reference found is in the NEWS section:
> 
> i.  The programmable completion code now uses the same set of characters
> as readline when breaking the command line into a list of words.
> 
> The word breaking problem occurs with certain characters, like double
> colon and equal sign.

Nit: "double colon" is "::" -- the name of the character is just "colon".

		M.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-11-01 13:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-30 20:42 [PATCH v3/RFC 0/2] Make git-completion Bash 4 compatible Peter van der Does
2010-10-30 20:42 ` [PATCH v3/RFC 1/2] Introduce functions from bash-completion project Peter van der Does
2010-11-01 13:35   ` Marc Branchaud
2010-10-30 20:42 ` [PATCH v3/RFC 2/2] Use the new functions to get the current cword Peter van der Does

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).