about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/compcore.c15
-rw-r--r--Src/Zle/compresult.c15
2 files changed, 24 insertions, 6 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 3e4d4c93c..b0ee2b1d0 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -163,10 +163,10 @@ mod_export struct cldata listdat;
 /**/
 mod_export int ispattern, haspattern;
 
-/* Non-zero if at least one match was added without -U. */
+/* Non-zero if at least one match was added without/with -U. */
 
 /**/
-mod_export int hasmatched;
+mod_export int hasmatched, hasunmatched;
 
 /* The current group of matches. */
 
@@ -304,7 +304,7 @@ do_completion(Hookdef dummy, Compldat dat)
     startauto = isset(AUTOMENU);
     movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1);
     showinglist = 0;
-    hasmatched = 0;
+    hasmatched = hasunmatched = 0;
     minmlen = 1000000;
     maxmlen = -1;
 
@@ -1522,9 +1522,12 @@ addmatches(Cadata dat, char **argv)
     /* Switch back to the heap that was used when the completion widget
      * was invoked. */
     SWITCHHEAPS(compheap) {
-	if ((doadd = (!dat->apar && !dat->opar && !dat->dpar)) &&
-	    (dat->aflags & CAF_MATCH))
-	    hasmatched = 1;
+	if ((doadd = (!dat->apar && !dat->opar && !dat->dpar))) {
+	    if (dat->aflags & CAF_MATCH)
+		hasmatched = 1;
+	    else
+		hasunmatched = 1;
+	}
 	if (dat->apar)
 	    aparl = newlinklist();
 	if (dat->opar)
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index e5d0617ef..64de5c744 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -610,6 +610,7 @@ do_ambiguous(void)
 	do_ambig_menu();
     } else if (ainfo) {
 	int atend = (cs == we), la, eq, tcs;
+	VARARR(char, old, we - wb);
 
 	minfo.cur = NULL;
 	minfo.asked = 0;
@@ -617,11 +618,25 @@ do_ambiguous(void)
 	fixsuffix();
 
 	/* First remove the old string from the line. */
+	tcs = cs;
 	cs = wb;
+	memcpy(old, (char *) line + wb, we - wb);
 	foredel(we - wb);
 
 	/* Now get the unambiguous string and insert it into the line. */
 	cline_str(ainfo->line, 1, NULL);
+
+	/* Sometimes the different match specs used may result in a cline
+	 * that is shorter than the original string. If that happened, we
+	 * re-insert the old string. Unless there were matches added with
+	 * -U, that is. */
+	if (lastend - wb < we - wb && !hasunmatched) {
+	    cs = wb;
+	    foredel(lastend - wb);
+	    inststrlen(old, 0, we - wb);
+	    lastend = we;
+	    cs = tcs;
+	}
 	if (eparq) {
 	    tcs = cs;
 	    cs = lastend;