Patchwork [4,of,7] bash_completion: fix issue with subdirectories not being completed

login
register
mail settings
Submitter Sean Farley
Date Nov. 21, 2013, 10:56 p.m.
Message ID <14432a04ead843eacc54.1385074568@laptop.local>
Download mbox | patch
Permalink /patch/3083/
State Superseded
Commit 25cb1d96c3078d4d15a4df17bdc9a28baf3edaf4
Headers show

Comments

Sean Farley - Nov. 21, 2013, 10:56 p.m.
# HG changeset patch
# User Sean Farley <sean.michael.farley@gmail.com>
# Date 1384976718 18000
#      Wed Nov 20 14:45:18 2013 -0500
# Node ID 14432a04ead843eacc54deadd88ed706b4f2de89
# Parent  d43f240774e9ca3acb00d49584c192f0d47b4de5
bash_completion: fix issue with subdirectories not being completed

Previously, if there was a directory between the file and first-level directory (e.g. 'bar' in
foo/bar/file), then bash_completion would only list 'foo/file' instead of 'foo/bar/file'.

This behavior was introduced in 80f3ae36f908 to fix spaces in file names. In
this patch, we keep that behavior while also fixing subdirectory completion by
reverting 80f3ae36f908 and instead add backslashes to whitespace manually. This
approach means adding the completion option 'nospace' since we do this manually
now.

Patch

diff --git a/contrib/bash_completion b/contrib/bash_completion
--- a/contrib/bash_completion
+++ b/contrib/bash_completion
@@ -82,19 +82,17 @@ 
 
 _hg_debugpathcomplete()
 {
     local files="$(_hg_cmd debugpathcomplete $1 "$cur")"
     local IFS=$'\n'
-    compopt -o filenames 2>/dev/null
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 }
 
 _hg_status()
 {
     local files="$(_hg_cmd status -n$1 "glob:$cur**")"
     local IFS=$'\n'
-    compopt -o filenames 2>/dev/null
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 }
 
 _hg_bookmarks()
 {
@@ -126,10 +124,23 @@ 
     done
 
     echo $(($count - 1))
 }
 
+_hg_fix_wordlist()
+{
+    local LASTCHAR=' '
+    if [ ${#COMPREPLY[@]} = 1 ]; then
+        [ -d "$COMPREPLY" ] && LASTCHAR=/
+        COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR")
+    else
+        for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
+            [ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
+        done
+    fi
+}
+
 _hg()
 {
     local cur prev cmd cmd_index opts i aliashg
     # global options that receive an argument
     local global_args='--cwd|-R|--repository'
@@ -160,40 +171,46 @@ 
         fi
     done
 
     if [[ "$cur" == -* ]]; then
         if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then
+            _hg_fix_wordlist
             return
         fi
 
         opts=$(_hg_cmd debugcomplete --options "$cmd")
 
         COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
+        _hg_fix_wordlist
         return
     fi
 
     # global options
     case "$prev" in
         -R|--repository)
             _hg_paths
             _hg_repos
+            _hg_fix_wordlist
             return
         ;;
         --cwd)
             # Stick with default bash completion
+            _hg_fix_wordlist
             return
         ;;
     esac
 
     if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
         _hg_commands
+        _hg_fix_wordlist
         return
     fi
 
     # try to generate completion candidates for whatever command the user typed
     local help
     if _hg_command_specific; then
+        _hg_fix_wordlist
         return
     fi
 
     # canonicalize the command name and try again
     help=$(_hg_cmd help "$cmd")
@@ -203,10 +220,11 @@ 
     fi
     cmd=${help#hg }
     cmd=${cmd%%[$' \n']*}
     canonical=1
     _hg_command_specific
+    _hg_fix_wordlist
 }
 
 _hg_command_specific()
 {
     if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
@@ -289,12 +307,12 @@ 
     esac
 
     return 0
 }
 
-complete -o bashdefault -o default -F _hg hg \
-    || complete -o default -F _hg hg
+complete -o bashdefault -o default -o nospace -F _hg hg \
+    || complete -o default -o nospace -F _hg hg
 
 
 # Completion for commands provided by extensions
 
 # bookmarks