zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: more selection
@ 2002-05-13 15:33 Peter Stephenson
  2002-05-14  9:48 ` Borsenkow Andrej
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Peter Stephenson @ 2002-05-13 15:33 UTC (permalink / raw)
  To: Zsh hackers list

This patch is more advanced warning of future pain than anything else,
in case anyone wants to scream at the very idea.

The following patch adds an fd-watching facility to zle.  You tell zle
(via zle -F) to select on an fd and give it a function handler.  When data
is available for reading on that handle (only reading, at the moment),
the handler will be called, and zle will sail on without returning.
This allows you to handle input from other sources while the shell is
inactive waiting for terminal input.  It's all handled synchronously
within zle, so it should be free of the hazards of asynchronous input.

Unfortunately, this has to be part of the core zle, since it needs to
be tied into getkey(), so it's not an optional feature.

I've been getting good results with this so far (I don't even seem to
have screwed up key timeouts, yet!) but I want to do more work, even if
nobody else wants this, or would prefer it to be a compile-time option.
In particular, it might be better to make the list of fds and functions
a list rather than a pair of arrays.  Also, once again it's perfectly
possible to use poll() instead of select(), but I haven't bothered
adding it.

The could easily be more nasties lurking within the fact that the
call to the handler function is rather deep within zle.

Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.17
diff -u -r1.17 zle.yo
--- Doc/Zsh/zle.yo	5 Mar 2002 16:33:21 -0000	1.17
+++ Doc/Zsh/zle.yo	13 May 2002 15:18:49 -0000
@@ -314,6 +314,7 @@
 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(-I))
 xitem(tt(zle) var(widget) tt([ -n) var(num) tt(]) tt([ -N ]) var(args) ...)
 item(tt(zle))(
@@ -410,6 +411,65 @@
 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) ] ])(
+Only available if your system support the `select' system call; most
+modern systems do.
+
+Installs var(handler) (the name of a shell function) to handle input from
+file descriptor var(fd).  When zle is attempting to read data, it will
+examine both the terminal and the list of handled var(fd)'s.  If data
+becomes available on a handled var(fd), zle will call var(handler) with
+the fd which is ready for reading as the only argument.  If the handler
+produces output to the terminal, it should call `tt(zle -I)' before doing
+so (see below).  The handler should not attempt to read from the terminal.
+Note that zle makes no attempt to check whether this fd is actually
+readable when installing the handler.  The user must make their own
+arrangments for handling the file descriptor when zle is not active.
+
+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.
+
+If no var(handler) is given, but an var(fd) is present, any handler for
+that var(fd) is removed.  If there is none, an error message is printed
+and status 1 is returned.
+
+If no arguments are given, or the tt(-L) option is supplied, a list of
+handlers is printed in a form which can be stored for later execution.
+
+An var(fd) (but not a var(handler)) may optionally be given with the tt(-L)
+option; in this case, the function will list the handler if any, else
+silently return status 1.
+
+Note that this feature should be used with care.  Activity on one of the
+var(fd)'s which is not properly handled can cause the terminal to become
+unusable.
+
+Here is a simple example of using this feature.  A connection to a remote
+TCP port is created using the ztcp command; see 
+ifzman(the description of the tt(zsh/net/tcp) module in zmanref(zshmodules))\
+ifnzman(noderef(The zsh/net/tcp Module)).  Then a handler is installed
+which simply prints out any data which arrives on this connection.  Note
+that `select' will indicate that the file descriptor needs handling
+if the remote side has closed the connection; we handle that by testing
+for a failed read.
+example(if ztcp pwspc 2811; then
+  tcpfd=$REPLY
+  handler() {
+    zle -I
+    local line
+    if ! read line <&$1; then
+      # select marks this fd if we reach EOF,
+      # so handle this specially.
+      print "[Read on fd $1 failed, removing.]" >&2
+      zle -F $1
+      return 1
+    fi
+    print -r - $line
+  }
+  zle -F $tcpfd handler
+fi)
 )
 item(tt(-I))(
 Unusually, this option is only useful em(outside) ordinary widget functions.
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.22
diff -u -r1.22 zle_main.c
--- Src/Zle/zle_main.c	1 Mar 2002 10:42:02 -0000	1.22
+++ Src/Zle/zle_main.c	13 May 2002 15:18:49 -0000
@@ -141,6 +141,17 @@
 static int delayzsetterm;
 #endif
 
+/*
+ * File descriptors we are watching as well as the terminal fd. 
+ * These are all for reading; we don't watch for writes or exceptions.
+ */
+/**/
+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 */
+
 /* set up terminal */
 
 /**/
@@ -324,86 +335,169 @@
 # define read    breakread
 #endif
 
-/**/
-mod_export int
-getkey(int keytmout)
+static int
+raw_getkey(int keytmout, char *cptr)
 {
-    char cc;
-    unsigned int ret;
     long exp100ths;
-    int die = 0, r, icnt = 0;
-    int old_errno = errno, obreaks = breaks;
-
+    int ret;
 #ifdef HAVE_SELECT
     fd_set foofd;
-
 #else
 # ifdef HAS_TIO
     struct ttyinfo ti;
-
 # endif
 #endif
 
-    if (kungetct)
-	ret = STOUC(kungetbuf[--kungetct]);
-    else {
-#ifdef FIONREAD
-	if (delayzsetterm) {
-	    int val;
-	    ioctl(SHTTY, FIONREAD, (char *)&val);
-	    if (!val)
-		zsetterm();
-	}
-#endif
-	if (keytmout
+    /*
+     * Handle timeouts and watched fd's.  We only do one at once;
+     * key timeouts take precedence.  This saves tricky timing
+     * problems with the key timeout.
+     */
+    if ((nwatch || keytmout)
 #ifdef FIONREAD
-	    && ! delayzsetterm
+	&& ! delayzsetterm
 #endif
-	    ) {
-	    if (keytimeout > 500)
-		exp100ths = 500;
-	    else if (keytimeout > 0)
-		exp100ths = keytimeout;
-	    else
-		exp100ths = 0;
+	) {
+	if (!keytmout || keytimeout <= 0)
+	    exp100ths = 0;
+	else if (keytimeout > 500)
+	    exp100ths = 500;
+	else
+	    exp100ths = keytimeout;
 #ifdef HAVE_SELECT
+	if (!keytmout || exp100ths) {
+	    struct timeval *tvptr = NULL;
+	    struct timeval expire_tv;
+	    int i, fdmax = SHTTY, errtry = 0;
 	    if (exp100ths) {
-		struct timeval expire_tv;
-
 		expire_tv.tv_sec = exp100ths / 100;
 		expire_tv.tv_usec = (exp100ths % 100) * 10000L;
+		tvptr = &expire_tv;
+	    }
+	    do {
+		int selret;
 		FD_ZERO(&foofd);
 		FD_SET(SHTTY, &foofd);
-		if (select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
-			   NULL, NULL, &expire_tv) <= 0)
-		    return EOF;
-	    }
+		if (!keytmout && !errtry) {
+		    for (i = 0; i < nwatch; i++) {
+			int fd = watch_fds[i];
+			FD_SET(fd, &foofd);
+			if (fd > fdmax)
+			    fdmax = fd;
+		    }
+		}
+		selret = select(fdmax+1, (SELECT_ARG_2_T) & foofd,
+				NULL, NULL, tvptr);
+		/*
+		 * Try to avoid errors on our special fd's from
+		 * messing up reads from the terminal.  Try first
+		 * with all fds, then try unsetting the special ones.
+		 */
+		if (selret < 0 && !keytmout && !errtry) {
+		    errtry = 1;
+		    continue;
+		}
+		if (selret == 0) {
+		    /* Special value -2 signals nothing ready */
+		    return -2;
+		} else if (selret < 0)
+		    return selret;
+		if (!keytmout && nwatch) {
+		    /*
+		     * Copy the details of the watch fds in case the
+		     * user decides to delete one from inside the
+		     * handler function.
+		     */
+		    int lnwatch = nwatch;
+		    int *lwatch_fds = zalloc(lnwatch*sizeof(int));
+		    char **lwatch_funcs = zarrdup(watch_funcs);
+		    memcpy(lwatch_fds, watch_fds, lnwatch*sizeof(int));
+		    for (i = 0; i < lnwatch; i++) {
+			if (FD_ISSET(lwatch_fds[i], &foofd)) {
+			    /* Handle the fd. */
+			    LinkList funcargs = znewlinklist();
+			    zaddlinknode(funcargs, ztrdup(lwatch_funcs[i]));
+			    {
+				char buf[BDIGBUFSIZE];
+				convbase(buf, lwatch_fds[i], 10);
+				zaddlinknode(funcargs, ztrdup(buf));
+			    }
+
+			    callhookfunc(lwatch_funcs[i], funcargs);
+			    if (errflag) {
+				/* No sensible way of handling errors here */
+				errflag = 0;
+				/*
+				 * Paranoia: don't run the hooks again this
+				 * time.
+				 */
+				errtry = 1;
+			    }
+			    freelinklist(funcargs, freestr);
+			}
+		    }
+		    /* Function may have invalidated the display. */
+		    if (resetneeded)
+			zrefresh();
+		    zfree(lwatch_fds, lnwatch*sizeof(int));
+		    freearray(lwatch_funcs);
+		}
+	    } while (!FD_ISSET(SHTTY, &foofd));
+	}
 #else
 # ifdef HAS_TIO
-	    ti = shttyinfo;
-	    ti.tio.c_lflag &= ~ICANON;
-	    ti.tio.c_cc[VMIN] = 0;
-	    ti.tio.c_cc[VTIME] = exp100ths / 10;
+	ti = shttyinfo;
+	ti.tio.c_lflag &= ~ICANON;
+	ti.tio.c_cc[VMIN] = 0;
+	ti.tio.c_cc[VTIME] = exp100ths / 10;
 #  ifdef HAVE_TERMIOS_H
-	    tcsetattr(SHTTY, TCSANOW, &ti.tio);
+	tcsetattr(SHTTY, TCSANOW, &ti.tio);
 #  else
-	    ioctl(SHTTY, TCSETA, &ti.tio);
+	ioctl(SHTTY, TCSETA, &ti.tio);
 #  endif
-	    r = read(SHTTY, &cc, 1);
+	ret = read(SHTTY, cptr, 1);
 #  ifdef HAVE_TERMIOS_H
-	    tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
+	tcsetattr(SHTTY, TCSANOW, &shttyinfo.tio);
 #  else
-	    ioctl(SHTTY, TCSETA, &shttyinfo.tio);
+	ioctl(SHTTY, TCSETA, &shttyinfo.tio);
 #  endif
-	    return (r <= 0) ? EOF : cc;
+	return (ret <= 0) ? ret : *cptr;
 # endif
 #endif
+    }
+
+    ret = read(SHTTY, cptr, 1);
+
+    return ret;
+}
+
+/**/
+mod_export int
+getkey(int keytmout)
+{
+    char cc;
+    unsigned int ret;
+    int die = 0, r, icnt = 0;
+    int old_errno = errno, obreaks = breaks;
+
+    if (kungetct)
+	ret = STOUC(kungetbuf[--kungetct]);
+    else {
+#ifdef FIONREAD
+	if (delayzsetterm) {
+	    int val;
+	    ioctl(SHTTY, FIONREAD, (char *)&val);
+	    if (!val)
+		zsetterm();
 	}
+#endif
 	for (;;) {
 	    int q = queue_signal_level();
 	    dont_queue_signals();
-	    r = read(SHTTY, &cc, 1);
+	    r = raw_getkey(keytmout, &cc);
 	    restore_queue_signals(q);
+	    if (r == -2)	/* timeout */
+		return EOF;
 	    if (r == 1)
 		break;
 	    if (r == 0) {
@@ -1101,7 +1195,7 @@
 static struct builtin bintab[] = {
     BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLRp", NULL),
     BUILTIN("vared",   0, bin_vared,   1,  7, 0, NULL,             NULL),
-    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaUKI", NULL),
+    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "aAcCDFgGIKlLmMNRU", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
Index: Src/Zle/zle_thingy.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_thingy.c,v
retrieving revision 1.4
diff -u -r1.4 zle_thingy.c
--- Src/Zle/zle_thingy.c	3 Sep 2001 01:39:20 -0000	1.4
+++ Src/Zle/zle_thingy.c	13 May 2002 15:18:49 -0000
@@ -341,6 +341,7 @@
 	{ 'U', bin_zle_unget, 1, 1 },
 	{ 'K', bin_zle_keymap, 1, 1 },
 	{ 'I', bin_zle_invalidate, 0, 0 },
+	{ 'F', bin_zle_fd, 0, 2 },
 	{ 0,   bin_zle_call, 0, -1 },
     };
     struct opn const *op, *opp;
@@ -676,6 +677,108 @@
 	return 0;
     } else
 	return 1;
+}
+
+/**/
+static int
+bin_zle_fd(char *name, char **args, char *ops, char func)
+{
+    int fd = 0, i, found = 0;
+    char *endptr;
+
+    if (*args) {
+	fd = (int)zstrtol(*args, &endptr, 10);
+
+	if (*endptr || fd < 0) {
+	    zwarnnam(name, "Bad file descriptor number for -F: %s", *args, 0);
+	    return 1;
+	}
+    }
+
+    if (ops['L'] || !*args) {
+	/* Listing handlers. */
+	if (args[1]) {
+	    zwarnnam(name, "too many arguments for -FL", NULL, 0);
+	    return 1;
+	}
+	for (i = 0; i < nwatch; i++) {
+	    if (*args && watch_fds[i] != fd)
+		continue;
+	    found = 1;
+	    printf("%s -F %d %s\n", name, watch_fds[i], watch_funcs[i]);
+	}
+	/* only return status 1 if fd given and not found */
+	return *args && !found;
+    }
+
+    if (args[1]) {
+	/* Adding or replacing a handler */
+	char *funcnam = ztrdup(args[1]);
+	if (nwatch) {
+	    for (i = 0; i < nwatch; i++) {
+		if (watch_fds[i] == fd) {
+		    zsfree(watch_funcs[i]);
+		    watch_funcs[i] = funcnam;
+		    found = 1;
+		    break;
+		}
+	    }
+	}
+	if (!found) {
+	    /* zrealloc handles NULL pointers, so OK for first time through */
+	    int newnwatch = nwatch+1;
+	    watch_fds = (int *)zrealloc(watch_fds, 
+					newnwatch * sizeof(int));
+	    watch_funcs = (char **)zrealloc(watch_funcs,
+					    (newnwatch+1) * sizeof(char *));
+	    watch_fds[nwatch] = fd;
+	    watch_funcs[nwatch] = funcnam;
+	    watch_funcs[newnwatch] = NULL;
+	    nwatch = newnwatch;
+	}
+    } else {
+	/* Deleting a handler */
+	for (i = 0; i < nwatch; i++) {
+	    if (watch_fds[i] == fd) {
+		int newnwatch = nwatch-1;
+		int *new_fds;
+		char **new_funcs;
+
+		zsfree(watch_funcs[i]);
+		if (newnwatch) {
+		    new_fds = zalloc(newnwatch*sizeof(int));
+		    new_funcs = zalloc((newnwatch+1)*sizeof(char*));
+		    if (i) {
+			memcpy(new_fds, watch_fds, i*sizeof(int));
+			memcpy(new_funcs, new_fds, i*sizeof(char *));
+		    }
+		    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 *));
+		    }
+		    new_funcs[newnwatch] = NULL;
+		} else {
+		    new_fds = NULL;
+		    new_funcs = NULL;
+		}
+		zfree(watch_fds, nwatch*sizeof(int));
+		zfree(watch_funcs, (nwatch+1)*sizeof(char *));
+		watch_fds = new_fds;
+		watch_funcs = new_funcs;
+		nwatch = newnwatch;
+		found = 1;
+		break;
+	    }
+	}
+	if (!found) {
+	    zwarnnam(name, "No handler installed for fd %d", NULL, fd);
+	    return 1;
+	}
+    }
+
+    return 0;
 }
 
 /*******************/

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: PATCH: more selection
  2002-05-13 15:33 PATCH: more selection Peter Stephenson
@ 2002-05-14  9:48 ` Borsenkow Andrej
  2002-05-14 10:04   ` Peter Stephenson
  2002-05-14 11:37 ` Peter Stephenson
  2002-05-21 11:21 ` Peter Stephenson
  2 siblings, 1 reply; 7+ messages in thread
From: Borsenkow Andrej @ 2002-05-14  9:48 UTC (permalink / raw)
  To: Zsh hackers list

On Mon, 13 May 2002, Peter Stephenson wrote:

> This patch is more advanced warning of future pain than anything else,
> in case anyone wants to scream at the very idea.
>
> The following patch adds an fd-watching facility to zle.  You tell zle
> (via zle -F) to select on an fd and give it a function handler.  When data
> is available for reading on that handle (only reading, at the moment),
> the handler will be called, and zle will sail on without returning.
> This allows you to handle input from other sources while the shell is
> inactive waiting for terminal input.  It's all handled synchronously
> within zle, so it should be free of the hazards of asynchronous input.
>

Is it posible to extend it to set timeouts while waiting for input? This
could be used to update prompts as example (often asked question - how to
get time in prompt).

My only concern is that if there is any chance handler will block you can
just as well kill your shell - there is no way to give shell input
anymore.

-andrej


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: PATCH: more selection
  2002-05-14  9:48 ` Borsenkow Andrej
@ 2002-05-14 10:04   ` Peter Stephenson
  0 siblings, 0 replies; 7+ messages in thread
From: Peter Stephenson @ 2002-05-14 10:04 UTC (permalink / raw)
  To: Zsh hackers list

Borsenkow Andrej wrote:
> My only concern is that if there is any chance handler will block you can
> just as well kill your shell - there is no way to give shell input
> anymore.

Yes, you could use `read -t' to read from it.  But unless someone else
has been tinkering with the fd before the handler get's to look at it,
the result of the select assures you that the first read won't block.

There's some rudimentary support for recovery: if there's an error in
a handler (e.g. ^C), the error flag is unset and the select is tried
again with all the handlers removed (it could simply drop through to the
read).  It could be altered so that this actually uninstalled the
handler in question.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: PATCH: more selection
  2002-05-13 15:33 PATCH: more selection Peter Stephenson
  2002-05-14  9:48 ` Borsenkow Andrej
@ 2002-05-14 11:37 ` Peter Stephenson
  2002-05-21 11:21 ` Peter Stephenson
  2 siblings, 0 replies; 7+ messages in thread
From: Peter Stephenson @ 2002-05-14 11:37 UTC (permalink / raw)
  To: Zsh hackers list

Peter Stephenson wrote:
> This patch is more advanced warning of future pain than anything else,
> in case anyone wants to scream at the very idea.

Just realised --- the patch won't actually work because I've missed out
this change in utils.c.  As I said, it will be tweaked anyway.  (As
posted, for example, you need two ^C's to abort the current line, which
is clearly wrong.)

Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.39
diff -u -r1.39 utils.c
--- Src/utils.c	6 Jan 2002 01:07:23 -0000	1.39
+++ Src/utils.c	14 May 2002 11:35:59 -0000
@@ -624,6 +624,30 @@
 /**/
 time_t lastwatch;
 
+/**/
+mod_export int
+callhookfunc(char *name, LinkList lnklst)
+{
+    Eprog prog;
+
+    if ((prog = getshfunc(name)) != &dummy_eprog) {
+	/*
+	 * Save stopmsg, since user doesn't get a chance to respond
+	 * to a list of jobs generated in a hook.
+	 */
+	int osc = sfcontext, osm = stopmsg;
+
+	sfcontext = SFC_HOOK;
+	doshfunc(name, prog, lnklst, 0, 1);
+	sfcontext = osc;
+	stopmsg = osm;
+
+	return 0;
+    }
+
+    return 1;
+}
+
 /* do pre-prompt stuff */
 
 /**/
@@ -632,7 +656,6 @@
 {
     static time_t lastperiodic;
     LinkNode ln;
-    Eprog prog;
     int period = getiparam("PERIOD");
     int mailcheck = getiparam("MAILCHECK");
 
@@ -645,18 +668,7 @@
 
     /* If a shell function named "precmd" exists, *
      * then execute it.                           */
-    if ((prog = getshfunc("precmd")) != &dummy_eprog) {
-	/*
-	 * Save stopmsg, since user doesn't get a chance to respond
-	 * to a list of jobs generated in precmd.
-	 */
-	int osc = sfcontext, osm = stopmsg;
-
-	sfcontext = SFC_HOOK;
-	doshfunc("precmd", prog, NULL, 0, 1);
-	sfcontext = osc;
-	stopmsg = osm;
-    }
+    callhookfunc("precmd", NULL);
     if (errflag)
 	return;
 
@@ -664,14 +676,8 @@
      * "periodic" exists, 3) it's been greater than PERIOD since we *
      * executed "periodic", then execute it now.                    */
     if (period && (time(NULL) > lastperiodic + period) &&
-	(prog = getshfunc("periodic")) != &dummy_eprog) {
-	int osc = sfcontext;
-
-	sfcontext = SFC_HOOK;
-	doshfunc("periodic", prog, NULL, 0, 1);
-	sfcontext = osc;
+	!callhookfunc("periodic", NULL))
 	lastperiodic = time(NULL);
-    }
     if (errflag)
 	return;
 
-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: PATCH: more selection
  2002-05-13 15:33 PATCH: more selection Peter Stephenson
  2002-05-14  9:48 ` Borsenkow Andrej
  2002-05-14 11:37 ` Peter Stephenson
@ 2002-05-21 11:21 ` Peter Stephenson
  2002-05-21 12:48   ` Oliver Kiddle
  2 siblings, 1 reply; 7+ messages in thread
From: Peter Stephenson @ 2002-05-21 11:21 UTC (permalink / raw)
  To: Zsh hackers list

Peter Stephenson wrote:
> The following patch adds an fd-watching facility to zle.  You tell zle
> (via zle -F) to select on an fd and give it a function handler.  When data
> is available for reading on that handle (only reading, at the moment),
> the handler will be called, and zle will sail on without returning.
> This allows you to handle input from other sources while the shell is
> inactive waiting for terminal input.  It's all handled synchronously
> within zle, so it should be free of the hazards of asynchronous input.

This has been working smoothly for me for several days with multiple TCP
connections, so I've committed it, with small tweaks.  The chance of
fallout if you are not using the new feature is pretty small.

I've been putting together a function script that uses this to make a
front-end to remote connections, vaguely expect-like but with much
better interactive features.  It was designed so I can do on UNIX
remotely from a single existing zsh session what I used to have to do
with a set of completely different command line tools running under
Windows, but it is entirely general purpose; you could write a `talk'
tool integrated into zsh, for example.  It combines the use of ztcp,
zselect and zle -F.  I may or may not tidy it up and post it.

(A scan of the code shows it doesn't rely on fd multiplexing with zselect,
only with zle -F, so that part could be done without the module if we
implemented the bash version of `read -t <timeout>'.  It's annoying I
picked that letter for polling.)

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: PATCH: more selection
  2002-05-21 11:21 ` Peter Stephenson
@ 2002-05-21 12:48   ` Oliver Kiddle
  2002-05-21 13:11     ` Peter Stephenson
  0 siblings, 1 reply; 7+ messages in thread
From: Oliver Kiddle @ 2002-05-21 12:48 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh hackers list

On Tue, May 21, 2002 at 12:21:27PM +0100, Peter Stephenson wrote:

> only with zle -F, so that part could be done without the module if we
> implemented the bash version of `read -t <timeout>'.  It's annoying I
> picked that letter for polling.)

If the timeout is considered to be an optional argument, is there
really any conflict there? The timeout defaulting to zero would 
give exactly the same as current behaviour so it could be compatible
with both older zsh and bash/ksh93. right?

Oliver

This e-mail and any attachment is for authorised use by the intended recipient(s) only.  It may contain proprietary material, confidential information and/or be subject to legal privilege.  It should not be copied, disclosed to, retained or used by, any other party.  If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender.  Thank you.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: PATCH: more selection
  2002-05-21 12:48   ` Oliver Kiddle
@ 2002-05-21 13:11     ` Peter Stephenson
  0 siblings, 0 replies; 7+ messages in thread
From: Peter Stephenson @ 2002-05-21 13:11 UTC (permalink / raw)
  To: Zsh hackers list

Oliver Kiddle wrote:
> On Tue, May 21, 2002 at 12:21:27PM +0100, Peter Stephenson wrote:
> 
> > only with zle -F, so that part could be done without the module if we
> > implemented the bash version of `read -t <timeout>'.  It's annoying I
> > picked that letter for polling.)
> 
> If the timeout is considered to be an optional argument, is there
> really any conflict there? The timeout defaulting to zero would 
> give exactly the same as current behaviour so it could be compatible
> with both older zsh and bash/ksh93. right?

Yes, I was wondering about that.  The major objection at the moment is
that zsh's internal handling for options with arguments is awful ---
look at the hacks for dealing with read -k and read -u, similarly
typeset -i/-Z/-R/-L.  (I tried to combine read -k and -u and it took an
effort to work out what was happening.)  I've been hoping for ages
someone would fix this and save me having to do anything.

The neatest thing I can think of is turn ops into a union and do some
more sophisticated form of getopts string processing.  This increases
the stack usage for each execbuiltin() by some considerable amount,
however.  We can probably do something with the value of the individual
option value.  Currently 2 is used for turning off with `+', but scope
for something more.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 392070


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-05-21 13:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-13 15:33 PATCH: more selection Peter Stephenson
2002-05-14  9:48 ` Borsenkow Andrej
2002-05-14 10:04   ` Peter Stephenson
2002-05-14 11:37 ` Peter Stephenson
2002-05-21 11:21 ` Peter Stephenson
2002-05-21 12:48   ` Oliver Kiddle
2002-05-21 13:11     ` Peter Stephenson

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