diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2016-12-04 04:32:03 +0100 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2016-12-04 04:32:03 +0100 |
commit | 3e439c3863f14c82f70666804c8570a13b3732e6 (patch) | |
tree | 07036c43e0f3f9242bb6dd42cd2a849ec8ea8aca /Src/Zle/zle_main.c | |
parent | 2aedc4b88fd0e87b89583983951b04b96f48efd3 (diff) | |
parent | 7b7e84f0815ed22a0ee348a217776529035dccf3 (diff) | |
download | zsh-3e439c3863f14c82f70666804c8570a13b3732e6.tar.gz zsh-3e439c3863f14c82f70666804c8570a13b3732e6.zip |
Merge tag 'zsh-5.2-test-1' into debian
Diffstat (limited to 'Src/Zle/zle_main.c')
-rw-r--r-- | Src/Zle/zle_main.c | 152 |
1 files changed, 130 insertions, 22 deletions
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 6e2bfded8..15ea79643 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -357,6 +357,21 @@ ungetbytes(char *s, int len) ungetbyte(*--s); } +/**/ +void +ungetbytes_unmeta(char *s, int len) +{ + s += len; + while (len--) { + if (len && s[-2] == Meta) { + ungetbyte(*--s ^ 32); + len--; + s--; + } else + ungetbyte(*--s); + } +} + #if defined(pyr) && defined(HAVE_SELECT) static int breakread(int fd, char *buf, int n) @@ -456,7 +471,7 @@ calc_timeout(struct ztmout *tmoutp, long do_keytmout) tfdat = (Timedfn)getdata(tfnode); diff = tfdat->when - time(NULL); - if (diff < 0) { + if (diff <= 0) { /* Already due; call it and rescan. */ tfdat->func(); continue; @@ -909,13 +924,13 @@ getbyte(long do_keytmout, int *timeout) ret = STOUC(cc); } /* - * vichgbuf is raw bytes, not wide characters, so is dealt + * curvichg.buf is raw bytes, not wide characters, so is dealt * with here. */ if (vichgflag) { - if (vichgbufptr == vichgbufsz) - vichgbuf = realloc(vichgbuf, vichgbufsz *= 2); - vichgbuf[vichgbufptr++] = ret; + if (curvichg.bufptr == curvichg.bufsz) + curvichg.buf = realloc(curvichg.buf, curvichg.bufsz *= 2); + curvichg.buf[curvichg.bufptr++] = ret; } errno = old_errno; return lastchar = ret; @@ -1026,28 +1041,43 @@ getrestchar(int inchar, char *outstr, int *outcount) #endif /**/ -void redrawhook(void) +void +redrawhook(void) { Thingy initthingy; if ((initthingy = rthingy_nocreate("zle-line-pre-redraw"))) { + /* Duplicating most of zlecallhook() to save additional state */ + int saverrflag = errflag, savretflag = retflag; int lastcmd_prev = lastcmd; int old_incompfunc = incompfunc; char *args[2]; Thingy lbindk_save = lbindk, bindk_save = bindk; + refthingy(lbindk_save); refthingy(bindk_save); args[0] = initthingy->nam; args[1] = NULL; + + /* The generic redraw hook cannot be a completion function, so + * temporarily reset state for special variable handling etc. + */ incompfunc = 0; - execzlefunc(initthingy, args, 0); + execzlefunc(initthingy, args, 1); incompfunc = old_incompfunc; + + /* Restore errflag and retflag as zlecallhook() does */ + errflag = saverrflag | (errflag & ERRFLAG_INT); + retflag = savretflag; + unrefthingy(initthingy); unrefthingy(lbindk); unrefthingy(bindk); lbindk = lbindk_save; bindk = bindk_save; + /* we can't set ZLE_NOTCOMMAND since it's not a legit widget, so - * restore lastcmd manually so that we don't mess up the global state */ + * restore lastcmd manually so that we don't mess up the global state + */ lastcmd = lastcmd_prev; } } @@ -1144,11 +1174,19 @@ zlecore(void) } - region_active = 0; popheap(); } -/* Read a line. It is returned metafied. */ +/* Read a line. It is returned metafied. + * + * Parameters: + * - lp: left prompt, e.g., $PS1 + * - rp: right prompt, e.g., $RPS1 + * - flags: ZLRF_* flags (I think), see zlereadflags + * - context: ZLCON_* flags (I think), see zlecontext + * - init: "zle-line-init" + * - finish: "zle-line-finish" + */ /**/ char * @@ -1222,6 +1260,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) *zleline = ZWC('\0'); virangeflag = lastcmd = done = zlecs = zlell = mark = yankb = yanke = 0; vichgflag = 0; + viinrepeat = 0; viinsbegin = 0; statusline = NULL; selectkeymap("main", 1); @@ -1277,6 +1316,7 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) lastcol = -1; initmodifier(&zmod); prefixflag = 0; + region_active = 0; zrefresh(); @@ -1284,6 +1324,9 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) zlecallhook(init, NULL); + if (zleline && *zleline) + redrawhook(); + if ((bracket = getaparam("zle_bracketed_paste")) && arrlen(bracket) == 2) fputs(*bracket, shout); @@ -1326,6 +1369,16 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) return s; } +/**/ +static int +execimmortal(Thingy func, char **args) +{ + Thingy immortal = rthingy_nocreate(dyncat(".", func->nam)); + if (immortal) + return execzlefunc(immortal, args, 0); + return 1; +} + /* * Execute a widget. The third argument indicates that the global * variable bindk should be set temporarily so that WIDGET etc. @@ -1337,6 +1390,8 @@ int execzlefunc(Thingy func, char **args, int set_bindk) { int r = 0, ret = 0, remetafy = 0; + int nestedvichg = vichgflag; + int isrepeat = (viinrepeat == 3); Widget w; Thingy save_bindk = bindk; @@ -1346,8 +1401,10 @@ execzlefunc(Thingy func, char **args, int set_bindk) unmetafy_line(); remetafy = 1; } + if (isrepeat) + viinrepeat = 2; - if(func->flags & DISABLED) { + if (func->flags & DISABLED) { /* this thingy is not the name of a widget */ char *nm = nicedup(func->nam, 0); char *msg = tricat("No such widget `", nm, "'"); @@ -1355,7 +1412,7 @@ execzlefunc(Thingy func, char **args, int set_bindk) zsfree(nm); showmsg(msg); zsfree(msg); - ret = 1; + ret = execimmortal(func, args); } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) { int wflags = w->flags; @@ -1419,7 +1476,7 @@ execzlefunc(Thingy func, char **args, int set_bindk) zsfree(nm); showmsg(msg); zsfree(msg); - ret = 1; + ret = execimmortal(func, args); } else { int osc = sfcontext, osi = movefd(0); int oxt = isset(XTRACE); @@ -1441,6 +1498,12 @@ execzlefunc(Thingy func, char **args, int set_bindk) opts[XTRACE] = oxt; sfcontext = osc; endparamscope(); + if (errflag == ERRFLAG_ERROR) { + int saverr = errflag; + errflag &= ~ERRFLAG_ERROR; + if ((ret = execimmortal(func, args)) != 0) + errflag |= saverr; + } lastcmd = w->flags & ~(WIDGET_INUSE|WIDGET_FREE); if (inuse) { w->flags &= WIDGET_INUSE|WIDGET_FREE; @@ -1469,6 +1532,25 @@ execzlefunc(Thingy func, char **args, int set_bindk) CCRIGHT(); if (remetafy) metafy_line(); + + /* if this widget constituted the vi change, end it */ + if (vichgflag == 2 && !nestedvichg) { + if (invicmdmode()) { + if (ret) { + free(curvichg.buf); + } else { + if (lastvichg.buf) + free(lastvichg.buf); + lastvichg = curvichg; + } + vichgflag = 0; + curvichg.buf = NULL; + } else + vichgflag = 1; /* vi change continues while in insert mode */ + } + if (isrepeat) + viinrepeat = !invicmdmode(); + return ret; } @@ -1604,6 +1686,7 @@ bin_vared(char *name, char **args, Options ops, UNUSED(int func)) return 1; } else if (v) { if (*s) { + unqueue_signals(); zwarnnam(name, "not an identifier: `%s'", args[0]); return 1; } @@ -1840,11 +1923,17 @@ int recursiveedit(UNUSED(char **args)) { int locerror; + int q = queue_signal_level(); + + /* zlecore() expects to be entered with signal queue disabled */ + dont_queue_signals(); redrawhook(); zrefresh(); zlecore(); + restore_queue_signals(q); + locerror = errflag ? 1 : 0; errflag = done = eofsent = 0; @@ -1856,6 +1945,7 @@ void reexpandprompt(void) { static int reexpanding; + static int looping; if (!reexpanding++) { /* @@ -1866,15 +1956,33 @@ reexpandprompt(void) int local_lastval = lastval; lastval = pre_zle_status; - free(lpromptbuf); - lpromptbuf = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL, - &pmpt_attr); - rpmpt_attr = pmpt_attr; - free(rpromptbuf); - rpromptbuf = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL, - &rpmpt_attr); + do { + /* A new SIGWINCH may arrive while in promptexpand(), causing + * looping to increment. This only happens when a command + * substitution is used in a PROMPT_SUBST prompt, but + * nevertheless keep trying until we see no more changes. + */ + char *new_lprompt, *new_rprompt; + looping = reexpanding; + + new_lprompt = promptexpand(raw_lp ? *raw_lp : NULL, 1, NULL, NULL, + &pmpt_attr); + free(lpromptbuf); + lpromptbuf = new_lprompt; + + if (looping != reexpanding) + continue; + + rpmpt_attr = pmpt_attr; + new_rprompt = promptexpand(raw_rp ? *raw_rp : NULL, 1, NULL, NULL, + &rpmpt_attr); + free(rpromptbuf); + rpromptbuf = new_rprompt; + } while (looping != reexpanding); + lastval = local_lastval; - } + } else + looping = reexpanding; reexpanding--; } @@ -2150,7 +2258,7 @@ finish_(UNUSED(Module m)) cleanup_keymaps(); deletehashtable(thingytab); - zfree(vichgbuf, vichgbufsz); + zfree(lastvichg.buf, lastvichg.bufsz); zfree(kungetbuf, kungetsz); free_isrch_spots(); if (rdstrs) |