Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: fix up suffix handling in completion



This is an attempt to make autoremovable suffixes compatible with wide
characters.  I'm not sure if I've done it the simplest way but it should
at least work up to minor glitches.  I probably won't get a chance to
commit this till Monday.

This is the last major fix for wide characters on my list.  One thing is
still broken, bangchar, but that will need hist.c fixing to make it
useful.  All the other notes left in zle are about inefficiencies and
things that might go wrong.  Of course, there are probably a great many
little things that aren't quite right.

While testing this I noticed magic-space didn't behave the same as an
ordinary space for suffix-removal purposes, and presumably it should, so
I've changed that.

Index: Src/Zle/compresult.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/compresult.c,v
retrieving revision 1.59
diff -u -r1.59 compresult.c
--- Src/Zle/compresult.c	28 Oct 2005 17:34:33 -0000	1.59
+++ Src/Zle/compresult.c	4 Nov 2005 18:03:40 -0000
@@ -991,9 +991,17 @@
 	if (minfo.we) {
 	    minfo.end += minfo.insc;
 	    if (m->flags & CMF_REMOVE) {
-		makesuffixstr(m->remf, m->rems, minfo.insc);
-		if (minfo.insc == 1)
-		    suffixlen[STOUC(m->suf[0])] = 1;
+		/*
+		 * Here we need the number of characters, not
+		 * bytes in the string.
+		 */
+		int len;
+		ZLE_STRING_T wsuf =
+		    stringaszleline(m->suf, 0, &len, NULL, NULL);
+		makesuffixstr(m->remf, m->rems, len);
+		if (len == 1)
+		    addsuffix(SUFTYP_POSSTR, wsuf, 1, 1);
+		free(wsuf);
 	    }
 	}
     } else {
@@ -1085,7 +1093,7 @@
 			makesuffixstr(m->remf, m->rems, 1);
 		    else if (isset(AUTOREMOVESLASH)) {
 			makesuffix(1);
-			suffixlen['/'] = 1;
+			addsuffix(SUFTYP_POSSTR, ZWS("/"), 1, 1);
 		    }
 		}
 	    }
@@ -1100,7 +1108,7 @@
 	    /* If a suffix was added, and is removable, let *
 	     * `,' and `}' remove it.                       */
 	    if (isset(AUTOPARAMKEYS))
-		suffixlen[','] = suffixlen['}'] = suffixlen[256];
+		addsuffix(SUFTYP_POSSTR, ZWS(",}"), 2, suffixnoinslen);
 	} else if (!menucmp) {
 	    /*{{*/
 	    /* Otherwise, add a `,' suffix, and let `}' remove it. */
@@ -1110,7 +1118,7 @@
 	    minfo.insc++;
 	    makesuffix(1);
 	    if ((!menucmp || minfo.we) && isset(AUTOPARAMKEYS))
-		suffixlen[','] = suffixlen['}'] = 1;
+		addsuffix(SUFTYP_POSSTR, ZWS(",}"), 2, 1);
 	}
     } else if (!havesuff && (!(m->flags & CMF_FILE) || !sr)) {
 	/* If we didn't add a suffix, add a space, unless we are *
@@ -1129,8 +1137,14 @@
 		makesuffixstr(m->remf, m->rems, 1);
 	}
     }
-    if (minfo.we && partest && isset(AUTOPARAMKEYS))
-	makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), minfo.insc - parq);
+    if (minfo.we && partest && isset(AUTOPARAMKEYS)) {
+	/* the suffix code needs numbers of characters, not octets */
+	int outlen;
+	char *tmpstr = dupstrpfx(zlemetaline + parq, minfo.insc - parq);
+	ZLE_STRING_T subline = stringaszleline(tmpstr, 0, &outlen, NULL, NULL);
+	makeparamsuffix(((m->flags & CMF_PARBR) ? 1 : 0), outlen);
+	free(subline);
+    }
 
     if ((menucmp && !minfo.we) || !movetoend) {
 	zlemetacs = minfo.end;
Index: Src/Zle/iwidgets.list
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/iwidgets.list,v
retrieving revision 1.6
diff -u -r1.6 iwidgets.list
--- Src/Zle/iwidgets.list	1 Jul 2004 14:55:57 -0000	1.6
+++ Src/Zle/iwidgets.list	4 Nov 2005 18:03:40 -0000
@@ -73,7 +73,7 @@
 "kill-word", killword, ZLE_KILL | ZLE_KEEPSUFFIX
 "list-choices", listchoices, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_ISCOMP
 "list-expand", listexpand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
-"magic-space", magicspace, 0
+"magic-space", magicspace, ZLE_KEEPSUFFIX | ZLE_MENUCMP
 "menu-complete", menucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
 "menu-expand-or-complete", menuexpandorcomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
 "neg-argument", negargument, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
Index: Src/Zle/zle.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle.h,v
retrieving revision 1.23
diff -u -r1.23 zle.h
--- Src/Zle/zle.h	1 Nov 2005 03:26:51 -0000	1.23
+++ Src/Zle/zle.h	4 Nov 2005 18:03:40 -0000
@@ -248,7 +248,12 @@
 
 /* Standard type of suffix removal. */
 
-#define removesuffix() iremovesuffix(256, 0)
+#ifdef MULTIBYTE_SUPPORT
+#define NO_INSERT_CHAR	WEOF
+#else
+#define NO_INSERT_CHAR  256
+#endif
+#define removesuffix() iremovesuffix(NO_INSERT_CHAR, 0)
 
 /*
  * Cut/kill buffer type.  The buffer itself is purely binary data, not
@@ -326,6 +331,15 @@
     ZSL_TOEND = 2,		/* Go to the end of the new line */
 };
 
+
+/* Type arguments to addsuffix() */
+enum suffixtype {
+    SUFTYP_POSSTR,		/* String of characters to match */
+    SUFTYP_NEGSTR,		/* String of characters not to match */
+    SUFTYP_POSRNG,		/* Range of characters to match */
+    SUFTYP_NEGRNG		/* Range of characters not to match */
+};
+
 #ifdef DEBUG
 #define STRINGIFY_LITERAL(x)	# x
 #define STRINGIFY(x)		STRINGIFY_LITERAL(x)
Index: Src/Zle/zle_misc.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v
retrieving revision 1.33
diff -u -r1.33 zle_misc.c
--- Src/Zle/zle_misc.c	2 Nov 2005 11:09:23 -0000	1.33
+++ Src/Zle/zle_misc.c	4 Nov 2005 18:03:40 -0000
@@ -1012,20 +1012,51 @@
  * indicate that it is being permanently fixed.
  */
 
-/* Length of suffix to remove when inserting each possible character value.  *
- * suffixlen[256] is the length to remove for non-insertion editing actions. */
+struct suffixset;
 
-/*
- * TODO: Aargh, this is completely broken with wide characters.
- */
-/**/
-mod_export int suffixlen[257];
+/* An element of a suffix specification */
+struct suffixset {
+    struct suffixset *next;	/* Next in the list */
+    int tp;			/* The SUFTYP_* from enum suffixtype */
+    ZLE_STRING_T chars;		/* Set of characters to match (or not) */
+    int lenstr;			/* Length of chars */
+    int lensuf;			/* Length of suffix */
+};
+
+/* The list of suffix structures */
+struct suffixset *suffixlist;
 
 /* Shell function to call to remove the suffix. */
 
 /**/
 static char *suffixfunc;
 
+/* Length associated with the suffix function */
+static int suffixfunclen;
+
+/* Length associated with uninsertable characters */
+/**/
+mod_export int
+suffixnoinslen;
+
+/**/
+mod_export void
+addsuffix(int tp, ZLE_STRING_T chars, int lenstr, int lensuf)
+{
+    struct suffixset *newsuf = zalloc(sizeof(struct suffixset));
+    newsuf->next = suffixlist;
+    suffixlist = newsuf;
+
+    newsuf->tp = tp;
+    if (lenstr) {
+	newsuf->chars = zalloc(lenstr*sizeof(ZLE_CHAR_T));
+	ZS_memcpy(newsuf->chars, chars, lenstr);
+    } else
+	newsuf->chars = NULL;
+    newsuf->lenstr = lenstr;
+    newsuf->lensuf = lensuf;
+}
+
 /* Set up suffix: the last n characters are a suffix that should be *
  * removed in the usual word end conditions.                        */
 
@@ -1033,8 +1064,8 @@
 mod_export void
 makesuffix(int n)
 {
-    suffixlen[256] = suffixlen[' '] = suffixlen['\t'] = suffixlen['\n'] = 
-	suffixlen[';'] = suffixlen['&'] = suffixlen['|'] = n;
+    addsuffix(SUFTYP_POSSTR, ZWS(" \t\n;&|"), 6, n);
+    suffixnoinslen = n;
 }
 
 /* Set up suffix for parameter names: the last n characters are a suffix *
@@ -1047,13 +1078,16 @@
 mod_export void
 makeparamsuffix(int br, int n)
 {
-    if(br || unset(KSHARRAYS))
-	suffixlen[':'] = suffixlen['['] = n;
-    if(br) {
-	suffixlen['#'] = suffixlen['%'] = suffixlen['?'] = n;
-	suffixlen['-'] = suffixlen['+'] = suffixlen['='] = n;
-	/*{*/ suffixlen['}'] = suffixlen['/'] = n;
+    ZLE_STRING_T charstr = ZWS(":[#%?-+=");
+    int lenstr = 0;
+
+    if (br || unset(KSHARRAYS)) {
+	lenstr = 2;
+	if (br)
+	    lenstr += 6;
     }
+    if (lenstr)
+	addsuffix(SUFTYP_POSSTR, charstr, lenstr, n);
 }
 
 /* Set up suffix given a string containing the characters on which to   *
@@ -1066,9 +1100,10 @@
     if (f) {
 	zsfree(suffixfunc);
 	suffixfunc = ztrdup(f);
-	suffixlen[0] = n;
+	suffixfunclen = n;
     } else if (s) {
-	int inv, i, v, z = 0;
+	int inv, i, z = 0;
+	ZLE_STRING_T ws, lasts, wptr;
 
 	if (*s == '^' || *s == '!') {
 	    inv = 1;
@@ -1077,28 +1112,43 @@
 	    inv = 0;
 	s = getkeystring(s, &i, 5, &z);
 	s = metafy(s, i, META_USEHEAP);
-
-	if (inv) {
-	    v = 0;
-	    for (i = 0; i < 257; i++)
-		 suffixlen[i] = n;
-	} else
-	    v = n;
+	ws = stringaszleline(s, 0, &i, NULL, NULL);
 
 	if (z)
-	    suffixlen[256] = v;
+	    suffixnoinslen = inv ? 0 : n;
+	else if (inv) {
+	    /*
+	     * negative match, \- wasn't present, so it *should*
+	     * have this suffix length
+	     */
+	    suffixnoinslen = n;
+	}
 
-	while (*s) {
-	    if (s[1] == '-' && s[2]) {
-		int b = (int) *s, e = (int) s[2];
-
-		while (b <= e)
-		    suffixlen[b++] = v;
-		s += 2;
-	    } else
-		suffixlen[STOUC(*s)] = v;
-	    s++;
+	lasts = wptr = ws;
+	while (i) {
+	    if (i >= 3 && wptr[1] == ZWC('-')) {
+		ZLE_CHAR_T str[2];
+
+		if (wptr > lasts)
+		    addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR,
+			      lasts, wptr - lasts, n);
+		str[0] = *wptr;
+		str[1] = wptr[2];
+		addsuffix(inv ? SUFTYP_NEGRNG : SUFTYP_POSRNG,
+			  str, 2, n);
+
+		wptr += 3;
+		i -= 3;
+		lasts = wptr;
+	    } else {
+		wptr++;
+		i--;
+	    }
 	}
+	if (wptr > lasts)
+	    addsuffix(inv ? SUFTYP_NEGSTR : SUFTYP_POSSTR,
+		      lasts, wptr - lasts, n);
+	free(ws);
     } else
 	makesuffix(n);
 }
@@ -1129,7 +1179,7 @@
 		unmetafy_line();
 	    }
 
-	    sprintf(buf, "%d", suffixlen[0]);
+	    sprintf(buf, "%d", suffixfunclen);
 	    addlinknode(args, suffixfunc);
 	    addlinknode(args, buf);
 
@@ -1146,14 +1196,73 @@
 	zsfree(suffixfunc);
 	suffixfunc = NULL;
     } else {
-#ifdef MULTIBYTE_SUPPORT
-	/* TODO: best I can think of for now... */
-	int sl = (unsigned int)c <= 256 ? suffixlen[c] : 0;
-#else
-	int sl = suffixlen[c];
-#endif
-	if(sl) {
-	    backdel(sl);
+	int sl = 0;
+	struct suffixset *ss;
+
+	if (c == NO_INSERT_CHAR) {
+	    sl = suffixnoinslen;
+	} else {
+	    /*
+	     * Search for a match for c in the suffix list.
+	     * We stop if we encounter a match in a positive or negative
+	     * list, using the suffix length specified or zero respectively.
+	     * If we reached the end and passed through a negative
+	     * list, we use the suffix length for that, else zero.
+	     * This would break if it were possible to have negative
+	     * sets with different suffix length:  that's not supposed
+	     * to happen.
+	     */
+	    int negsuflen = 0, found = 0;
+
+	    for (ss = suffixlist; ss; ss = ss->next) {
+		switch (ss->tp) {
+		case SUFTYP_POSSTR:
+		    if (memchr(ss->chars, c, ss->lenstr)) {
+			sl = ss->lensuf;
+			found = 1;
+		    }
+		    break;
+
+		case SUFTYP_NEGSTR:
+		    if (memchr(ss->chars, c, ss->lenstr)) {
+			sl = 0;
+			found = 1;
+		    } else {
+			negsuflen = ss->lensuf;
+		    }
+		    break;
+
+		case SUFTYP_POSRNG:
+		    if (ss->chars[0] <= c && c <= ss->chars[1]) {
+			sl = ss->lensuf;
+			found = 1;
+		    }
+		    break;
+
+		case SUFTYP_NEGRNG:
+		    if (ss->chars[0] <= c && c <= ss->chars[1]) {
+			sl = 0;
+			found = 1;
+		    } else {
+			negsuflen = ss->lensuf;
+		    }
+		    break;
+		}
+		if (found)
+		    break;
+	    }
+
+	    if (!found)
+		sl = negsuflen;
+	}
+	if (sl) {
+	    /* must be shifting wide character lengths */
+	    if (zlemetaline != NULL) {
+		unmetafy_line();
+		backdel(sl);
+		metafy_line();
+	    } else
+		backdel(sl);
 	    if (!keep)
 		invalidatelist();
 	}
@@ -1167,5 +1276,15 @@
 mod_export void
 fixsuffix(void)
 {
-    memset(suffixlen, 0, sizeof(suffixlen));
+    while (suffixlist) {
+	struct suffixset *next = suffixlist->next;
+
+	if (suffixlist->lenstr)
+	    zfree(suffixlist->chars, suffixlist->lenstr * sizeof(ZLE_CHAR_T));
+	zfree(suffixlist, sizeof(struct suffixset));
+
+	suffixlist = next;
+    }
+
+    suffixfunclen = suffixnoinslen = 0;
 }

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


This message has been scanned for viruses by BlackSpider MailControl - www.blackspider.com



Messages sorted by: Reverse Date, Date, Thread, Author