From f77a7a5b18f0650d32e5e8dac1f1cb284a9e4690 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 7 Nov 2013 15:19:07 +0000 Subject: 31937: zle -Fw uses widget semantics for file descriptor handler --- ChangeLog | 7 +++++++ Doc/Zsh/zle.yo | 11 +++++++++-- Src/Zle/zle_main.c | 38 ++++++++++++++++++++++++-------------- Src/Zle/zle_thingy.c | 16 ++++++++++++++-- Src/Zle/zle_utils.c | 7 +++---- Src/math.c | 23 ++++++++++++++++++++--- Test/C01arith.ztst | 4 ++-- 7 files changed, 79 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5f5dc719c..2adf991f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-11-07 Peter Stephenson + + * 31937: Doc/Zsh/zle.yo, Src/Zle/zle_main.c, + Src/Zle/zle_thingy.c, Src/Zle/zle_utils.c, Src/math.c, + Test/C01arith.ztst: zle -Fw uses widget semantics for + file descriptor handler. + 2013-11-06 Peter Stephenson * unposted: Completion/Debian/Command/.distfiles, diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 614924bfb..2d7756859 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -373,7 +373,7 @@ xitem(tt(zle) tt(-R) [ tt(-c) ] [ var(display-string) ] [ var(string) ... ]) xitem(tt(zle) tt(-M) var(string)) xitem(tt(zle) tt(-U) var(string)) xitem(tt(zle) tt(-K) var(keymap)) -xitem(tt(zle) tt(-F) [ tt(-L) ] [ var(fd) [ var(handler) ] ]) +xitem(tt(zle) tt(-F) [ tt(-L) | tt(-w) ] [ var(fd) [ var(handler) ] ]) xitem(tt(zle) tt(-I)) xitem(tt(zle) tt(-T) [ tt(tc) var(function) | tt(-r) tt(tc) | tt(-L) ] ) item(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -Nw ] [ -K) var(keymap) tt(]) var(args) ...)( @@ -487,7 +487,7 @@ This keymap selection affects the interpretation of following keystrokes within this invocation of ZLE. Any following invocation (e.g., the next command line) will start as usual with the `tt(main)' keymap selected. ) -item(tt(-F) [ tt(-L) ] [ var(fd) [ var(handler) ] ])( +item(tt(-F) [ tt(-L) | tt(-w) ] [ var(fd) [ var(handler) ] ])( Only available if your system supports one of the `poll' or `select' system calls; most modern systems do. @@ -502,6 +502,13 @@ Note that zle makes no attempt to check whether this fd is actually readable when installing the handler. The user must make their own arrangements for handling the file descriptor when zle is not active. +If the option tt(-w) is also given, the var(handler) is instead a +line editor widget, typically a shell function made into a widget using +tt(zle -N). In that case var(handler) can use all the facilities of +zle to update the current editing line. Note, however, that as handling +var(fd) takes place at a low level changes to the display will not +automatically appear; the widget should call tt(zle -R) to force redisplay. + Any number of handlers for any number of readable file descriptors may be installed. Installing a handler for an var(fd) which is already handled causes the existing handler to be replaced. diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 5798e74b4..6822230b4 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -201,6 +201,8 @@ int nwatch; /* Number of fd's we are watching */ int *watch_fds; /* The list of fds, not terminated! */ /**/ char **watch_funcs; /* The corresponding functions to call, normal array */ +/**/ +int *watch_widgets; /* 1 if corresponding function is called as widget */ /* set up terminal */ @@ -725,7 +727,9 @@ raw_getbyte(long do_keytmout, char *cptr) int lnwatch = nwatch; int *lwatch_fds = zalloc(lnwatch*sizeof(int)); char **lwatch_funcs = zarrdup(watch_funcs); + int *lwatch_widgets = zalloc(lnwatch*sizeof(int)); memcpy(lwatch_fds, watch_fds, lnwatch*sizeof(int)); + memcpy(lwatch_widgets, watch_widgets, lnwatch*sizeof(int)); for (i = 0; i < lnwatch; i++) { if ( # ifdef HAVE_POLL @@ -735,30 +739,37 @@ raw_getbyte(long do_keytmout, char *cptr) # endif ) { /* Handle the fd. */ - LinkList funcargs = znewlinklist(); - zaddlinknode(funcargs, ztrdup(lwatch_funcs[i])); + char *fdbuf; { char buf[BDIGBUFSIZE]; convbase(buf, lwatch_fds[i], 10); - zaddlinknode(funcargs, ztrdup(buf)); + fdbuf = ztrdup(buf); } + + if (lwatch_widgets[i]) { + zlecallhook(lwatch_funcs[i], fdbuf); + zsfree(fdbuf); + } else { + LinkList funcargs = znewlinklist(); + zaddlinknode(funcargs, ztrdup(lwatch_funcs[i])); + zaddlinknode(funcargs, fdbuf); # ifdef HAVE_POLL # ifdef POLLERR - if (fds[i+1].revents & POLLERR) - zaddlinknode(funcargs, ztrdup("err")); + if (fds[i+1].revents & POLLERR) + zaddlinknode(funcargs, ztrdup("err")); # endif # ifdef POLLHUP - if (fds[i+1].revents & POLLHUP) - zaddlinknode(funcargs, ztrdup("hup")); + if (fds[i+1].revents & POLLHUP) + zaddlinknode(funcargs, ztrdup("hup")); # endif # ifdef POLLNVAL - if (fds[i+1].revents & POLLNVAL) - zaddlinknode(funcargs, ztrdup("nval")); + if (fds[i+1].revents & POLLNVAL) + zaddlinknode(funcargs, ztrdup("nval")); # endif # endif - - - callhookfunc(lwatch_funcs[i], funcargs, 0, NULL); + callhookfunc(lwatch_funcs[i], funcargs, 0, NULL); + freelinklist(funcargs, freestr); + } if (errflag) { /* No sensible way of handling errors here */ errflag = 0; @@ -768,7 +779,6 @@ raw_getbyte(long do_keytmout, char *cptr) */ errtry = 1; } - freelinklist(funcargs, freestr); } } /* Function may have invalidated the display. */ @@ -1960,7 +1970,7 @@ zle_main_entry(int cmd, va_list ap) static struct builtin bintab[] = { BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaM:ldDANmrsLRp", NULL), BUILTIN("vared", 0, bin_vared, 1, 1, 0, "aAcef:hi:M:m:p:r:t:", NULL), - BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDFgGIKlLmMNrRTU", NULL), + BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDFgGIKlLmMNrRTUw", NULL), }; /* The order of the entries in this table has to match the *HOOK diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c index 49d715e06..78c7918d2 100644 --- a/Src/Zle/zle_thingy.c +++ b/Src/Zle/zle_thingy.c @@ -781,7 +781,8 @@ bin_zle_fd(char *name, char **args, Options ops, UNUSED(char func)) if (*args && watch_fds[i] != fd) continue; found = 1; - printf("%s -F %d %s\n", name, watch_fds[i], watch_funcs[i]); + printf("%s -F %s%d %s\n", name, watch_widgets[i] ? "-w " : "", + watch_fds[i], watch_funcs[i]); } /* only return status 1 if fd given and not found */ return *args && !found; @@ -795,6 +796,7 @@ bin_zle_fd(char *name, char **args, Options ops, UNUSED(char func)) if (watch_fds[i] == fd) { zsfree(watch_funcs[i]); watch_funcs[i] = funcnam; + watch_widgets[i] = OPT_ISSET(ops,'w') ? 1 : 0; found = 1; break; } @@ -807,9 +809,12 @@ bin_zle_fd(char *name, char **args, Options ops, UNUSED(char func)) newnwatch * sizeof(int)); watch_funcs = (char **)zrealloc(watch_funcs, (newnwatch+1) * sizeof(char *)); + watch_widgets = (int *)zrealloc(watch_widgets, + newnwatch * sizeof(int)); watch_fds[nwatch] = fd; watch_funcs[nwatch] = funcnam; watch_funcs[newnwatch] = NULL; + watch_widgets[nwatch] = OPT_ISSET(ops,'w') ? 1 : 0; nwatch = newnwatch; } } else { @@ -817,32 +822,39 @@ bin_zle_fd(char *name, char **args, Options ops, UNUSED(char func)) for (i = 0; i < nwatch; i++) { if (watch_fds[i] == fd) { int newnwatch = nwatch-1; - int *new_fds; + int *new_fds, *new_widgets; char **new_funcs; zsfree(watch_funcs[i]); if (newnwatch) { new_fds = zalloc(newnwatch*sizeof(int)); new_funcs = zalloc((newnwatch+1)*sizeof(char*)); + new_widgets = zalloc(newnwatch*sizeof(int)); if (i) { memcpy(new_fds, watch_fds, i*sizeof(int)); memcpy(new_funcs, watch_funcs, i*sizeof(char *)); + memcpy(new_widgets, watch_widgets, i*sizeof(int)); } if (i < newnwatch) { memcpy(new_fds+i, watch_fds+i+1, (newnwatch-i)*sizeof(int)); memcpy(new_funcs+i, watch_funcs+i+1, (newnwatch-i)*sizeof(char *)); + memcpy(new_widgets+i, watch_widgets+i+1, + (newnwatch-i)*sizeof(int)); } new_funcs[newnwatch] = NULL; } else { new_fds = NULL; new_funcs = NULL; + new_widgets = NULL; } zfree(watch_fds, nwatch*sizeof(int)); zfree(watch_funcs, (nwatch+1)*sizeof(char *)); + zfree(watch_widgets, nwatch*sizeof(int)); watch_fds = new_fds; watch_funcs = new_funcs; + watch_widgets = new_widgets; nwatch = newnwatch; found = 1; break; diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index b84d253bb..b82e54ce5 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1643,7 +1643,7 @@ zlecallhook(char *name, char *arg) { Thingy thingy = rthingy_nocreate(name); int saverrflag, savretflag; - char *args[3]; + char *args[2]; if (!thingy) return; @@ -1651,9 +1651,8 @@ zlecallhook(char *name, char *arg) saverrflag = errflag; savretflag = retflag; - args[0] = thingy->nam; - args[1] = arg; - args[2] = NULL; + args[0] = arg; + args[1] = NULL; execzlefunc(thingy, args, 1); unrefthingy(thingy); diff --git a/Src/math.c b/Src/math.c index eae283d19..b21a3adee 100644 --- a/Src/math.c +++ b/Src/math.c @@ -1374,6 +1374,19 @@ mathevalarg(char *s, char **ss) mnumber x; int xmtok = mtok; + /* + * At this entry point we don't allow an empty expression, + * whereas we do with matheval(). I'm not sure if this + * difference is deliberate, but it does mean that e.g. + * $array[$ind] where ind hasn't been set produces an error, + * which is probably safe. + * + * To avoid a more opaque error further in, bail out here. + */ + if (!*s) { + zerr("bad math expression: empty string"); + return (zlong)0; + } x = mathevall(s, MPREC_ARG, ss); if (mtok == COMMA) (*ss)--; @@ -1401,6 +1414,7 @@ checkunary(int mtokc, char *mptr) } if (errmsg) { int len, over = 0; + char *errtype = errmsg == 2 ? "operator" : "operand"; while (inblank(*mptr)) mptr++; len = ztrlen(mptr); @@ -1408,9 +1422,12 @@ checkunary(int mtokc, char *mptr) len = 10; over = 1; } - zerr("bad math expression: %s expected at `%l%s'", - errmsg == 2 ? "operator" : "operand", - mptr, len, over ? "..." : ""); + if (!*mptr) + zerr("bad math expression: %s expected at end of string", + errtype); + else + zerr("bad math expression: %s expected at `%l%s'", + errtype, mptr, len, over ? "..." : ""); } unary = !(tp & OP_OPF); } diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst index 71c8a1969..c19135ce6 100644 --- a/Test/C01arith.ztst +++ b/Test/C01arith.ztst @@ -134,11 +134,11 @@ print $(( a = )) 1:empty assignment -?(eval):1: bad math expression: operand expected at `' +?(eval):1: bad math expression: operand expected at end of string print $(( 3, )) 1:empty right hand of comma -?(eval):1: bad math expression: operand expected at `' +?(eval):1: bad math expression: operand expected at end of string print $(( 3,,4 )) 1:empty middle of comma -- cgit 1.4.1