about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--Doc/Zsh/builtins.yo4
-rw-r--r--Doc/Zsh/manual.yo2
-rw-r--r--Doc/Zsh/params.yo4
-rw-r--r--Doc/Zsh/roadmap.yo5
-rw-r--r--Src/Zle/compresult.c30
-rw-r--r--Src/Zle/iwidgets.list2
-rw-r--r--Src/Zle/zle.h16
-rw-r--r--Src/Zle/zle_misc.c209
-rw-r--r--Src/builtin.c2
-rw-r--r--Src/params.c1
11 files changed, 229 insertions, 59 deletions
diff --git a/ChangeLog b/ChangeLog
index d033848e0..3e77961e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2005-11-07  Peter Stephenson  <pws@csr.com>
+
+	* 21986: Src/Zle/compresult.c, Src/Zle/iwidgets.list,
+	Src/Zle/zle.h, Src/Zle/zle_misc.c: make completion suffix
+	system work with wide characters; also make magic-space
+	behave like a normal space when it follows a suffix.
+
+	* users/9638: Src/builtin.c, Doc/Zsh/builtins.yo,
+	Doc/Zsh/roadmap.yo: allow FCEDIT to default to EDITOR before
+	defaulting to the builtin default; mention edit-command-line in
+	menu in roadmap.  Also (unposted) indicate roadmap in detailed
+	texinfo node listing even though it doesn't have subentries.
+
 2005-11-06  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
 	* Scott Murray <semurray@ntlworld.com>: users/9648:
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 0ae467c42..affe5b610 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -410,7 +410,9 @@ pattern (should be quoted) and only the history events matching this
 pattern will be shown.
 Otherwise the editor program var(ename) is invoked on a file containing
 these history events.  If var(ename) is not given, the value
-of the parameter tt(FCEDIT) is used.  If var(ename) is `tt(-)',
+of the parameter tt(FCEDIT) is used; if that is not set the value of the
+parameter tt(EDITOR) is used; if that is not set a builtin default, usually
+`tt(vi)' is used.  If var(ename) is `tt(-)',
 no editor is invoked.  When editing is complete, the edited
 command is executed.
 
diff --git a/Doc/Zsh/manual.yo b/Doc/Zsh/manual.yo
index 9820f1f23..4bf9f6bcd 100644
--- a/Doc/Zsh/manual.yo
+++ b/Doc/Zsh/manual.yo
@@ -59,6 +59,8 @@ menu(The Zsh Web Page)
 menu(The Zsh Userguide)
 menu(See Also)
 
+Roadmap
+
 Invocation
 
 menu(Compatibility)
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index d48723756..7999d297b 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -758,7 +758,9 @@ tt(ENV) is em(not) used unless zsh is emulating bf(sh) or bf(ksh).
 )
 vindex(FCEDIT)
 item(tt(FCEDIT))(
-The default editor for the tt(fc) builtin.
+The default editor for the tt(fc) builtin.  If tt(FCEDIT) is not set,
+the parameter tt(EDITOR) is used; if that is not set either, a builtin
+default, usually tt(vi), is used.
 )
 vindex(fignore)
 vindex(FIGNORE)
diff --git a/Doc/Zsh/roadmap.yo b/Doc/Zsh/roadmap.yo
index 5c5bb5ea5..547f7e20b 100644
--- a/Doc/Zsh/roadmap.yo
+++ b/Doc/Zsh/roadmap.yo
@@ -58,7 +58,10 @@ item(tt(history-beginning-search-backward-end), etc.)(
 alternative ways of searching the shell history
 )
 item(tt(replace-string), tt(replace-pattern))(
-functions for replacing strings or patterns globally in the command line.
+functions for replacing strings or patterns globally in the command line
+)
+item(tt(edit-command-line))(
+edit the command line with an external editor.
 )
 enditem()
 
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index 4018c5488..84e276747 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -991,9 +991,17 @@ do_single(Cmatch m)
 	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 @@ do_single(Cmatch m)
 			makesuffixstr(m->remf, m->rems, 1);
 		    else if (isset(AUTOREMOVESLASH)) {
 			makesuffix(1);
-			suffixlen['/'] = 1;
+			addsuffix(SUFTYP_POSSTR, ZWS("/"), 1, 1);
 		    }
 		}
 	    }
@@ -1100,7 +1108,7 @@ do_single(Cmatch m)
 	    /* 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 @@ do_single(Cmatch m)
 	    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 @@ do_single(Cmatch m)
 		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;
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index bf8b7c0ce..bf1abdadc 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -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
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 6c960e595..59e790542 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -248,7 +248,12 @@ typedef void (*KeyScanFunc) _((char *, Thingy, char *, void *));
 
 /* 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 @@ enum {
     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)
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 8605c4624..4caf0b915 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -1012,20 +1012,51 @@ executenamedcommand(char *prmt)
  * 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 @@ static char *suffixfunc;
 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 @@ makesuffix(int n)
 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 @@ makesuffixstr(char *f, char *s, int n)
     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 @@ makesuffixstr(char *f, char *s, int n)
 	    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;
-
-	while (*s) {
-	    if (s[1] == '-' && s[2]) {
-		int b = (int) *s, e = (int) s[2];
+	    suffixnoinslen = inv ? 0 : n;
+	else if (inv) {
+	    /*
+	     * negative match, \- wasn't present, so it *should*
+	     * have this suffix length
+	     */
+	    suffixnoinslen = n;
+	}
 
-		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 @@ iremovesuffix(ZLE_INT_T c, int keep)
 		unmetafy_line();
 	    }
 
-	    sprintf(buf, "%d", suffixlen[0]);
+	    sprintf(buf, "%d", suffixfunclen);
 	    addlinknode(args, suffixfunc);
 	    addlinknode(args, buf);
 
@@ -1146,14 +1196,73 @@ iremovesuffix(ZLE_INT_T c, int keep)
 	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 @@ iremovesuffix(ZLE_INT_T c, int keep)
 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;
 }
diff --git a/Src/builtin.c b/Src/builtin.c
index 063baa687..1b7e1935e 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -1461,6 +1461,8 @@ bin_fc(char *nam, char **argv, Options ops, int func)
 		else
 		    editor = getsparam("FCEDIT");
 		if (!editor)
+		    editor = getsparam("EDITOR");
+		if (!editor)
 		    editor = DEFAULT_FCEDIT;
 
 		unqueue_signals();
diff --git a/Src/params.c b/Src/params.c
index 1468c014a..0d3b6a25b 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -643,7 +643,6 @@ createparamtable(void)
 #ifdef HAVE_SELECT
     setiparam("BAUD", getbaudrate(&shttyinfo));  /* get the output baudrate */
 #endif
-    setsparam("FCEDIT", ztrdup(DEFAULT_FCEDIT));
     setsparam("TMPPREFIX", ztrdup(DEFAULT_TMPPREFIX));
     setsparam("TIMEFMT", ztrdup(DEFAULT_TIMEFMT));
     setsparam("WATCHFMT", ztrdup(default_watchfmt));