31937: zle -Fw uses widget semantics for file descriptor handler

This commit is contained in:
Peter Stephenson 2013-11-07 15:19:07 +00:00
parent 375115c7df
commit f77a7a5b18
7 changed files with 79 additions and 27 deletions

View File

@ -1,3 +1,10 @@
2013-11-07 Peter Stephenson <p.stephenson@samsung.com>
* 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 <p.w.stephenson@ntlworld.com>
* unposted: Completion/Debian/Command/.distfiles,

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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