about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorSven Wischnowsky <wischnow@users.sourceforge.net>2000-10-10 08:36:32 +0000
committerSven Wischnowsky <wischnow@users.sourceforge.net>2000-10-10 08:36:32 +0000
commit7bb0338a78ceebaa8d9a4713ed4a1088411a317b (patch)
tree1967d81178169ca5b741d23bede01b1fed6f8efd /Src
parent1ea97c109fcb093245c56f5f5c44df986d139ea5 (diff)
downloadzsh-7bb0338a78ceebaa8d9a4713ed4a1088411a317b.tar.gz
zsh-7bb0338a78ceebaa8d9a4713ed4a1088411a317b.tar.xz
zsh-7bb0338a78ceebaa8d9a4713ed4a1088411a317b.zip
follow-up to 12930, make it first try exact character matches, but enable it to go back to try match specs if it fails after accepting such character matches (12941)
Diffstat (limited to 'Src')
-rw-r--r--Src/Zle/compmatch.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c
index 6bf82c18e..d7a8e8e73 100644
--- a/Src/Zle/compmatch.c
+++ b/Src/Zle/compmatch.c
@@ -440,7 +440,7 @@ int
 match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 	  int sfx, int test, int part)
 {
-    int ll = strlen(l), lw = strlen(w), oll = ll, olw = lw;
+    int ll = strlen(l), lw = strlen(w), oll = ll, olw = lw, exact = 0, wexact = 0;
     int il = 0, iw = 0, t, ind, add, he = 0, bpc, obc = bc, bslash;
     VARARR(unsigned char, ea, (ll > lw ? ll : lw) + 1);
     char *ow;
@@ -489,11 +489,12 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 	 * Update: this once tested `test && ...' to check for exact
 	 * character matches only in recursive calls.  But then one
 	 * can't complete `nom<TAB>' to `nomatch' with a match spec
-	 * of `B:[nN][oO]=' because that will eat the `no'. I'm almost
-	 * certain that this will break something, but I don't know what
-	 * or if it really is a problem (or has been fixed by other
-	 * changes in the code handling partial word matching). And the
-	 * completion matching tests work.
+	 * of `B:[nN][oO]=' because that will eat the `no'.
+	 * But that would break completion of strings like `nonomatch'
+	 * because the `B:[nN][oO]=' doesn't match the second `no'.
+	 * For this we added the code below that can remove already
+	 * accepted exact characters and try again, preferring match
+	 * specs.
 	 */
 
 	bslash = 0;
@@ -503,10 +504,12 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 			(ind ? (w[0] == l[0]) : (w[1] == l[0])))))) {
 	    /* No matcher could be used, but the strings have the same
 	     * character here, skip over it. */
-	    l += add; w += (bslash ? (add + add ) : add);
+	    l += add; w += (bslash ? (add + add) : add);
 	    il++; iw += 1 + bslash;
 	    ll--; lw -= 1 + bslash;
 	    bc++;
+	    exact++;
+	    wexact += 1 + bslash;
 	    if (!test)
 		while (bp && bc >= (useqbr ? bp->qpos : bp->pos)) {
 		    bp->curpos = matchbufadded + (sfx ? (ow - w) : (w - ow)) + obc;
@@ -517,6 +520,7 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 
 	    continue;
 	}
+    retry:
 	/* First try the matchers. Err... see above. */
 	for (mp = NULL, ms = mstack; !mp && ms; ms = ms->next) {
 	    for (mp = ms->matcher; mp; mp = mp->next) {
@@ -687,6 +691,7 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 		    ll -= llen; il += llen;
 		    lw -= alen; iw += alen;
 		    bc += llen;
+		    exact = 0;
 
 		    if (!test)
 			while (bp &&
@@ -798,6 +803,7 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 		    il += mp->llen; iw += mp->wlen;
 		    ll -= mp->llen; lw -= mp->wlen;
 		    bc += mp->llen;
+		    exact = 0;
 
 		    if (!test)
 			while (bp &&
@@ -836,6 +842,23 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp,
 	    lm = NULL;
 	    he = 0;
 	} else {
+
+	    if (exact) {
+		/* If we just accepted some characters directly (at the
+		 * beginning of the loop) and now can't match any further,
+		 * we go back to before those characters and try again,
+		 * preferring match specs this time. */
+
+		il -= exact; iw -= wexact;
+		ll += exact; lw += wexact;
+		bc -= exact;
+		l -= add * exact; w -= add * wexact;
+
+		exact = wexact = 0;
+
+		goto retry;
+	    }
+
 	    if (!lw)
 		break;
 	    /* No matcher and different characters: l does not match w. */