zsh-workers
 help / color / mirror / code / Atom feed
* minor 'select' snag
@ 2016-02-14 23:05 Martijn Dekker
  2016-02-15 12:48 ` Peter Stephenson
  2016-02-15 16:46 ` Bart Schaefer
  0 siblings, 2 replies; 5+ messages in thread
From: Martijn Dekker @ 2016-02-14 23:05 UTC (permalink / raw)
  To: zsh-workers

I'm analysing the behaviour of 'select' in various shells and found a a
way in which it's different in zsh from bash, ksh93 and {pd,m}ksh.

If a user presses Ctrl-D (EOF) within a 'select' loop, the REPLY
variable is left unchanged on zsh. On the other shells with 'select', it
is cleared, which is the same behaviour as 'read' (including 'read' on
zsh) and seems more logical. This makes it possible to decide whether to
continue after the loop by testing for the emptiness of $REPLY without
having to initialise it before entering the loop. It would be nice if
this worked the same way on zsh.

Thanks,

- M.

(Note of possible side interest: My experimental cross-platform shell
library, "modernish" <http://github.com/modernish/modernish> has a
module providing its own 'select' implementation for POSIX shells. It
mimics native implementations as closely as possible. On bash, *ksh and
zsh, the module does nothing except a check for a particular shell bug.
End result: all POSIX shells can use 'select'. There are just some minor
differences to account for, including the above-mentioned one.)


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

* Re: minor 'select' snag
  2016-02-14 23:05 minor 'select' snag Martijn Dekker
@ 2016-02-15 12:48 ` Peter Stephenson
  2016-02-15 17:01   ` Bart Schaefer
  2016-09-26 16:59   ` Martijn Dekker
  2016-02-15 16:46 ` Bart Schaefer
  1 sibling, 2 replies; 5+ messages in thread
From: Peter Stephenson @ 2016-02-15 12:48 UTC (permalink / raw)
  To: zsh-workers

On Mon, 15 Feb 2016 00:05:06 +0100
Martijn Dekker <martijn@inlv.org> wrote:
> I'm analysing the behaviour of 'select' in various shells and found a a
> way in which it's different in zsh from bash, ksh93 and {pd,m}ksh.
> 
> If a user presses Ctrl-D (EOF) within a 'select' loop, the REPLY
> variable is left unchanged on zsh. On the other shells with 'select', it
> is cleared, which is the same behaviour as 'read' (including 'read' on
> zsh) and seems more logical. This makes it possible to decide whether to
> continue after the loop by testing for the emptiness of $REPLY without
> having to initialise it before entering the loop. It would be nice if
> this worked the same way on zsh.

This looks easy.  I don't think there's any existing moral right to
expect REPLY to be unaffected in such circumstances.

diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo
index 2a76964..7488829 100644
--- a/Doc/Zsh/grammar.yo
+++ b/Doc/Zsh/grammar.yo
@@ -279,8 +279,10 @@ is set to the var(word) corresponding to this number.
 If this line is empty, the selection list is printed again.
 Otherwise, the value of the parameter var(name) is set to null.
 The contents of the line read from standard input is saved
-in the parameter tt(REPLY).  var(list) is executed
-for each selection until a break or end-of-file is encountered.
+in the parameter tt(REPLY); this is set to the empty string if no
+input was done for the benefit of code following the tt(select).
+var(list) is executed for each selection until a break or end-of-file is
+encountered.
 )
 cindex(subshell)
 item(tt(LPAR()) var(list) tt(RPAR()))(
diff --git a/Src/loop.c b/Src/loop.c
index 19d7f73..dd4b282 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -224,6 +224,7 @@ execselect(Estate state, UNUSED(int do_exec))
     size_t more;
     LinkList args;
     int old_simple_pline = simple_pline;
+    int reply_set = 0;
 
     /* See comments in execwhile() */
     simple_pline = 1;
@@ -303,6 +304,7 @@ execselect(Estate state, UNUSED(int do_exec))
 	    more = selectlist(args, more);
 	}
 	setsparam("REPLY", ztrdup(str));
+	reply_set = 1;
 	i = atoi(str);
 	if (!i)
 	    str = "";
@@ -327,6 +329,8 @@ execselect(Estate state, UNUSED(int do_exec))
 	    break;
     }
   done:
+    if (!reply_set)
+	setsparam("REPLY", ztrdup(""));
     cmdpop();
     popheap();
     fclose(inp);


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

* Re: minor 'select' snag
  2016-02-14 23:05 minor 'select' snag Martijn Dekker
  2016-02-15 12:48 ` Peter Stephenson
@ 2016-02-15 16:46 ` Bart Schaefer
  1 sibling, 0 replies; 5+ messages in thread
From: Bart Schaefer @ 2016-02-15 16:46 UTC (permalink / raw)
  To: zsh-workers

On Feb 15, 12:05am, Martijn Dekker wrote:
}
} If a user presses Ctrl-D (EOF) within a 'select' loop, the REPLY
} variable is left unchanged on zsh. On the other shells with 'select', it
} is cleared, which is the same behaviour as 'read' (including 'read' on
} zsh) and seems more logical.

There are several other differenced of "select" from "read".  For example
zsh's "select" will accept a maximum of 256 bytes of input, doesn't do
any special handling of multibyte characters, won't allow a line to be
continued with a backslash, etc.  In bash,

    select foo in a b c; do loopbody; done

seems to be equivalent to

    while read "?$PS3"; do
     case $REPLY in (1) foo=a;; (2) foo=b;; (3) foo=c;; (*) foo="";; esac
     loopbody
    done

Zsh also prints an extra newline after the select is done.


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

* Re: minor 'select' snag
  2016-02-15 12:48 ` Peter Stephenson
@ 2016-02-15 17:01   ` Bart Schaefer
  2016-09-26 16:59   ` Martijn Dekker
  1 sibling, 0 replies; 5+ messages in thread
From: Bart Schaefer @ 2016-02-15 17:01 UTC (permalink / raw)
  To: zsh-workers

On Feb 15, 12:48pm, Peter Stephenson wrote:
}
} This looks easy.  I don't think there's any existing moral right to
} expect REPLY to be unaffected in such circumstances.

It's actually even easier than what you did, setting REPLY="" right
before the "goto done" will cover it.

However, see my other email.  We might want to re-implment execselect()
by [the equivalent of] calling bin_read() instead of managing this here.


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

* Re: minor 'select' snag
  2016-02-15 12:48 ` Peter Stephenson
  2016-02-15 17:01   ` Bart Schaefer
@ 2016-09-26 16:59   ` Martijn Dekker
  1 sibling, 0 replies; 5+ messages in thread
From: Martijn Dekker @ 2016-09-26 16:59 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1429 bytes --]

Op 15-02-16 om 12:48 schreef Peter Stephenson:
> On Mon, 15 Feb 2016 00:05:06 +0100
> Martijn Dekker <martijn@inlv.org> wrote:
>> I'm analysing the behaviour of 'select' in various shells and found a a
>> way in which it's different in zsh from bash, ksh93 and {pd,m}ksh.
>>
>> If a user presses Ctrl-D (EOF) within a 'select' loop, the REPLY
>> variable is left unchanged on zsh. On the other shells with 'select', it
>> is cleared, which is the same behaviour as 'read' (including 'read' on
>> zsh) and seems more logical. This makes it possible to decide whether to
>> continue after the loop by testing for the emptiness of $REPLY without
>> having to initialise it before entering the loop. It would be nice if
>> this worked the same way on zsh.
> 
> This looks easy.  I don't think there's any existing moral right to
> expect REPLY to be unaffected in such circumstances.

This is from February and no action seems to have been taken since. I
spent some time looking into it now. Please consider the simple patch
attached. It makes zsh 'select' act exactly like bash and *ksh: if user
presses Ctrl-D (EOF), the REPLY variable is cleared, but if there is an
interrupt or error (e.g. Ctrl+C) the REPLY variable remains unaffected.

To reiterate, this makes it possible to check for EOF by checking the
emptiness of REPLY without having to manually initialise REPLY first,
like on bash, ksh93 and mksh.

Thanks,

- Martijn


[-- Attachment #2: select.patch --]
[-- Type: text/x-patch, Size: 406 bytes --]

diff --git a/Src/loop.c b/Src/loop.c
index fa7602e..3b9d021 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -289,6 +289,8 @@ execselect(Estate state, UNUSED(int do_exec))
 	    	}
 	    } else
 		str = (char *)getlinknode(bufstack);
+            if (!str && !errflag)
+                setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */
 	    if (!str || errflag) {
 		if (breaks)
 		    breaks--;

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

end of thread, other threads:[~2016-09-26 18:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-14 23:05 minor 'select' snag Martijn Dekker
2016-02-15 12:48 ` Peter Stephenson
2016-02-15 17:01   ` Bart Schaefer
2016-09-26 16:59   ` Martijn Dekker
2016-02-15 16:46 ` Bart Schaefer

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