zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Zsh Hackers' List <zsh-workers@zsh.org>
Subject: Re: Fish-like autosuggestions
Date: Wed, 6 Nov 2013 21:33:44 +0000	[thread overview]
Message-ID: <20131106213344.3e9bea64@pws-pc.ntlworld.com> (raw)
In-Reply-To: <20131106200715.6e549a6e@pws-pc.ntlworld.com>

(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 <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


       reply	other threads:[~2013-11-06 21:59 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CAAq2XdpaRKOnDe1LBafsq+Ln6wU0_9RL71exrOEyboi1PWcx3w@mail.gmail.com>
     [not found] ` <131030092555.ZM8077@torch.brasslantern.com>
     [not found]   ` <CAAq2Xdos6Xdt-XunRuWToDkoaubwztRP8tesPyByU8CWc3FR=Q@mail.gmail.com>
     [not found]     ` <131105075700.ZM18043@torch.brasslantern.com>
     [not found]       ` <20131105161858.543037da@pwslap01u.europe.root.pri>
     [not found]         ` <131105114640.ZM18224@torch.brasslantern.com>
     [not found]           ` <131105124000.ZM18277@torch.brasslantern.com>
     [not found]             ` <20131106200715.6e549a6e@pws-pc.ntlworld.com>
2013-11-06 21:33               ` Peter Stephenson [this message]
2013-11-07  0:11                 ` Bart Schaefer
2013-11-12 19:46                 ` Peter Stephenson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131106213344.3e9bea64@pws-pc.ntlworld.com \
    --to=p.w.stephenson@ntlworld.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).