{"thread":{"id":"25562","subject":"[PATCH v2/RFC] Make git-completion Bash 4 compatible.","startedAt":"2010-10-27T17:15:06Z","lastAt":"2010-10-28T18:46:49Z","messageCount":11,"participants":["Peter van der Does","Brian Gernhardt","Jonathan Nieder","SZEDER Gábor","Jakub Narebski"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"154556","messageId":"20101027131506.4da06c6d@MonteCarlo","threadId":"25562","inReplyTo":null,"subject":"[PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Peter van der Does","fromEmail":"peter@avirtualhome.com","sentAt":"2010-10-27T17:15:06Z","receivedAt":"2010-10-27T17:15:06Z","isPatch":true,"sender":{"key":"peter@avirtualhome.com","avatar":"https://avatars.githubusercontent.com/u/380071?v=4"},"body":"\nThe completion script does not work as expected under Bash 4.\nBash: 3\noutput:\n$ git log --pretty=<tab><tab>\nemail     full      medium    raw\nformat:   fuller    oneline   short\n\nBash: 4\noutput:\n$ git log --pretty=<tab><tab>\n.bash_logout         .local/\n.bash_profile        Music/\n--More--\n\nSigned-off-by: Peter van der Does <peter@avirtualhome.com>\n---\nUpdated patch to play along with latest maint branch. It broke after the patch \nml/completion-zsh was implemented.\nRemoved some debugging code from the patch.\n\n contrib/completion/git-completion.bash |  417 +++++++++++++++++++++++++++-----\n 1 files changed, 355 insertions(+), 62 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 64341d5..85fb0f1 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -76,12 +76,251 @@\n #\n #       git@vger.kernel.org\n #\n+# Updated for Bash 4.0\n \n case \"$COMP_WORDBREAKS\" in\n *:*) : great ;;\n *)   COMP_WORDBREAKS=\"$COMP_WORDBREAKS:\"\n esac\n \n+# If the function _get_comp_words_by_ref does not exists, we can assume the\n+# bash_completion 1.2 script isn't loaded and therefor we're defining the\n+# necessary functions ourselves.\n+if ! type _get_comp_words_by_ref &> /dev/null ; then\n+\t# Assign variable one scope above the caller\n+\t# Usage: local \"$1\" && _upvar $1 \"value(s)\"\n+\t# Param: $1  Variable name to assign value to\n+\t# Param: $*  Value(s) to assign.  If multiple values, an array is\n+\t#            assigned, otherwise a single value is assigned.\n+\t# NOTE: For assigning multiple variables, use '_upvars'.  Do NOT\n+\t#       use multiple '_upvar' calls, since one '_upvar' call might\n+\t#       reassign a variable to be used by another '_upvar' call.\n+\t# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference\n+\t_upvar() {\n+\t\tif unset -v \"$1\"; then           # Unset & validate varname\n+\t        if (( $# == 2 )); then\n+\t            eval $1=\\\"\\$2\\\"          # Return single value\n+\t        else\n+\t            eval $1=\\(\\\"\\${@:2}\\\"\\)  # Return array\n+\t        fi\n+\t    fi\n+\t}\n+\n+\n+\t# Assign variables one scope above the caller\n+\t# Usage: local varname [varname ...] &&\n+\t#        _upvars [-v varname value] | [-aN varname [value ...]] ...\n+\t# Available OPTIONS:\n+\t#     -aN  Assign next N values to varname as array\n+\t#     -v   Assign single value to varname\n+\t# Return: 1 if error occurs\n+\t# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference\n+\t_upvars() {\n+\t    if ! (( $# )); then\n+\t        echo \"${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname\"\\\n+\t            \"value] | [-aN varname [value ...]] ...\" 1>&2\n+\t        return 2\n+\t    fi\n+\t    while (( $# )); do\n+\t        case $1 in\n+\t            -a*)\n+\t                # Error checking\n+\t                [[ ${1#-a} ]] || { echo \"bash: ${FUNCNAME[0]}: \\`$1': missing\"\\\n+\t                    \"number specifier\" 1>&2; return 1; }\n+\t                printf %d \"${1#-a}\" &> /dev/null || { echo \"bash:\"\\\n+\t                    \"${FUNCNAME[0]}: \\`$1': invalid number specifier\" 1>&2\n+\t                    return 1; }\n+\t                # Assign array of -aN elements\n+\t                [[ \"$2\" ]] && unset -v \"$2\" && eval $2=\\(\\\"\\${@:3:${1#-a}}\\\"\\) &&\n+\t                shift $((${1#-a} + 2)) || { echo \"bash: ${FUNCNAME[0]}:\"\\\n+\t                    \"\\`$1${2+ }$2': missing argument(s)\" 1>&2; return 1; }\n+\t                ;;\n+\t            -v)\n+\t                # Assign single value\n+\t                [[ \"$2\" ]] && unset -v \"$2\" && eval $2=\\\"\\$3\\\" &&\n+\t                shift 3 || { echo \"bash: ${FUNCNAME[0]}: $1: missing\"\\\n+\t                \"argument(s)\" 1>&2; return 1; }\n+\t                ;;\n+\t            *)\n+\t                echo \"bash: ${FUNCNAME[0]}: $1: invalid option\" 1>&2\n+\t                return 1 ;;\n+\t        esac\n+\t    done\n+\t}\n+\n+\n+\t# Reassemble command line words, excluding specified characters from the\n+\t# list of word completion separators (COMP_WORDBREAKS).\n+\t# @param $1 chars  Characters out of $COMP_WORDBREAKS which should\n+\t#     NOT be considered word breaks. This is useful for things like scp where\n+\t#     we want to return host:path and not only path, so we would pass the\n+\t#     colon (:) as $1 here.\n+\t# @param $2 words  Name of variable to return words to\n+\t# @param $3 cword  Name of variable to return cword to\n+\t#\n+\t__reassemble_comp_words_by_ref() {\n+\t    local exclude i j ref\n+\t    # Exclude word separator characters?\n+\t    if [[ $1 ]]; then\n+\t        # Yes, exclude word separator characters;\n+\t        # Exclude only those characters, which were really included\n+\t        exclude=\"${1//[^$COMP_WORDBREAKS]}\"\n+\t    fi\n+\n+\t    # Default to cword unchanged\n+\t    eval $3=$COMP_CWORD\n+\t    # Are characters excluded which were former included?\n+\t    if [[ $exclude ]]; then\n+\t        # Yes, list of word completion separators has shrunk;\n+\t        # Re-assemble words to complete\n+\t        for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n+\t            # Is current word not word 0 (the command itself) and is word not\n+\t            # empty and is word made up of just word separator characters to be\n+\t            # excluded?\n+\t            while [[ $i -gt 0 && ${COMP_WORDS[$i]} &&\n+\t                ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]}\n+\t            ]]; do\n+\t                [ $j -ge 2 ] && ((j--))\n+\t                # Append word separator to current word\n+\t                ref=\"$2[$j]\"\n+\t                eval $2[$j]=\\${!ref}\\${COMP_WORDS[i]}\n+\t                # Indicate new cword\n+\t                [ $i = $COMP_CWORD ] && eval $3=$j\n+\t                # Indicate next word if available, else end *both* while and for loop\n+\t                (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2\n+\t            done\n+\t            # Append word to current word\n+\t            ref=\"$2[$j]\"\n+\t            eval $2[$j]=\\${!ref}\\${COMP_WORDS[i]}\n+\t            # Indicate new cword\n+\t            [ $i = $COMP_CWORD ] && [[ ${COMP_WORDS[i]} ]] && eval $3=$j\n+\t        done\n+\t    else\n+\t        # No, list of word completions separators hasn't changed;\n+\t        eval $2=\\( \\\"\\${COMP_WORDS[@]}\\\" \\)\n+\t    fi\n+\t} # __reassemble_comp_words_by_ref()\n+\n+\t# @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be\n+\t#     considered word breaks. This is useful for things like scp where\n+\t#     we want to return host:path and not only path, so we would pass the\n+\t#     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this\n+\t#     ensures we get the same word on both bash-3 and bash-4.\n+\t# @param $2 words  Name of variable to return words to\n+\t# @param $3 cword  Name of variable to return cword to\n+\t# @param $4 cur  Name of variable to return current word to complete to\n+\t# @see ___get_cword_at_cursor_by_ref()\n+\t__get_cword_at_cursor_by_ref() {\n+\t    local cword words=()\n+\t    __reassemble_comp_words_by_ref \"$1\" words cword\n+\n+\t    local i cur2\n+\t    local cur=\"$COMP_LINE\"\n+\t    local index=\"$COMP_POINT\"\n+\t    for (( i = 0; i <= cword; ++i )); do\n+\t        while [[\n+\t            # Current word fits in $cur?\n+\t            \"${#cur}\" -ge ${#words[i]} &&\n+\t            # $cur doesn't match cword?\n+\t            \"${cur:0:${#words[i]}}\" != \"${words[i]}\"\n+\t        ]]; do\n+\t            # Strip first character\n+\t            cur=\"${cur:1}\"\n+\t            # Decrease cursor position\n+\t            ((index--))\n+\t        done\n+\n+\t        # Does found word matches cword?\n+\t        if [[ \"$i\" -lt \"$cword\" ]]; then\n+\t            # No, cword lies further;\n+\t            local old_size=\"${#cur}\"\n+\t            cur=\"${cur#${words[i]}}\"\n+\t            local new_size=\"${#cur}\"\n+\t            index=$(( index - old_size + new_size ))\n+\t        fi\n+\t    done\n+\n+\t    if [[ \"${words[cword]:0:${#cur}}\" != \"$cur\" ]]; then\n+\t        # We messed up. At least return the whole word so things keep working\n+\t        cur2=${words[cword]}\n+\t    else\n+\t        cur2=${cur:0:$index}\n+\t    fi\n+\n+\t    local \"$2\" \"$3\" \"$4\" &&\n+\t        _upvars -a${#words[@]} $2 \"${words[@]}\" -v $3 \"$cword\" -v $4 \"$cur2\"\n+\t}\n+\n+\n+\t# Get the word to complete and optional previous words.\n+\t# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases\n+\t# where the user is completing in the middle of a word.\n+\t# (For example, if the line is \"ls foobar\",\n+\t# and the cursor is here -------->   ^\n+\t# Also one is able to cross over possible wordbreak characters.\n+\t# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]\n+\t# Available VARNAMES:\n+\t#     cur         Return cur via $cur\n+\t#     prev        Return prev via $prev\n+\t#     words       Return words via $words\n+\t#     cword       Return cword via $cword\n+\t#\n+\t# Available OPTIONS:\n+\t#     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be\n+\t#                 considered word breaks. This is useful for things like scp\n+\t#                 where we want to return host:path and not only path, so we\n+\t#                 would pass the colon (:) as -n option in this case.  Bash-3\n+\t#                 doesn't do word splitting, so this ensures we get the same\n+\t#                 word on both bash-3 and bash-4.\n+\t#     -c VARNAME  Return cur via $VARNAME\n+\t#     -p VARNAME  Return prev via $VARNAME\n+\t#     -w VARNAME  Return words via $VARNAME\n+\t#     -i VARNAME  Return cword via $VARNAME\n+\t#\n+\t# Example usage:\n+\t#\n+\t#    $ _get_comp_words_by_ref -n : cur prev\n+\t#\n+\t_get_comp_words_by_ref()\n+\t{\n+\t    local exclude flag i OPTIND=1\n+\t    local cur cword words=()\n+\t    local upargs=() upvars=() vcur vcword vprev vwords\n+\n+\t    while getopts \"c:i:n:p:w:\" flag \"$@\"; do\n+\t        case $flag in\n+\t            c) vcur=$OPTARG ;;\n+\t            i) vcword=$OPTARG ;;\n+\t            n) exclude=$OPTARG ;;\n+\t            p) vprev=$OPTARG ;;\n+\t            w) vwords=$OPTARG ;;\n+\t        esac\n+\t    done\n+\t    while [[ $# -ge $OPTIND ]]; do\n+\t        case ${!OPTIND} in\n+\t            cur)   vcur=cur ;;\n+\t            prev)  vprev=prev ;;\n+\t            cword) vcword=cword ;;\n+\t            words) vwords=words ;;\n+\t            *) echo \"bash: $FUNCNAME(): \\`${!OPTIND}': unknown argument\" \\\n+\t                1>&2; return 1\n+\t        esac\n+\t        let \"OPTIND += 1\"\n+\t    done\n+\n+\t    __get_cword_at_cursor_by_ref \"$exclude\" words cword cur\n+\n+\t    [[ $vcur   ]] && { upvars+=(\"$vcur\"  ); upargs+=(-v $vcur   \"$cur\"  ); }\n+\t    [[ $vcword ]] && { upvars+=(\"$vcword\"); upargs+=(-v $vcword \"$cword\"); }\n+\t    [[ $vprev  ]] && { upvars+=(\"$vprev\" ); upargs+=(-v $vprev\n+\t        \"${words[cword - 1]}\"); }\n+\t    [[ $vwords ]] && { upvars+=(\"$vwords\"); upargs+=(-a${#words[@]} $vwords\n+\t        \"${words[@]}\"); }\n+\n+\t    (( ${#upvars[@]} )) && local \"${upvars[@]}\" && _upvars \"${upargs[@]}\"\n+\t}\n+fi\n+\n # __gitdir accepts 0 or 1 arguments (i.e., location)\n # returns location of .git repo\n __gitdir ()\n@@ -331,7 +570,8 @@ __gitcomp_1 ()\n # generates completion reply with compgen\n __gitcomp ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tif [ $# -gt 2 ]; then\n \t\tcur=\"$3\"\n \tfi\n@@ -390,7 +630,8 @@ __git_tags ()\n __git_refs ()\n {\n \tlocal i is_hash=y dir=\"$(__gitdir \"${1-}\")\"\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\" format refs\n+\tlocal cur format refs\n+\t_get_comp_words_by_ref cur\n \tif [ -d \"$dir\" ]; then\n \t\tcase \"$cur\" in\n \t\trefs|refs/*)\n@@ -488,7 +729,8 @@ __git_compute_merge_strategies ()\n \n __git_complete_file ()\n {\n-\tlocal pfx ls ref cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal pfx ls ref cur\n+\t_get_comp_words_by_ref -n \":\" cur\n \tcase \"$cur\" in\n \t?*:*)\n \t\tref=\"${cur%%:*}\"\n@@ -536,7 +778,8 @@ __git_complete_file ()\n \n __git_complete_revlist ()\n {\n-\tlocal pfx cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal pfx cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t*...*)\n \t\tpfx=\"${cur%...*}...\"\n@@ -556,11 +799,14 @@ __git_complete_revlist ()\n \n __git_complete_remote_or_refspec ()\n {\n-\tlocal cmd=\"${COMP_WORDS[1]}\"\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal git_comp_words git_comp_cword\n+\t__reassemble_comp_words_by_ref : git_comp_words git_comp_cword\n+\tlocal cmd=\"${git_comp_words[1]}\"\n+\tlocal cur\n \tlocal i c=2 remote=\"\" pfx=\"\" lhs=1 no_complete_refspec=0\n-\twhile [ $c -lt $COMP_CWORD ]; do\n-\t\ti=\"${COMP_WORDS[c]}\"\n+\t_get_comp_words_by_ref -n \":\" cur\n+\twhile [ $c -lt $git_comp_cword ]; do\n+\t\ti=\"${git_comp_words[c]}\"\n \t\tcase \"$i\" in\n \t\t--mirror) [ \"$cmd\" = \"push\" ] && no_complete_refspec=1 ;;\n \t\t--all)\n@@ -628,13 +874,15 @@ __git_complete_remote_or_refspec ()\n \n __git_complete_strategy ()\n {\n+\tlocal cur prev\n+\t_get_comp_words_by_ref -n \"=\" cur prev\n \t__git_compute_merge_strategies\n-\tcase \"${COMP_WORDS[COMP_CWORD-1]}\" in\n+\tcase \"${prev}\" in\n \t-s|--strategy)\n \t\t__gitcomp \"$__git_merge_strategies\"\n \t\treturn 0\n \tesac\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\n \tcase \"$cur\" in\n \t--strategy=*)\n \t\t__gitcomp \"$__git_merge_strategies\" \"\" \"${cur##--strategy=}\"\n@@ -824,7 +1072,10 @@ __git_whitespacelist=\"nowarn warn error error-all fix\"\n \n _git_am ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\" dir=\"$(__gitdir)\"\n+\tlocal cur\n+\tlocal dir=\"$(__gitdir)\"\n+\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tif [ -d \"$dir\"/rebase-apply ]; then\n \t\t__gitcomp \"--skip --continue --resolved --abort\"\n \t\treturn\n@@ -848,7 +1099,8 @@ _git_am ()\n \n _git_apply ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--whitespace=*)\n \t\t__gitcomp \"$__git_whitespacelist\" \"\" \"${cur##--whitespace=}\"\n@@ -871,7 +1123,8 @@ _git_add ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -885,7 +1138,8 @@ _git_add ()\n \n _git_archive ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--format=*)\n \t\t__gitcomp \"$(git archive --list)\" \"\" \"${cur##--format=}\"\n@@ -929,7 +1183,8 @@ _git_bisect ()\n \n _git_branch ()\n {\n-\tlocal i c=1 only_local_ref=\"n\" has_r=\"n\"\n+\tlocal i c=1 only_local_ref=\"n\" has_r=\"n\", cur\n+\t_get_comp_words_by_ref cur\n \n \twhile [ $c -lt $COMP_CWORD ]; do\n \t\ti=\"${COMP_WORDS[c]}\"\n@@ -940,7 +1195,7 @@ _git_branch ()\n \t\tc=$((++c))\n \tdone\n \n-\tcase \"${COMP_WORDS[COMP_CWORD]}\" in\n+\tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n \t\t\t--color --no-color --verbose --abbrev= --no-abbrev\n@@ -982,7 +1237,8 @@ _git_checkout ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--conflict=*)\n \t\t__gitcomp \"diff3 merge\" \"\" \"${cur##--conflict=}\"\n@@ -1006,7 +1262,8 @@ _git_cherry ()\n \n _git_cherry_pick ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--edit --no-commit\"\n@@ -1021,7 +1278,8 @@ _git_clean ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--dry-run --quiet\"\n@@ -1033,7 +1291,8 @@ _git_clean ()\n \n _git_clone ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -1060,7 +1319,8 @@ _git_commit ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--cleanup=*)\n \t\t__gitcomp \"default strip verbatim whitespace\n@@ -1095,7 +1355,8 @@ _git_commit ()\n \n _git_describe ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -1127,7 +1388,8 @@ _git_diff ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--cached --staged --pickaxe-all --pickaxe-regex\n@@ -1148,7 +1410,8 @@ _git_difftool ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--tool=*)\n \t\t__gitcomp \"$__git_mergetools_common kompare\" \"\" \"${cur##--tool=}\"\n@@ -1173,7 +1436,8 @@ __git_fetch_options=\"\n \n _git_fetch ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"$__git_fetch_options\"\n@@ -1185,7 +1449,8 @@ _git_fetch ()\n \n _git_format_patch ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--thread=*)\n \t\t__gitcomp \"\n@@ -1217,7 +1482,8 @@ _git_format_patch ()\n \n _git_fsck ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -1232,7 +1498,8 @@ _git_fsck ()\n \n _git_gc ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--prune --aggressive\"\n@@ -1251,7 +1518,8 @@ _git_grep ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -1274,7 +1542,8 @@ _git_grep ()\n \n _git_help ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--all --info --man --web\"\n@@ -1292,7 +1561,8 @@ _git_help ()\n \n _git_init ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--shared=*)\n \t\t__gitcomp \"\n@@ -1312,7 +1582,8 @@ _git_ls_files ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--cached --deleted --modified --others --ignored\n@@ -1366,7 +1637,8 @@ _git_log ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tlocal g=\"$(git rev-parse --git-dir 2>/dev/null)\"\n \tlocal merge=\"\"\n \tif [ -f \"$g/MERGE_HEAD\" ]; then\n@@ -1425,7 +1697,8 @@ _git_merge ()\n {\n \t__git_complete_strategy && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"$__git_merge_options\"\n@@ -1436,7 +1709,8 @@ _git_merge ()\n \n _git_mergetool ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--tool=*)\n \t\t__gitcomp \"$__git_mergetools_common tortoisemerge\" \"\" \"${cur##--tool=}\"\n@@ -1457,7 +1731,8 @@ _git_merge_base ()\n \n _git_mv ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--dry-run\"\n@@ -1494,7 +1769,8 @@ _git_pull ()\n {\n \t__git_complete_strategy && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -1510,8 +1786,9 @@ _git_pull ()\n \n _git_push ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n-\tcase \"${COMP_WORDS[COMP_CWORD-1]}\" in\n+\tlocal cur prev\n+\t_get_comp_words_by_ref -n \"=\" cur prev\n+\tcase \"$prev\" in\n \t--repo)\n \t\t__gitcomp \"$(__git_remotes)\"\n \t\treturn\n@@ -1534,7 +1811,9 @@ _git_push ()\n \n _git_rebase ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\" dir=\"$(__gitdir)\"\n+\tlocal cur\n+\tlocal dir=\"$(__gitdir)\"\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tif [ -d \"$dir\"/rebase-apply ] || [ -d \"$dir\"/rebase-merge ]; then\n \t\t__gitcomp \"--continue --skip --abort\"\n \t\treturn\n@@ -1564,7 +1843,8 @@ __git_send_email_suppresscc_options=\"author self cc bodycc sob cccmd body all\"\n \n _git_send_email ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--confirm=*)\n \t\t__gitcomp \"\n@@ -1606,9 +1886,11 @@ _git_stage ()\n \n __git_config_get_set_variables ()\n {\n-\tlocal prevword word config_file= c=$COMP_CWORD\n+\tlocal prevword word config_file= c\n+\tlocal git_comp_words\n+\t__reassemble_comp_words_by_ref = git_comp_words c\n \twhile [ $c -gt 1 ]; do\n-\t\tword=\"${COMP_WORDS[c]}\"\n+\t\tword=\"${git_comp_words[c]}\"\n \t\tcase \"$word\" in\n \t\t--global|--system|--file=*)\n \t\t\tconfig_file=\"$word\"\n@@ -1636,9 +1918,9 @@ __git_config_get_set_variables ()\n \n _git_config ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n-\tlocal prv=\"${COMP_WORDS[COMP_CWORD-1]}\"\n-\tcase \"$prv\" in\n+\tlocal cur prev\n+\t_get_comp_words_by_ref cur prev\n+\tcase \"$prev\" in\n \tbranch.*.remote)\n \t\t__gitcomp \"$(__git_remotes)\"\n \t\treturn\n@@ -1648,13 +1930,13 @@ _git_config ()\n \t\treturn\n \t\t;;\n \tremote.*.fetch)\n-\t\tlocal remote=\"${prv#remote.}\"\n+\t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.fetch}\"\n \t\t__gitcomp \"$(__git_refs_remotes \"$remote\")\"\n \t\treturn\n \t\t;;\n \tremote.*.push)\n-\t\tlocal remote=\"${prv#remote.}\"\n+\t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.push}\"\n \t\t__gitcomp \"$(git --git-dir=\"$(__gitdir)\" \\\n \t\t\tfor-each-ref --format='%(refname):%(refname)' \\\n@@ -2045,7 +2327,8 @@ _git_reset ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--merge --mixed --hard --soft --patch\"\n@@ -2057,7 +2340,8 @@ _git_reset ()\n \n _git_revert ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--edit --mainline --no-edit --no-commit --signoff\"\n@@ -2071,7 +2355,8 @@ _git_rm ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur=\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"--cached --dry-run --ignore-unmatch --quiet\"\n@@ -2085,7 +2370,8 @@ _git_shortlog ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -2103,7 +2389,8 @@ _git_show ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref -n \"=\" cur\n \tcase \"$cur\" in\n \t--pretty=*)\n \t\t__gitcomp \"$__git_log_pretty_formats\n@@ -2127,7 +2414,8 @@ _git_show ()\n \n _git_show_branch ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n@@ -2144,10 +2432,11 @@ _git_show_branch ()\n \n _git_stash ()\n {\n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n \tlocal save_opts='--keep-index --no-keep-index --quiet --patch'\n \tlocal subcommands='save list show apply clear drop pop create branch'\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n+\t_get_comp_words_by_ref cur\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n \t\t--*)\n@@ -2189,7 +2478,8 @@ _git_submodule ()\n \n \tlocal subcommands=\"add status init update summary foreach sync\"\n \tif [ -z \"$(__git_find_on_cmdline \"$subcommands\")\" ]; then\n-\t\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\t\tlocal cur\n+\t\t_get_comp_words_by_ref cur\n \t\tcase \"$cur\" in\n \t\t--*)\n \t\t\t__gitcomp \"--quiet --cached\"\n@@ -2233,7 +2523,8 @@ _git_svn ()\n \t\t\t--edit --rmdir --find-copies-harder --copy-similarity=\n \t\t\t\"\n \n-\t\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\t\tlocal cur\n+\t\t_get_comp_words_by_ref cur\n \t\tcase \"$subcommand,$cur\" in\n \t\tfetch,--*)\n \t\t\t__gitcomp \"--revision= --fetch-all $fc_opts\"\n@@ -2343,15 +2634,16 @@ _git_whatchanged ()\n \n _git ()\n {\n-\tlocal i c=1 command __git_dir\n+\tlocal i c=1 command __git_dir git_comp_words git_comp_cword\n \n \tif [[ -n $ZSH_VERSION ]]; then\n \t\temulate -L bash\n \t\tsetopt KSH_TYPESET\n \tfi\n \n-\twhile [ $c -lt $COMP_CWORD ]; do\n-\t\ti=\"${COMP_WORDS[c]}\"\n+\t__reassemble_comp_words_by_ref = git_comp_words git_comp_cword\n+\twhile [ $c -lt $git_comp_cword ]; do\n+\t\ti=\"${git_comp_words[c]}\"\n \t\tcase \"$i\" in\n \t\t--git-dir=*) __git_dir=\"${i#--git-dir=}\" ;;\n \t\t--bare)      __git_dir=\".\" ;;\n@@ -2363,7 +2655,7 @@ _git ()\n \tdone\n \n \tif [ -z \"$command\" ]; then\n-\t\tcase \"${COMP_WORDS[COMP_CWORD]}\" in\n+\t\tcase \"${git_comp_words[git_comp_cword]}\" in\n \t\t--*)   __gitcomp \"\n \t\t\t--paginate\n \t\t\t--no-pager\n@@ -2401,12 +2693,13 @@ _gitk ()\n \n \t__git_has_doubledash && return\n \n-\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal cur\n \tlocal g=\"$(__gitdir)\"\n \tlocal merge=\"\"\n \tif [ -f \"$g/MERGE_HEAD\" ]; then\n \t\tmerge=\"--merge\"\n \tfi\n+\t_get_comp_words_by_ref cur\n \tcase \"$cur\" in\n \t--*)\n \t\t__gitcomp \"\n-- \n1.7.3.2\n\n\n-- \nPeter van der Does\n\nGPG key: E77E8E98\n\nIRC: Ganseki on irc.freenode.net\nTwitter: @petervanderdoes\n"},{"id":"154558","messageId":"091B05F5-D5F4-4DD6-90AF-E0BD77700326@gernhardtsoftware.com","threadId":"25562","inReplyTo":"20101027131506.4da06c6d@MonteCarlo","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Brian Gernhardt","fromEmail":"brian@gernhardtsoftware.com","sentAt":"2010-10-27T17:23:27Z","receivedAt":"2010-10-27T17:23:27Z","isPatch":true,"sender":{"key":"brian@gernhardtsoftware.com","avatar":"https://avatars.githubusercontent.com/u/133455?v=4"},"body":"\nOn Oct 27, 2010, at 1:15 PM, Peter van der Does wrote:\n\n> contrib/completion/git-completion.bash |  417 +++++++++++++++++++++++++++-----\n> 1 files changed, 355 insertions(+), 62 deletions(-)\n\nThat's a lot of added lines?  Do we use all of this code?  If not, should we trim it down just to support the features we need?\n\nAlso, there appears to be no note in the code or commit message that this came from somewhere else.  Shouldn't we note the source of the code?  Is bash-completion GPLv2 as we are?\n\n> +\t_upvar() {\n> +\t\tif unset -v \"$1\"; then           # Unset & validate varname\n\nNit: This should be indented one less level.\n\n> +\t        if (( $# == 2 )); then\n> +\t            eval $1=\\\"\\$2\\\"          # Return single value\n> +\t        else\n> +\t            eval $1=\\(\\\"\\${@:2}\\\"\\)  # Return array\n> +\t        fi\n> +\t    fi\n> +\t}\n> +\n\nOther than those concerns, I like it.  Good call not trying to redefine the functions from bash-completion if it's loaded already.\n\n~~ Brian\n"},{"id":"154559","messageId":"20101027173132.GA15657@burratino","threadId":"25562","inReplyTo":"20101027131506.4da06c6d@MonteCarlo","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-27T17:31:32Z","receivedAt":"2010-10-27T17:31:32Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi Peter,\n\nPeter van der Does wrote:\n\n> The completion script does not work as expected under Bash 4.\n\nThanks for your work fixing this.  That's awesome.\n\nIt would be ideal if someone could write or find a nice summary of the\nproblem and the chosen solution, for inclusion in the commit message.\n\nCould some zsh user perhaps test that the new zsh support is not\nbroken?\n\n>  1 files changed, 355 insertions(+), 62 deletions(-)\n\nKind of unfortunate.  There are a lot of comments, but still...\n\n> --- a/contrib/completion/git-completion.bash\n> +++ b/contrib/completion/git-completion.bash\n> @@ -76,12 +76,251 @@\n>  #\n>  #       git@vger.kernel.org\n>  #\n> +# Updated for Bash 4.0\n\nI don't think this comment will be so important for posterity (e.g., once\nbash 5 comes around ;-)).\n\n[...]\n> +# If the function _get_comp_words_by_ref does not exists, we can assume the\n> +# bash_completion 1.2 script isn't loaded and therefor we're defining the\n> +# necessary functions ourselves.\n\nProbably this explanation belongs in the commit message?  A comment\ncould provide a brief reminder, like:\n\n\tif ! type _get_comp_words_by_ref &>/dev/null ; then\n\t\t# The bash_completion 1.2 library was not loaded,\n\t\t# so we have to define some functions from it ourselves.\n\nAre the implementations taken from bash_completion?  If so, that would\nbe very useful information for the log message: future readers may\nwant to know where to look for a more recent version.\n\n> +\t# Assign variable one scope above the caller\n[... I'm assuming this is all written correctly, etc ...]\n\n> @@ -331,7 +570,8 @@ __gitcomp_1 ()\n>  # generates completion reply with compgen\n>  __gitcomp ()\n>  {\n> -\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n> +\tlocal cur\n> +\t_get_comp_words_by_ref -n \"=\" cur\n[...]\n\nThe rest looks sane.  Maybe it would make sense to split this into two\npatches for readability:\n\n - one to introduce the _get_comp_words_by_ref function\n - one to use it\n\n?\n"},{"id":"154587","messageId":"20101027223918.GA1877@neumann","threadId":"25562","inReplyTo":"20101027131506.4da06c6d@MonteCarlo","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2010-10-27T22:39:18Z","receivedAt":"2010-10-27T22:39:18Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Hi,\n\nOn Wed, Oct 27, 2010 at 01:15:06PM -0400, Peter van der Does wrote:\n> The completion script does not work as expected under Bash 4.\n\nThank you.  I applied your patch to play around a bit, and it seems to\nwork (but, of course, I have not tried all the affected commands).\n\nI agree with the comments and suggestiong of Brian and Jonathan.  The\ncurrent commit message covers only the symptoms of a bug this patch\nattempts to fix, but it should also explain its cause and how the\npatch is supposed to fix it.  Unfortunately, I can only comment on the\nlatter: if these new functions are good enough for the folks over at\nbash-completion project, then they should be good enough for us (;\n\nI'm still puzzled that the only relevant entry I could find in the\nbash NEWS file is:\n\ni.  The programmable completion code now uses the same set of characters as\n    readline when breaking the command line into a list of words.\n\nYet, as I mentioned in one of the previous threads, I have two\nmachines with different bash versions (3.2 and 4.1) but with the exact\nsame set of characters in COMP_WORDBREAKS, and they show different\nbehavior.\n\n> Bash: 3\n> output:\n> $ git log --pretty=<tab><tab>\n> email     full      medium    raw\n> format:   fuller    oneline   short\n> \n> Bash: 4\n> output:\n> $ git log --pretty=<tab><tab>\n> .bash_logout         .local/\n> .bash_profile        Music/\n> --More--\n> \n> Signed-off-by: Peter van der Does <peter@avirtualhome.com>\n\n\n> @@ -556,11 +799,14 @@ __git_complete_revlist ()\n>  \n>  __git_complete_remote_or_refspec ()\n>  {\n> -\tlocal cmd=\"${COMP_WORDS[1]}\"\n> -\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n> +\tlocal git_comp_words git_comp_cword\n> +\t__reassemble_comp_words_by_ref : git_comp_words git_comp_cword\n\nI suggest using '_get_comp_words_by_ref -n \":\" words cword' here.\nFirst, for consistency's sake, because you use\n_get_comp_words_by_ref() everywhere else, too (almost).  Second, I'm\nworried about the double underscore prefix in the function name,\nbecause it usually indicates something that is not supposed to be used\ndirectly from outside.  Even the bash-completion project's scripts\nprefer _get_comp_words_by_ref() to __reassemble_comp_words_by_ref().\nAnd third, ...\n\n> +\tlocal cmd=\"${git_comp_words[1]}\"\n> +\tlocal cur\n>  \tlocal i c=2 remote=\"\" pfx=\"\" lhs=1 no_complete_refspec=0\n> -\twhile [ $c -lt $COMP_CWORD ]; do\n> -\t\ti=\"${COMP_WORDS[c]}\"\n> +\t_get_comp_words_by_ref -n \":\" cur\n\n... you could then join this _get_comp_words_by_ref() invocation with\nthe one above.\n\n> +\twhile [ $c -lt $git_comp_cword ]; do\n> +\t\ti=\"${git_comp_words[c]}\"\n>  \t\tcase \"$i\" in\n>  \t\t--mirror) [ \"$cmd\" = \"push\" ] && no_complete_refspec=1 ;;\n>  \t\t--all)\n\n\n> @@ -824,7 +1072,10 @@ __git_whitespacelist=\"nowarn warn error error-all fix\"\n>  \n>  _git_am ()\n>  {\n> -\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\" dir=\"$(__gitdir)\"\n> +\tlocal cur\n> +\tlocal dir=\"$(__gitdir)\"\n\nYou could keep the two declarations in a single line.\n\n> +\n> +\t_get_comp_words_by_ref -n \"=\" cur\n>  \tif [ -d \"$dir\"/rebase-apply ]; then\n>  \t\t__gitcomp \"--skip --continue --resolved --abort\"\n>  \t\treturn\n\n\n> @@ -929,7 +1183,8 @@ _git_bisect ()\n>  \n>  _git_branch ()\n>  {\n> -\tlocal i c=1 only_local_ref=\"n\" has_r=\"n\"\n> +\tlocal i c=1 only_local_ref=\"n\" has_r=\"n\", cur\n\nThe comma before \"cur\" shouldn't be there.\n\n> +\t_get_comp_words_by_ref cur\n>  \n>  \twhile [ $c -lt $COMP_CWORD ]; do\n>  \t\ti=\"${COMP_WORDS[c]}\"\n\nHmph.\n\nI don't think there is anything that could go wrong here with respect\nto word breaking, but at least for consistency's sake you could query\nfor words and cword, too, and use ${words[cword]} here.\n\n\n> @@ -1006,7 +1262,8 @@ _git_cherry ()\n>  \n>  _git_cherry_pick ()\n>  {\n> -\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n> +\tlocal cur\n> +_get_comp_words_by_ref cur\n\nMissing indentation.\n\n>  \tcase \"$cur\" in\n>  \t--*)\n>  \t\t__gitcomp \"--edit --no-commit\"\n\n\n> @@ -1606,9 +1886,11 @@ _git_stage ()\n>  \n>  __git_config_get_set_variables ()\n>  {\n> -\tlocal prevword word config_file= c=$COMP_CWORD\n> +\tlocal prevword word config_file= c\n> +\tlocal git_comp_words\n> +\t__reassemble_comp_words_by_ref = git_comp_words c\n\nUse _get_comp_words_by_ref() instead.\n\n>  \twhile [ $c -gt 1 ]; do\n> -\t\tword=\"${COMP_WORDS[c]}\"\n> +\t\tword=\"${git_comp_words[c]}\"\n>  \t\tcase \"$word\" in\n>  \t\t--global|--system|--file=*)\n>  \t\t\tconfig_file=\"$word\"\n\n\n> @@ -2045,7 +2327,8 @@ _git_reset ()\n>  {\n>  \t__git_has_doubledash && return\n>  \n> -\tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n> +\tlocal cur\n> +_get_comp_words_by_ref cur\n\nMissing indentation.\n\n>  \tcase \"$cur\" in\n>  \t--*)\n>  \t\t__gitcomp \"--merge --mixed --hard --soft --patch\"\n\n\n> @@ -2343,15 +2634,16 @@ _git_whatchanged ()\n>  \n>  _git ()\n>  {\n> -\tlocal i c=1 command __git_dir\n> +\tlocal i c=1 command __git_dir git_comp_words git_comp_cword\n>  \n>  \tif [[ -n $ZSH_VERSION ]]; then\n>  \t\temulate -L bash\n>  \t\tsetopt KSH_TYPESET\n>  \tfi\n>  \n> -\twhile [ $c -lt $COMP_CWORD ]; do\n> -\t\ti=\"${COMP_WORDS[c]}\"\n> +\t__reassemble_comp_words_by_ref = git_comp_words git_comp_cword\n\nUse _get_comp_words_by_ref() instead.\n\n> +\twhile [ $c -lt $git_comp_cword ]; do\n> +\t\ti=\"${git_comp_words[c]}\"\n>  \t\tcase \"$i\" in\n>  \t\t--git-dir=*) __git_dir=\"${i#--git-dir=}\" ;;\n>  \t\t--bare)      __git_dir=\".\" ;;\n"},{"id":"154588","messageId":"20101027225318.GB1877@neumann","threadId":"25562","inReplyTo":"20101027173132.GA15657@burratino","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2010-10-27T22:53:18Z","receivedAt":"2010-10-27T22:53:18Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Hi Jonathan,\n\n\nOn Wed, Oct 27, 2010 at 12:31:32PM -0500, Jonathan Nieder wrote:\n> Could some zsh user perhaps test that the new zsh support is not\n> broken?\n\nI'm afraid it is.\n\nThe commit message of 06f44c3 (completion: make compatible with zsh,\n2010-09-06) says:\n\n    ${var:2}\n        Zsh does not implement ${var:2} to skip the first 2 characters, but\n        ${var#??} works in both shells to replace the first 2 characters\n        with nothing.  Thanks to Jonathan Nieder for the suggestion.\n\n    for (( n=1; \"$n\" ... ))\n        Zsh does not allow \"$var\" in arithmetic loops.  Instead, pre-compute\n        the endpoint and use the variables without $'s or quotes.\n\nHowever, the functions taken over from the bash-completion code\ncontain constructs like:\n\n    ${cur:0:$index}\n    # ok, this is not exactly the same as ${var:2}, so it might even\n    # work...\n\nand\n\n    for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n\nBut I haven't actually tried it.\n\n\nBest,\nGábor\n"},{"id":"154594","messageId":"20101028004835.GB31501@burratino","threadId":"25562","inReplyTo":"20101027223918.GA1877@neumann","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-28T00:48:35Z","receivedAt":"2010-10-28T00:48:35Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"SZEDER Gábor wrote:\n\n> I'm still puzzled that the only relevant entry I could find in the\n> bash NEWS file is:\n> \n> i.  The programmable completion code now uses the same set of characters as\n>     readline when breaking the command line into a list of words.\n\nHere's a note to the Debian bash maintainer on that subject:\n\n http://bugs.debian.org/601632\n\nI'm still too confused to come up with a documentation patch to send to\nbug-bash.\n"},{"id":"154596","messageId":"20101027205217.3f28b9d1@MonteCarlo","threadId":"25562","inReplyTo":"20101027225318.GB1877@neumann","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Peter van der Does","fromEmail":"peter@avirtualhome.com","sentAt":"2010-10-28T00:52:17Z","receivedAt":"2010-10-28T00:52:17Z","isPatch":true,"sender":{"key":"peter@avirtualhome.com","avatar":"https://avatars.githubusercontent.com/u/380071?v=4"},"body":"On Thu, 28 Oct 2010 00:53:18 +0200\nSZEDER Gábor <szeder@ira.uka.de> wrote:\n\n> Hi Jonathan,\n> \n> \n> On Wed, Oct 27, 2010 at 12:31:32PM -0500, Jonathan Nieder wrote:\n> > Could some zsh user perhaps test that the new zsh support is not\n> > broken?\n> \n> I'm afraid it is.\n> \n> The commit message of 06f44c3 (completion: make compatible with zsh,\n> 2010-09-06) says:\n> \n>     ${var:2}\n>         Zsh does not implement ${var:2} to skip the first 2\n> characters, but ${var#??} works in both shells to replace the first 2\n> characters with nothing.  Thanks to Jonathan Nieder for the\n> suggestion.\n> \n>     for (( n=1; \"$n\" ... ))\n>         Zsh does not allow \"$var\" in arithmetic loops.  Instead,\n> pre-compute the endpoint and use the variables without $'s or quotes.\n> \n> However, the functions taken over from the bash-completion code\n> contain constructs like:\n> \n>     ${cur:0:$index}\n>     # ok, this is not exactly the same as ${var:2}, so it might even\n>     # work...\n> \n> and\n> \n>     for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do\n> \n> But I haven't actually tried it.\n> \n> \n> Best,\n> Gábor\n> \nOn the zsh change, I replied to the email \"What's cooking in git.git\n(Oct 2010, #02; Tue, 26)\"\n\n> With the patch \"Make git-completion Bash 4 compatible\" in mind, it\n> might be useful to start looking into a different way to distribute\n> the completion script to accommodate different shells. Adding\n> compatibility for each shell into one script can get nasty. We could\n> have a different completion script for each shell.\n\nThe bash completion script could still be included with the core, but\nwe can offer different versions for different shells.\n\n-- \nPeter van der Does\n\nGPG key: E77E8E98\n\nIRC: Ganseki on irc.freenode.net\nTwitter: @petervanderdoes\n"},{"id":"154598","messageId":"20101028005455.GC31501@burratino","threadId":"25562","inReplyTo":"20101027205217.3f28b9d1@MonteCarlo","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-10-28T00:54:55Z","receivedAt":"2010-10-28T00:54:55Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Peter van der Does wrote:\n\n> The bash completion script could still be included with the core, but\n> we can offer different versions for different shells.\n\nWhy?  That's three times the maintenance work.\n"},{"id":"154626","messageId":"20101028081445.27cc603b@MonteCarlo","threadId":"25562","inReplyTo":"20101028005455.GC31501@burratino","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Peter van der Does","fromEmail":"peter@avirtualhome.com","sentAt":"2010-10-28T12:14:45Z","receivedAt":"2010-10-28T12:14:45Z","isPatch":true,"sender":{"key":"peter@avirtualhome.com","avatar":"https://avatars.githubusercontent.com/u/380071?v=4"},"body":"On Wed, 27 Oct 2010 19:54:55 -0500\nJonathan Nieder <jrnieder@gmail.com> wrote:\n\n> Peter van der Does wrote:\n> \n> > The bash completion script could still be included with the core,\n> > but we can offer different versions for different shells.\n> \n> Why?  That's three times the maintenance work.\n\nThe cons of everything in one script:\n- If the script needs an update the submitter has to take in account\n  the different coding standards each shell has. Examples of this have\n  been given in the commit message of 06f44c3 (completion: make\n  compatible with zsh, 2010-09-06)\n\n- The script could end up with a slew of if statements to see which\n  shell the script is running in and taking some action.\n\n- Shells don't share all the same functions, the script could be filled\n  with functions not needed in other shells. the zsh patch includes\n  one, the Bash 4 patch includes several.\n\nThe pros of everything in one script:\n- Small changes, like adding an extra option to a git command for\n  completion only have to implemented in one script.\n\n\nThe maintenance of the various scripts would be done by people who have\na full understanding of the shell for which the script is written\nfor.\nI kind of see this suggestion as building the git package for a Linux\ndistribution, Windows or Mac. Debian and Ubuntu have some patches\nthat are not included in the core to make git work better on those\ndistributions. The maintenance is done by the people who have in depth\nknowledge of that distribution.\n\n\n-- \nPeter van der Does\n\nGPG key: E77E8E98\n\nIRC: Ganseki on irc.freenode.net\nTwitter: @petervanderdoes\n"},{"id":"154638","messageId":"m31v7ai9c2.fsf@localhost.localdomain","threadId":"25562","inReplyTo":"20101028081445.27cc603b@MonteCarlo","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-28T16:15:45Z","receivedAt":"2010-10-28T16:15:45Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Peter van der Does <peter@avirtualhome.com> writes:\n> On Wed, 27 Oct 2010 19:54:55 -0500\n> Jonathan Nieder <jrnieder@gmail.com> wrote:\n> \n> > Peter van der Does wrote:\n> > \n> > > The bash completion script could still be included with the core,\n> > > but we can offer different versions for different shells.\n> > \n> > Why?  That's three times the maintenance work.\n> \n> The cons of everything in one script:\n> - If the script needs an update the submitter has to take in account\n>   the different coding standards each shell has. Examples of this have\n>   been given in the commit message of 06f44c3 (completion: make\n>   compatible with zsh, 2010-09-06)\n> \n> - The script could end up with a slew of if statements to see which\n>   shell the script is running in and taking some action.\n> \n> - Shells don't share all the same functions, the script could be filled\n>   with functions not needed in other shells. the zsh patch includes\n>   one, the Bash 4 patch includes several.\n> \n> The pros of everything in one script:\n> - Small changes, like adding an extra option to a git command for\n>   completion only have to implemented in one script.\n\nWhat about having separate scripts, but sourcing common library that\ndoesn't do completion, but just provides list of possible completions?\nThis would be best of both worlds, I think.\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"154661","messageId":"20101028144649.0f7b13b6@MonteCarlo","threadId":"25562","inReplyTo":"m31v7ai9c2.fsf@localhost.localdomain","subject":"Re: [PATCH v2/RFC] Make git-completion Bash 4 compatible.","fromName":"Peter van der Does","fromEmail":"peter@avirtualhome.com","sentAt":"2010-10-28T18:46:49Z","receivedAt":"2010-10-28T18:46:49Z","isPatch":true,"sender":{"key":"peter@avirtualhome.com","avatar":"https://avatars.githubusercontent.com/u/380071?v=4"},"body":"On Thu, 28 Oct 2010 09:15:45 -0700 (PDT)\nJakub Narebski <jnareb@gmail.com> wrote:\n\n> Peter van der Does <peter@avirtualhome.com> writes:\n> > On Wed, 27 Oct 2010 19:54:55 -0500\n> > Jonathan Nieder <jrnieder@gmail.com> wrote:\n> > \n> > > Peter van der Does wrote:\n> > > \n> > > > The bash completion script could still be included with the\n> > > > core, but we can offer different versions for different shells.\n> > > \n> > > Why?  That's three times the maintenance work.\n> > \n> > The cons of everything in one script:\n> > - If the script needs an update the submitter has to take in account\n> >   the different coding standards each shell has. Examples of this\n> > have been given in the commit message of 06f44c3 (completion: make\n> >   compatible with zsh, 2010-09-06)\n> > \n> > - The script could end up with a slew of if statements to see which\n> >   shell the script is running in and taking some action.\n> > \n> > - Shells don't share all the same functions, the script could be\n> > filled with functions not needed in other shells. the zsh patch\n> > includes one, the Bash 4 patch includes several.\n> > \n> > The pros of everything in one script:\n> > - Small changes, like adding an extra option to a git command for\n> >   completion only have to implemented in one script.\n> \n> What about having separate scripts, but sourcing common library that\n> doesn't do completion, but just provides list of possible completions?\n> This would be best of both worlds, I think.\n> \n\nThat would be the best solution.\n\nI believe it's very hard to accomplish though.\nThe options for completion are determined within each completion\nfunction, and depending on the option a decision on what to offer the\nuser is made.\nThe way to decide which option is given and what to offer differs, some\nfunctions use for/next loops, some use case <var>.\n\n-- \nPeter van der Does\n\nGPG key: E77E8E98\n\nIRC: Ganseki on irc.freenode.net\nTwitter: @petervanderdoes\n"}]}