diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/compresult.c | 30 | ||||
-rw-r--r-- | Src/Zle/iwidgets.list | 2 | ||||
-rw-r--r-- | Src/Zle/zle.h | 16 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 209 |
4 files changed, 202 insertions, 55 deletions
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; } |