From e366ca8dbfb3d38e4bcbfa02965d6736a7e6bdca Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 7 Nov 2005 09:37:34 +0000 Subject: users/9638: tweaks for FCEDIT etc. 21986: rewrite completion suffixes for wide characters --- ChangeLog | 13 ++++ Doc/Zsh/builtins.yo | 4 +- Doc/Zsh/manual.yo | 2 + Doc/Zsh/params.yo | 4 +- Doc/Zsh/roadmap.yo | 5 +- Src/Zle/compresult.c | 30 ++++++-- Src/Zle/iwidgets.list | 2 +- Src/Zle/zle.h | 16 +++- Src/Zle/zle_misc.c | 209 +++++++++++++++++++++++++++++++++++++++----------- Src/builtin.c | 2 + Src/params.c | 1 - 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 + + * 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 * Scott Murray : 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 @@ -1460,6 +1460,8 @@ bin_fc(char *nam, char **argv, Options ops, int func) editor = OPT_ARG(ops, 'e'); else editor = getsparam("FCEDIT"); + if (!editor) + editor = getsparam("EDITOR"); if (!editor) editor = DEFAULT_FCEDIT; 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)); -- cgit 1.4.1