From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12128 invoked by alias); 6 Nov 2013 21:59:52 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 31937 Received: (qmail 26475 invoked from network); 6 Nov 2013 21:59:37 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:subject:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=5G4dFd5hXOtUPFZxclSLmvUMt1ps9GewXM6H+CUlBr8=; b=V9zIXsC5fTPbyOYj60UKu72FHMfgnTdQt6XLoi4uCi8aqWtKeP1Dje4C24qFaANyuZ 0rcIyMhIs744RZe0/vycLq3CGw7CGOPJ9yplVWbF2TSOz6oWnNbpjIL9dYozcdo37BPE yDnvGxp5vFlZ5qQMXEhnMg+UrbPJOD2ZBnhzGieOnC+WGfeL2l4Lsg/Zxe3uxgJ6BXFQ PXvhQYjkUbZ/TtgpaAWcMAbyBT1w7WwjyBIdBFuQfq3t3qWNOs8wCcLYi9ZmhHHIelRF GrxhnkyPDx/9mdIKkI+0UPV4vrIekkwvYgoJB1zbe8GgyQo8Hv7njdK3V9Vf8JoOR1qc a+DQ== X-Gm-Message-State: ALoCoQlZvxI5aTj447b3mKUo3i6Jjcr6ZYUiCUh+yK3JwQMvTOuVVEBs4yiS4al16NAEowXIxCku X-Received: by 10.194.104.66 with SMTP id gc2mr317486wjb.75.1383773627009; Wed, 06 Nov 2013 13:33:47 -0800 (PST) X-ProxyUser-IP: 86.6.157.246 Date: Wed, 6 Nov 2013 21:33:44 +0000 From: Peter Stephenson To: Zsh Hackers' List Subject: Re: Fish-like autosuggestions Message-ID: <20131106213344.3e9bea64@pws-pc.ntlworld.com> In-Reply-To: <20131106200715.6e549a6e@pws-pc.ntlworld.com> References: <131030092555.ZM8077@torch.brasslantern.com> <131105075700.ZM18043@torch.brasslantern.com> <20131105161858.543037da@pwslap01u.europe.root.pri> <131105114640.ZM18224@torch.brasslantern.com> <131105124000.ZM18277@torch.brasslantern.com> <20131106200715.6e549a6e@pws-pc.ntlworld.com> X-Mailer: Claws Mail 3.8.0 (GTK+ 2.24.7; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit (Moved to zsh-workers.) This seems to work. In one session I did ztcp -l 3519 port=$REPLY ztcp -a $port out=$REPLY and on the other ztcp localhost 3519 in=$REPLY read-from-fd() { local REPLY read -u$1 REPLY LBUFFER+=$REPLY zle -R } zle -N read-from-fd zle -Fw $in read-from-fd and then doing "print stuff >&$out" in the first session causes it to be added to the command line on the other. Note the point about "zle -R". We are down in the loop that processes input to the line editor; we don't get back to redisplaying until after we've read a key. This doesn't seem unreasonable, although we could force a redisplay internally if that seemed sensible. (Returning from the input reading without reading anything from the main input file descriptor doesn't seem the right thing to do.) I should really rewrite those three separate arrays to use an array of structures. I've fixed a bug here --- zlecallhook() prepended the thingy name to the argument list, but execzlefunc() prepended the function name, too. I don't think both can be right --- that gives $0 as the function name, $1 as the thingy name, and normal arguments starting at $2. I can't believe that's intentional and it doesn't appear to be suggested by the doc. I think $WIDGET does the expected thing of returning the name of the widget if different from the function name. diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 614924b..2d77568 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 5798e74..6822230 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 49d715e..78c7918 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 b84d253..b82e54c 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); -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/