diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/compcore.c | 14 | ||||
-rw-r--r-- | Src/Zle/compctl.c | 4 | ||||
-rw-r--r-- | Src/Zle/complist.c | 19 | ||||
-rw-r--r-- | Src/Zle/compresult.c | 2 | ||||
-rw-r--r-- | Src/Zle/computil.c | 10 | ||||
-rw-r--r-- | Src/Zle/iwidgets.list | 1 | ||||
-rw-r--r-- | Src/Zle/zle_hist.c | 4 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 66 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 28 | ||||
-rw-r--r-- | Src/Zle/zle_params.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_refresh.c | 9 | ||||
-rw-r--r-- | Src/Zle/zle_tricky.c | 5 | ||||
-rw-r--r-- | Src/Zle/zle_utils.c | 52 | ||||
-rw-r--r-- | Src/Zle/zle_vi.c | 37 |
14 files changed, 199 insertions, 54 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 5c5628a8d..ac7785ab7 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1260,6 +1260,20 @@ check_param(char *s, int set, int test) ispar = (br >= 2 ? 2 : 1); b[we-wb] = '\0'; return b; + } else if (offs > e - s && *e == ':') { + /* + * Guess whether we are in modifiers. + * If the name is followed by a : and the stuff after + * that is either colons or alphanumerics we probably are. + * This is a very rough guess. + */ + char *offsptr = s + offs; + for (; e < offsptr; e++) { + if (*e != ':' && !ialnum(*e)) + break; + } + ispar = (br >= 2 ? 2 : 1); + return NULL; } } return NULL; diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index ab1857c0a..52b9e9c82 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -193,7 +193,7 @@ compctlread(char *name, char **args, Options ops, char *reply) /* only allowed to be called for completion */ if (!incompctlfunc) { - zwarnnam(name, "option valid only in functions called for completion"); + zwarnnam(name, "option valid only in functions called via compctl"); return 1; } @@ -3391,7 +3391,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) mflags |= CMF_FILE; for (n = firstnode(l); n; incnode(n)) addmatch(getdata(n), NULL); - mflags &= !CMF_FILE; + mflags &= ~CMF_FILE; } opts[NULLGLOB] = ng; } else { diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index bcf356179..5e5ba9f20 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -383,12 +383,25 @@ getcoldef(char *s) } else if (*s == '=') { char *p = ++s, *t, *cols[MAX_POS]; int ncols = 0; + int nesting = 0; Patprog prog; /* This is for a pattern. */ - while (*s && *s != '=') - s++; + while (*s && (nesting || *s != '=')) { + switch (*s++) { + case '\\': + if (*s) + s++; + break; + case '(': + nesting++; + break; + case ')': + nesting--; + break; + } + } if (!*s) return s; *s++ = '\0'; @@ -2500,7 +2513,7 @@ domenuselect(Hookdef dummy, Chdata dat) mlbeg--; } } - if ((space = zterm_lines - pl - mhasstat)) + if ((space = zterm_lines - pl - mhasstat) > 0) while (mline >= mlbeg + space) if ((mlbeg += step) + space > mlines) mlbeg = mlines - space; diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c index c0e5ff3d8..fcceb670c 100644 --- a/Src/Zle/compresult.c +++ b/Src/Zle/compresult.c @@ -1131,7 +1131,7 @@ do_single(Cmatch m) /* If a suffix was added, and is removable, let * * `,' and `}' remove it. */ if (isset(AUTOPARAMKEYS)) - addsuffix(SUFTYP_POSSTR, 0, ZWS(",}"), 2, suffixnoinslen); + addsuffix(SUFTYP_POSSTR, 0, ZWS(",}"), 2, suffixlen); } else if (!menucmp) { /*{{*/ /* Otherwise, add a `,' suffix, and let `}' remove it. */ diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c index f5e6ba195..b11c39f25 100644 --- a/Src/Zle/computil.c +++ b/Src/Zle/computil.c @@ -1500,9 +1500,11 @@ parse_cadef(char *nam, char **args) nodopts++; /* If this is for single-letter option we also store a - * pointer for the definition in the array for fast lookup. */ + * pointer for the definition in the array for fast lookup. + * But don't treat '--' as a single option called '-' */ - if (single && name[1] && !name[2]) + + if (single && name[1] && !name[2] && name[1] != '-') ret->single[STOUC(name[1])] = opt; if (again == 1) { @@ -2034,7 +2036,9 @@ ca_parse_line(Cadef d, int multi, int first) state.optbeg = state.argbeg = state.inopt = cur; state.argend = argend; state.singles = (d->single && (!pe || !*pe) && - state.curopt->name[1] && !state.curopt->name[2]); + state.curopt->name[1] && !state.curopt->name[2] && + /* Don't treat '--' as a single option called '-' */ + state.curopt->name[1] != '-'); if (!state.oargs[state.curopt->num]) state.oargs[state.curopt->num] = znewlinklist(); diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index 4372fe36e..e3ffe3e8c 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -102,6 +102,7 @@ "self-insert-unmeta", selfinsertunmeta, ZLE_MENUCMP | ZLE_KEEPSUFFIX "send-break", sendbreak, 0 "set-mark-command", setmarkcommand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL +"split-undo", splitundo, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_NOTCOMMAND "spell-word", spellword, 0 "set-local-history", setlocalhistory, 0 "transpose-chars", transposechars, 0 diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index bd5bc36d5..44b39d186 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -890,6 +890,10 @@ zgetline(UNUSED(char **args)) free(s); free(lineadd); clearlist = 1; + if (stackhist != -1) { + histline = stackhist; + stackhist = -1; + } } return 0; } diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 040b7cb83..442c31995 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -157,10 +157,10 @@ mod_export char *statusline; /**/ int stackhist, stackcs; -/* != 0 if we are making undo records */ +/* position in undo stack from when the current vi change started */ /**/ -int undoing; +zlong vistartchange; /* current modifier status */ @@ -525,7 +525,8 @@ raw_getbyte(long do_keytmout, char *cptr) #endif #ifndef HAVE_POLL # ifdef HAVE_SELECT - fd_set foofd; + fd_set foofd, errfd; + FD_ZERO(&errfd); # endif #endif @@ -613,11 +614,14 @@ raw_getbyte(long do_keytmout, char *cptr) if (!errtry) { for (i = 0; i < nwatch; i++) { int fd = watch_fds[i].fd; + if (FD_ISSET(fd, &errfd)) + continue; FD_SET(fd, &foofd); if (fd > fdmax) fdmax = fd; } } + FD_ZERO(&errfd); if (tmout.tp != ZTM_NONE) { expire_tv.tv_sec = tmout.exp100ths / 100; @@ -732,9 +736,10 @@ raw_getbyte(long do_keytmout, char *cptr) Watch_fd lwatch_fd = lwatch_fds + i; if ( # ifdef HAVE_POLL - (fds[i+1].revents & POLLIN) + (fds[i+1].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) # else - FD_ISSET(lwatch_fd->fd, &foofd) + FD_ISSET(lwatch_fd->fd, &foofd) || + FD_ISSET(lwatch_fd->fd, &errfd) # endif ) { /* Handle the fd. */ @@ -765,6 +770,9 @@ raw_getbyte(long do_keytmout, char *cptr) if (fds[i+1].revents & POLLNVAL) zaddlinknode(funcargs, ztrdup("nval")); # endif +# else + if (FD_ISSET(lwatch_fd->fd, &errfd)) + zaddlinknode(funcargs, ztrdup("err")); # endif callhookfunc(lwatch_fd->func, funcargs, 0, NULL); freelinklist(funcargs, freestr); @@ -786,6 +794,31 @@ raw_getbyte(long do_keytmout, char *cptr) for (i = 0; i < lnwatch; i++) zsfree(lwatch_fds[i].func); zfree(lwatch_fds, lnwatch*sizeof(struct watch_fd)); + +# ifdef HAVE_POLL + /* Function may have added or removed handlers */ + nfds = 1 + nwatch; + if (nfds > 1) { + fds = zrealloc(fds, sizeof(struct pollfd) * nfds); + for (i = 0; i < nwatch; i++) { + /* + * This is imperfect because it assumes fds[] and + * watch_fds[] remain in sync, which may be false + * if handlers are shuffled. However, it should + * be harmless (e.g., produce one extra pass of + * the loop) in the event they fall out of sync. + */ + if (fds[i+1].fd == watch_fds[i].fd && + (fds[i+1].revents & (POLLERR|POLLHUP|POLLNVAL))) { + fds[i+1].events = 0; /* Don't poll this */ + } else { + fds[i+1].fd = watch_fds[i].fd; + fds[i+1].events = POLLIN; + } + fds[i+1].revents = 0; + } + } +# endif } } # ifdef HAVE_POLL @@ -1080,8 +1113,7 @@ zlecore(void) if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); - if (undoing) - handleundo(); + handleundo(); } else { errflag = 1; break; @@ -1190,7 +1222,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) zlereadflags = flags; zlecontext = context; histline = curhist; - undoing = 1; + vistartchange = -1; zleline = (ZLE_STRING_T)zalloc(((linesz = 256) + 2) * ZLE_CHAR_SIZE); *zleline = ZWC('\0'); virangeflag = lastcmd = done = zlecs = zlell = mark = 0; @@ -1198,14 +1230,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) viinsbegin = 0; statusline = NULL; selectkeymap("main", 1); - /* - * If main is linked to the viins keymap, we need to register - * explicitly that we're now in vi insert mode as there's - * no user operation to indicate this. - */ - if (openkeymap("main") == openkeymap("viins")) - viinsert(NULL); - selectlocalmap(NULL); + initundo(); fixsuffix(); if ((s = getlinknode(bufstack))) { setline(s, ZSL_TOEND); @@ -1222,7 +1247,14 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) stackhist = -1; } } - initundo(); + /* + * If main is linked to the viins keymap, we need to register + * explicitly that we're now in vi insert mode as there's + * no user operation to indicate this. + */ + if (openkeymap("main") == openkeymap("viins")) + viinsert_init(); + selectlocalmap(NULL); if (isset(PROMPTCR)) putc('\r', shout); if (tmout) diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 7be0ebbd1..9bc1cf6f5 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -1249,10 +1249,14 @@ static char *suffixfunc; /* Length associated with the suffix function */ static int suffixfunclen; -/* Length associated with uninsertable characters */ +/* Whether to remove suffix on uninsertable characters */ +/**/ +int suffixnoinsrem; + +/* Length of the currently active, auto-removable suffix. */ /**/ mod_export int -suffixnoinslen; +suffixlen; /**/ mod_export void @@ -1309,7 +1313,8 @@ makesuffix(int n) if ((suffixchars = getsparam("ZLE_SPACE_SUFFIX_CHARS")) && *suffixchars) addsuffixstring(SUFTYP_POSSTR, SUFFLAGS_SPACE, suffixchars, n); - suffixnoinslen = n; + suffixlen = n; + suffixnoinsrem = 1; } /* Set up suffix for parameter names: the last n characters are a suffix * @@ -1358,15 +1363,10 @@ makesuffixstr(char *f, char *s, int n) s = metafy(s, i, META_USEHEAP); ws = stringaszleline(s, 0, &i, NULL, NULL); - if (z) - suffixnoinslen = inv ? 0 : n; - else if (inv) { - /* - * negative match, \- wasn't present, so it *should* - * have this suffix length - */ - suffixnoinslen = n; - } + /* Remove suffix on uninsertable characters if \- was given * + * and the character class wasn't negated -- or vice versa. */ + suffixnoinsrem = z ^ inv; + suffixlen = n; lasts = wptr = ws; while (i) { @@ -1444,7 +1444,7 @@ iremovesuffix(ZLE_INT_T c, int keep) struct suffixset *ss; if (c == NO_INSERT_CHAR) { - sl = suffixnoinslen; + sl = suffixnoinsrem ? suffixlen : 0; } else { ZLE_CHAR_T ch = c; /* @@ -1538,5 +1538,5 @@ fixsuffix(void) suffixlist = next; } - suffixfunclen = suffixnoinslen = 0; + suffixfunclen = suffixnoinsrem = suffixlen = 0; } diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index a9bbf136a..5845207fa 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -363,7 +363,7 @@ get_prebuffer(UNUSED(Param pm)) static char * get_widget(UNUSED(Param pm)) { - return bindk->nam; + return bindk ? bindk->nam : ""; } /**/ diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index fd5485770..80be27f03 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -444,6 +444,7 @@ void set_region_highlight(UNUSED(Param pm), char **aval) { int len; + char **av = aval; struct region_highlight *rhp; len = aval ? arrlen(aval) : 0; @@ -490,6 +491,8 @@ set_region_highlight(UNUSED(Param pm), char **aval) match_highlight(strp, &rhp->atr); } + + freearray(av); } @@ -977,7 +980,7 @@ zrefresh(void) int tmpalloced; /* flag to free tmpline when finished */ int remetafy; /* flag that zle line is metafied */ int txtchange; /* attributes set after prompts */ - int rprompt_off; /* Offset of rprompt from right of screen */ + int rprompt_off = 1; /* Offset of rprompt from right of screen */ struct rparams rpms; #ifdef MULTIBYTE_SUPPORT int width; /* width of wide character */ @@ -1046,8 +1049,8 @@ zrefresh(void) region_highlights[1].start = region_highlights[1].end = -1; } /* check for an active completion suffix */ - if (suffixnoinslen) { - region_highlights[2].start = zlecs - suffixnoinslen; + if (suffixlen) { + region_highlights[2].start = zlecs - suffixlen; region_highlights[2].end = zlecs; } else { region_highlights[2].start = region_highlights[2].end = -1; diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index 9d163ad9e..499c4ae77 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -611,8 +611,6 @@ docomplete(int lst) active = 1; comprecursive = 0; makecommaspecial(0); - if (undoing) - setlastline(); /* From the C-code's point of view, we can only use compctl as a default * type of completion. Load it if it hasn't been loaded already and @@ -1164,7 +1162,7 @@ get_comp_string(void) * being separated by tokens | & &! |& || &&). The loop stops when * * the end of the command containing the cursor is reached. What * * makes this messy is checking for things like redirections, loops * - * and whatnot. */ + * and whatnot. */ do { qsub = noword = 0; @@ -2797,6 +2795,7 @@ doexpandhist(void) if (!err) { zlemetacs = excs; if (strcmp(zlemetaline, ol)) { + zle_free_positions(); unmetafy_line(); /* For vi mode -- reset the beginning-of-insertion pointer * * to the beginning of the line. This seems a little silly, * diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index b82e54ce5..1089e274f 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -710,6 +710,27 @@ zle_restore_positions(void) } /* + * Discard positions previously saved, the line has been updated. + */ + +/**/ +mod_export void +zle_free_positions(void) +{ + struct zle_position *oldpos = zle_positions; + struct zle_region *oldrhp; + + zle_positions = oldpos->next; + oldrhp = oldpos->regions; + while (oldrhp) { + struct zle_region *nextrhp = oldrhp->next; + zfree(oldrhp, sizeof(*oldrhp)); + oldrhp = nextrhp; + } + zfree(oldpos, sizeof(*oldpos)); +} + +/* * Basic utility functions for adding to line or removing from line. * At this level the counts supplied are raw character counts, so * the calling code must be aware of combining characters where @@ -1354,7 +1375,10 @@ handlesuffix(UNUSED(char **args)) /* head of the undo list, and the current position */ -static struct change *changes, *curchange; +/**/ +struct change *curchange; + +static struct change *changes; /* list of pending changes, not yet in the undo system */ @@ -1629,6 +1653,32 @@ viundochange(char **args) return undo(args); } +/**/ +int +splitundo(char **args) +{ + if (vistartchange >= 0) { + mergeundo(); + vistartchange = (curchange && curchange->prev) ? + curchange->prev->changeno : 0; + } + handleundo(); + return 0; +} + +/**/ +void +mergeundo(void) +{ + struct change *current; + for (current = curchange->prev; + current && current->prev && current->changeno > vistartchange+1; + current = current->prev) { + current->flags |= CH_PREV; + current->prev->flags |= CH_NEXT; + } +} + /* * Call a ZLE hook: a user-defined widget called at a specific point * within the line editor. diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 173a49ef9..9e39143d0 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -67,15 +67,23 @@ int viinsbegin; static struct modifier lastmod; static int inrepeat, vichgrepeat; +/** + * im: >= 0: is an insertmode + * -1: skip setting insert mode + * -2: entering viins at start of editing from clean --- don't use + * inrepeat or lastchar, synthesise an i to enter insert mode. + */ + /**/ static void startvichange(int im) { if (im != -1) { - insmode = im; vichgflag = 1; + if (im > -1) + insmode = im; } - if (inrepeat) { + if (inrepeat && im != -2) { zmod = lastmod; inrepeat = vichgflag = 0; vichgrepeat = 1; @@ -84,7 +92,12 @@ startvichange(int im) if (vichgbuf) free(vichgbuf); vichgbuf = (char *)zalloc(vichgbufsz = 16); - vichgbuf[0] = lastchar; + if (im == -2) { + vichgbuf[0] = + zlell ? (insmode ? (zlecs < zlell ? 'i' : 'a') : 'R') : 'o'; + } else { + vichgbuf[0] = lastchar; + } vichgbufptr = 1; vichgrepeat = 0; } @@ -96,7 +109,7 @@ startvitext(int im) { startvichange(im); selectkeymap("main", 1); - undoing = 0; + vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0; viinsbegin = zlecs; } @@ -303,6 +316,18 @@ viinsert(UNUSED(char **args)) return 0; } +/* + * Go to vi insert mode when we first start the line editor. + * Iniialises some other stuff. + */ + +/**/ +void +viinsert_init(void) +{ + startvitext(-2); +} + /**/ int viinsertbol(UNUSED(char **args)) @@ -376,7 +401,7 @@ vichange(UNUSED(char **args)) forekill(c2 - zlecs, CUT_RAW); selectkeymap("main", 1); viinsbegin = zlecs; - undoing = 0; + vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0; } return ret; } @@ -561,7 +586,7 @@ vicmdmode(UNUSED(char **args)) { if (invicmdmode() || selectkeymap("vicmd", 0)) return 1; - undoing = 1; + mergeundo(); vichgflag = 0; if (zlecs != findbol()) DECCS(); |