[PATCH 2 of 2 RFC] completion: use debugpathcomplete in bash_completion

Bryan O'Sullivan bos at serpentine.com
Wed Mar 13 16:42:54 CDT 2013


# HG changeset patch
# User Bryan O'Sullivan <bryano at fb.com>
# Date 1363210964 25200
# Node ID 27a63d55bcc1300b077537ef937c1e6fbd61a83e
# Parent  8d53d4c8d0e5b0b59fc8dc1adb51802ec621975f
completion: use debugpathcomplete in bash_completion

The current bash_completion code is very slow in a large working
directory. It uses "hg status" to generate possibly matching files,
which checks the status of every file. We usually don't care about
status when completing, so that cost is very high.

Switching to the new debugpathcomplete command does not check the
status of files, so offers much better performance.

Note that we also change some existing bash_completion behaviour.

For instance, the existing behaviour of completion for "hg remove"
is weird and wrong: we only complete files that have already been
deleted by hand ("hg status -d"), whereas we should complete only
files in the dirstate's 'n' (normal or modified) and 'm' (merge)
states.

There is a tradeoff, however: since we don't check the status of
files, we can now produce *more* completions than necessary for
cases where we'd like to complete only with modified files (e.g.
commit, diff). I'm not sure this is the right tradeoff, but it
seems much better than being terribly slow.

diff --git a/contrib/bash_completion b/contrib/bash_completion
--- a/contrib/bash_completion
+++ b/contrib/bash_completion
@@ -80,6 +80,14 @@ shopt -s extglob
     done
 }
 
+_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 .)"
@@ -252,19 +260,23 @@ shopt -s extglob
 	    _hg_labels
 	;;
 	commit|record)
-	    _hg_status "mar"
+	    # it is harmless to complete unmodified files
+	    _hg_debugpathcomplete
 	;;
 	remove)
-	    _hg_status "d"
+	    _hg_debugpathcomplete --normal
 	;;
 	forget)
-	    _hg_status "a"
+	    _hg_debugpathcomplete --added
 	;;
 	diff)
-	    _hg_status "mar"
+	    # it is harmless to complete unmodified files
+	    _hg_debugpathcomplete
 	;;
 	revert)
-	    _hg_status "mard"
+	    # we must complete all files in case we are asked to
+	    # revert to a non-parent rev
+	    _hg_debugpathcomplete
 	;;
 	clone)
 	    local count=$(_hg_count_non_option)


More information about the Mercurial-devel mailing list