zsh-workers
 help / color / mirror / code / Atom feed
* typeahead problem
@ 1998-12-08 12:38 Bernd Eggink
  1998-12-08 13:01 ` Andrej Borsenkow
  0 siblings, 1 reply; 11+ messages in thread
From: Bernd Eggink @ 1998-12-08 12:38 UTC (permalink / raw)
  To: zsh Workers

A sticking 'y' key on my keyboard revealed a weird zle behaviour which I
first assumed to be a bug, but after glancing through the sources turned
out to be a feature. In a script I have to process a long list of items,
and for each item there is a statement like

  read -q "REPLY?Yes or no: " && do_something

Now if "do_something" takes some time and you type at least one
character in advance, 'read -q' behaves as if you are constantly typing
'n', until you consume the pending character by a normal 'read'. In
other words, if you do NOT issue a normal read, EVERY following 'read
-q' will behave as if you had typed 'n', until the end of the script.

Is there a rationale for this feature  (which I still consider a bug,
because it makes 'read -q' nearly unusable, at least in scripts)?

Bernd

--
Bernd Eggink
Regionales Rechenzentrum der Uni Hamburg
eggink@rrz.uni-hamburg.de
http://www.rrz.uni-hamburg.de/eggink/BEggink.html


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

* RE: typeahead problem
  1998-12-08 12:38 typeahead problem Bernd Eggink
@ 1998-12-08 13:01 ` Andrej Borsenkow
  1998-12-08 14:07   ` Bernd Eggink
  0 siblings, 1 reply; 11+ messages in thread
From: Andrej Borsenkow @ 1998-12-08 13:01 UTC (permalink / raw)
  To: Bernd Eggink, zsh Workers

It is a "feature" of your particular OS. There is CLOBBERS_TYPEAHEAD define,
that tries to correct this. It gets set in configure for some systems. You
can try to recompile with this define set, and if it corrects your problem,
add setting for your system to configure.in.

/andrej




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

* Re: typeahead problem
  1998-12-08 13:01 ` Andrej Borsenkow
@ 1998-12-08 14:07   ` Bernd Eggink
  1998-12-08 14:30     ` Andrej Borsenkow
  0 siblings, 1 reply; 11+ messages in thread
From: Bernd Eggink @ 1998-12-08 14:07 UTC (permalink / raw)
  To: zsh Workers

Andrej Borsenkow wrote:
> 
> It is a "feature" of your particular OS. There is CLOBBERS_TYPEAHEAD define,
> that tries to correct this. It gets set in configure for some systems. You
> can try to recompile with this define set, and if it corrects your problem,
> add setting for your system to configure.in.
> 
> /andrej

In Linux and AIX 4.2 there is no difference in the behaviour whether or
not I define CLOBBERS_TYPEAHEAD in config.h. Hm, is that the right
location? I also added "x-*-linux*" to the switch in the "TYPEAHEAD
KLUDGE" section in configure.in, but that didn't change anything either.

Bernd

--
Bernd Eggink
Regionales Rechenzentrum der Uni Hamburg
eggink@rrz.uni-hamburg.de
http://www.rrz.uni-hamburg.de/eggink/BEggink.html


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

* RE: typeahead problem
  1998-12-08 14:07   ` Bernd Eggink
@ 1998-12-08 14:30     ` Andrej Borsenkow
  1998-12-08 15:08       ` Bernd Eggink
  0 siblings, 1 reply; 11+ messages in thread
From: Andrej Borsenkow @ 1998-12-08 14:30 UTC (permalink / raw)
  To: Bernd Eggink, zsh Workers


>
> In Linux and AIX 4.2 there is no difference in the behaviour whether or
> not I define CLOBBERS_TYPEAHEAD in config.h. Hm, is that the right
> location? I also added "x-*-linux*" to the switch in the "TYPEAHEAD
> KLUDGE" section in configure.in, but that didn't change anything either.
>


Sorry, it is unrelated to typeahead probleam, I had to read better :(

I tried it here with 3.1.5 + patches. It looks, like ZSH takes the first
character on the line and ignores the rest.

while read -q && sleep 10
do
echo YES
done
y <- cursor immediately springs to the next line
yyyYES
      ^^^ output by ZSH
<- note newline
YES

Only first 'y' from 'yyy' is taken. Is it what you've seen?

Well, manual says "read -q reads only one character" so it is really
confusing. Currently it "reads the line and takes the first character".
Who's wrong - binary or manual?

/andrej



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

* Re: typeahead problem
  1998-12-08 14:30     ` Andrej Borsenkow
@ 1998-12-08 15:08       ` Bernd Eggink
  1998-12-08 15:54         ` Andrej Borsenkow
  0 siblings, 1 reply; 11+ messages in thread
From: Bernd Eggink @ 1998-12-08 15:08 UTC (permalink / raw)
  To: zsh Workers

Andrej Borsenkow wrote:
> 
> >
> > In Linux and AIX 4.2 there is no difference in the behaviour whether or
> > not I define CLOBBERS_TYPEAHEAD in config.h. Hm, is that the right
> > location? I also added "x-*-linux*" to the switch in the "TYPEAHEAD
> > KLUDGE" section in configure.in, but that didn't change anything either.
> >
> 
> Sorry, it is unrelated to typeahead probleam, I had to read better :(
> 
> I tried it here with 3.1.5 + patches. It looks, like ZSH takes the first
> character on the line and ignores the rest.
> 
> while read -q && sleep 10
> do
> echo YES
> done
> y <- cursor immediately springs to the next line
> yyyYES
>       ^^^ output by ZSH
> <- note newline
> YES
> 
> Only first 'y' from 'yyy' is taken. Is it what you've seen?

No. For example, try this script:

  for i in {1..}
  do if read -q "REPLY?y/n: "
     then print yes
     else print no
     fi
     sleep 1
  done

After the first prompt, type aa quickly (or any other characters). On
Linux and AIX, I get

  y/n: a
  no
  ay/n: n
  no
  ay/n: n
  no
  ay/n: n
  no
  ay/n: n
  no
  $ a

where $ stands for the shell prompt.

I guess the problem is getzlequery() in Zle/zle_utils.c. The comment
says: "If there are any characters in the buffer, this is taken as a
negative response, and no characters are read." This sounds like an
exact description of what happens, and doesn't seem to make much sense.
Why aren't the characters in the buffer read?? OTOH, there is no such
bug on HP-UP, so I hesitate to hack the sources blindly...

Bernd

--
Bernd Eggink
Regionales Rechenzentrum der Uni Hamburg
eggink@rrz.uni-hamburg.de
http://www.rrz.uni-hamburg.de/eggink/BEggink.html


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

* RE: typeahead problem
  1998-12-08 15:08       ` Bernd Eggink
@ 1998-12-08 15:54         ` Andrej Borsenkow
  1998-12-08 17:39           ` Bernd Eggink
  1998-12-08 18:06           ` Bart Schaefer
  0 siblings, 2 replies; 11+ messages in thread
From: Andrej Borsenkow @ 1998-12-08 15:54 UTC (permalink / raw)
  To: Bernd Eggink, zsh Workers

>
> No. For example, try this script:
>
>   for i in {1..}
>   do if read -q "REPLY?y/n: "
>      then print yes
>      else print no
>      fi
>      sleep 1
>   done
>
> After the first prompt, type aa quickly (or any other characters). On
> Linux and AIX, I get
>
>   y/n: a
>   no
>   ay/n: n
>   no
>   ay/n: n
>   no
>   ay/n: n
>   no
>   ay/n: n
>   no
>   $ a
>

On 3.1.5-patched I cannot reproduce it. It behaves exactly as I described.
It _smells_ like CLOBBERS_TYPEAHED though ...

> where $ stands for the shell prompt.
>
> I guess the problem is getzlequery() in Zle/zle_utils.c. The comment
> says: "If there are any characters in the buffer, this is taken as a
> negative response, and no characters are read."

No, what is called is getquery(); zlegetquery() is used only when you have
too long completion list.

 guess, this happens exactly because your system does _not_ clobbers
typeahed :)) getquery() can be told to purge input - but read -q does not do
it; it sees typeahed, takes it for "no", and then is called again - but
nothing was ever read from terminal, so it sees the same input again ...

As to why it is taken for "no" - imagine, you typed something _before_
read -q, and that was not completely consumed - you definitely does not want
some leftover "y" to remove your valuable files :) so it tries to play safe.

The only thing I don't understand, why it works on my system ...

This sounds like an
> exact description of what happens, and doesn't seem to make much sense.
> Why aren't the characters in the buffer read?? OTOH, there is no such
> bug on HP-UP, so I hesitate to hack the sources blindly...
>

there is not on my system as well ... but funnily enough, it probably means
a bug on my system :))  The ultimate place to correct it is bin_read(); call
getquery with last argument 1.

/andrej


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

* Re: typeahead problem
  1998-12-08 15:54         ` Andrej Borsenkow
@ 1998-12-08 17:39           ` Bernd Eggink
  1998-12-08 18:06           ` Bart Schaefer
  1 sibling, 0 replies; 11+ messages in thread
From: Bernd Eggink @ 1998-12-08 17:39 UTC (permalink / raw)
  To: Zsh-workers

Andrej Borsenkow wrote:
 
> As to why it is taken for "no" - imagine, you typed something _before_
> read -q, and that was not completely consumed - you definitely does not want
> some leftover "y" to remove your valuable files :) so it tries to play safe.

But of course the prompt could as well have been "Do you want to keep
the file?"! IMHO it would be safer to discard all previously typed
characters before querying.

> The only thing I don't understand, why it works on my system ...

You're lucky. I don't understand a LOT of things! ;)

> The ultimate place to correct it is bin_read(); call
> getquery with last argument 1.

Yeah, that fixes it! Thanks! 
Hm, is there any reason to call getquery(x, 0) at all?

Bernd 

--
Bernd Eggink
Regionales Rechenzentrum der Uni Hamburg
eggink@uni-hamburg.de
http://www.rrz.uni-hamburg.de/eggink/BEggink.html


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

* Re: typeahead problem
  1998-12-08 15:54         ` Andrej Borsenkow
  1998-12-08 17:39           ` Bernd Eggink
@ 1998-12-08 18:06           ` Bart Schaefer
  1998-12-08 18:38             ` Andrej Borsenkow
  1998-12-08 18:38             ` Bernd Eggink
  1 sibling, 2 replies; 11+ messages in thread
From: Bart Schaefer @ 1998-12-08 18:06 UTC (permalink / raw)
  To: Bernd Eggink, zsh Workers, Andrej Borsenkow

On Dec 8,  1:38pm, Bernd Eggink wrote:
} Subject: typeahead problem
}
}   read -q "REPLY?Yes or no: " && do_something
} 
} Now if "do_something" takes some time and you type at least one
} character in advance, 'read -q' behaves as if you are constantly typing
} 'n', until you consume the pending character by a normal 'read'. In
} other words, if you do NOT issue a normal read, EVERY following 'read
} -q' will behave as if you had typed 'n', until the end of the script.
} 
} Is there a rationale for this feature  (which I still consider a bug,
} because it makes 'read -q' nearly unusable, at least in scripts)?

Andrej has been telling you mostly the right things ...

On Dec 8,  6:54pm, Andrej Borsenkow wrote:
} As to why it is taken for "no" - imagine, you typed something _before_
} read -q, and that was not completely consumed - you definitely does not want
} some leftover "y" to remove your valuable files :) so it tries to play safe.

The getquery() function is called for the `rm *` check (the one DISabled
by `setopt rmstarsilent`) and for spell checking (`setopt correct`) as
well as for read -q.  In those cases, typeahead is considered undesirable,
and in the spell-check case zsh wants to leave it available in case the
user intended it as input for the command.  In the `rm *` case, on systems
that support ioctl(FIONREAD), zsh consumes all the typeahead before it
prints the query.

On systems that don't support FIONREAD, zsh always consumes one character.

The question is which of those two cases `read -q` should emulate.  The
decision made was to treat it like spell checking, leaving the typeahead
alone when possible so that other commands may consume it.  The way you
get the "always consume one character" behavior is to use

	read -k1 "REPLY?Yes or no: " && do_something

so having `read -q` available as an alternative that does NOT consume any
characters is more flexible.  The problem this leaves that there's no way
to emulate "consume typeahead" from a script (because all other reads are
blocking and wait for a newline).

On Dec 8,  4:01pm, Andrej Borsenkow wrote:
} Subject: RE: typeahead problem
}
} It is a "feature" of your particular OS. There is CLOBBERS_TYPEAHEAD define,
} that tries to correct this.

Unfortunately, CLOBBERS_TYPEAHEAD only applies when zle is setting up the
terminal with zsetterm(), which doesn't happen during getquery().

On Dec 8,  5:30pm, Andrej Borsenkow wrote:
} Subject: RE: typeahead problem
}
} I tried it here with 3.1.5 + patches. It looks, like ZSH takes the first
} character on the line and ignores the rest.
} 
} while read -q && sleep 10
} do
} echo YES
} done
} y <- cursor immediately springs to the next line
} yyyYES
}       ^^^ output by ZSH
} <- note newline
} YES
} 
} Only first 'y' from 'yyy' is taken. Is it what you've seen?

I see the following in a patched 3.0.5 and in both patched and unpatched
3.1.5:

zagzig% while read -q && sleep 5
while> do echo YES; done
y				<-- newline echoed immediately
yyyYES				<-- I typed yyy, YES echoed after 5 sec.
n				<-- echoed immediately after YES
zagzig% yyy			<-- typeahead now appears at the prompt

} Well, manual says "read -q reads only one character" so it is really
} confusing. Currently it "reads the line and takes the first character".
} Who's wrong - binary or manual?

On my system, at least, zsh does not consume the line, only the first y
of the four that I typed.  That agrees with the manual, except that the
manual doesn't discuss the typeahead behavior.

On Dec 8,  6:54pm, Andrej Borsenkow wrote:
} Subject: RE: typeahead problem
}
} The ultimate place to correct it is bin_read(); call
} getquery with last argument 1.

That would indeed change the behavior, but only when FIONREAD is supported.

On Dec 8,  6:39pm, Bernd Eggink wrote:
} Subject: Re: typeahead problem
}
} Hm, is there any reason to call getquery(x, 0) at all?

I think the choice to pass purge==0 was partly to get consistent script
behavior regardless of the availablilty of FIONREAD.

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


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

* RE: typeahead problem
  1998-12-08 18:06           ` Bart Schaefer
@ 1998-12-08 18:38             ` Andrej Borsenkow
  1998-12-08 18:38             ` Bernd Eggink
  1 sibling, 0 replies; 11+ messages in thread
From: Andrej Borsenkow @ 1998-12-08 18:38 UTC (permalink / raw)
  To: Bart Schaefer, zsh Workers



> -----Original Message-----
> From: Bart Schaefer [mailto:schaefer@brasslantern.com]
>
>
> I see the following in a patched 3.0.5 and in both patched and unpatched
> 3.1.5:
>
> zagzig% while read -q && sleep 5
> while> do echo YES; done
> y				<-- newline echoed immediately
> yyyYES				<-- I typed yyy, YES echoed
> after 5 sec.
> n				<-- echoed immediately after YES
> zagzig% yyy			<-- typeahead now appears at the prompt
>
> } Well, manual says "read -q reads only one character" so it is really
> } confusing. Currently it "reads the line and takes the first character".
> } Who's wrong - binary or manual?
>
> On my system, at least, zsh does not consume the line, only the first y
> of the four that I typed.  That agrees with the manual, except that the
> manual doesn't discuss the typeahead behavior.
>

I know now, what happens here. See later

> I think the choice to pass purge==0 was partly to get consistent script
> behavior regardless of the availablilty of FIONREAD.
>

Unfortunately, it's not consistent. Consistent would be to read the first
character of typeahead.

About why it works and does not work.

getquery() changes tty modes, and on some systems that flushes unread input
("clobber typeahead") Looks, like my system is so fast, that even if I type
several characters, the first one is read by _first_ read -q, then the
second is read by the _second_ read -q and the others are simply lost.

In other words, if system does have FIONREAD but clobbers typeahead, zsh
always reads the first character and forgets the rest. CLOBBER_TYPEAHED is
used in zsetterm() but not in getquery() ... I think it is quite possible
... Well, do we need to change modes (setcbreak()) _before_ doing read? that
is, if FIONREAD is defined we check and either output NL
and return or read up typeahead and go on. the same, if we read the first
character of typeahead instead of assuming "no".

/andrej


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

* Re: typeahead problem
  1998-12-08 18:06           ` Bart Schaefer
  1998-12-08 18:38             ` Andrej Borsenkow
@ 1998-12-08 18:38             ` Bernd Eggink
  1998-12-08 21:22               ` Bart Schaefer
  1 sibling, 1 reply; 11+ messages in thread
From: Bernd Eggink @ 1998-12-08 18:38 UTC (permalink / raw)
  To: zsh Workers

Bart Schaefer wrote:
 
> The question is which of those two cases `read -q` should emulate.  The
> decision made was to treat it like spell checking, leaving the typeahead
> alone when possible so that other commands may consume it.  

IMHO this decision was wrong, but it's probabely too late now. The
situation when I noticed that behaviour was in a loop consisting of
about 100 successive 'read -q' queries. ONE false move, and ALL
remaining questions get the answer 'no'. This can have very harmful
consequences, whereas not being able to type something in advance for
the next command is just a minor inconvenience.

> The way you
> get the "always consume one character" behavior is to use
> 
>         read -k1 "REPLY?Yes or no: " && do_something

Hm, no. You have to write something like

	typeset -u REPLY
	read -k1 "REPLY?Yes or no: "
	[[ $REPLY == Y ]] && do_something

But apart from that you're right, of course.

Regards,
Bernd 

--
Bernd Eggink
Regionales Rechenzentrum der Uni Hamburg
eggink@uni-hamburg.de
http://www.rrz.uni-hamburg.de/eggink/BEggink.html


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

* Re: typeahead problem
  1998-12-08 18:38             ` Bernd Eggink
@ 1998-12-08 21:22               ` Bart Schaefer
  0 siblings, 0 replies; 11+ messages in thread
From: Bart Schaefer @ 1998-12-08 21:22 UTC (permalink / raw)
  To: Andrej Borsenkow, zsh Workers, Bernd Eggink

On Dec 8,  9:38pm, Andrej Borsenkow wrote:
> Subject: RE: typeahead problem
> 
> > I think the choice to pass purge==0 was partly to get consistent script
> > behavior regardless of the availablilty of FIONREAD.
> 
> Unfortunately, it's not consistent. Consistent would be to read the first
> character of typeahead.
> 
> About why it works and does not work.
> 
> getquery() changes tty modes, and on some systems that flushes unread input
> ("clobber typeahead") Looks, like my system is so fast, that even if I type
> several characters, the first one is read by _first_ read -q, then the
> second is read by the _second_ read -q and the others are simply lost.

Your machine executes "sleep 10" so quickly that you can't type before it
finishes?

> In other words, if system does have FIONREAD but clobbers typeahead, zsh
> always reads the first character and forgets the rest.

That shouldn't be how it works.  If the system clobbers typeahead in the
way described in Src/Zle/zle_main.c, then the typeahead should get lost
before getquery() has a chance to read even the first character.

However, it is the case that zsetterm() and getquery() are inconsistent
about their use of FIONREAD.  zsetterm() calls ioctl(FIONREAD) _before_
attaching to the TTY, whereas getquery() attaches first and then calls
ioctl().  If the zsetterm() code doesn't cause a problem with spurious
SIGTTIN and SIGTTOU signals, it should be safe to move the FIONREAD code
in getquery() to above the attachtty() and setcbreak().

> CLOBBER_TYPEAHED is used in zsetterm() but not in getquery() ...

Yes, but that doesn't make any difference [except for the inconsistency
I just noted], because getquery() already performs an equivalent test on
the value obtained from ioctl(FIONREAD).

> ... Well, do we need to change modes (setcbreak()) _before_ doing read?

Yes, but apparently not before doing ioctl(FIONREAD).

On Dec 8,  7:38pm, Bernd Eggink wrote:
> Subject: Re: typeahead problem
> Bart Schaefer wrote:
>  
> > The question is which of those two cases `read -q` should emulate.  The
> > decision made was to treat it like spell checking, leaving the typeahead
> > alone when possible so that other commands may consume it.  
> 
> IMHO this decision was wrong, but it's probabely too late now.

Actually, I don't get the impression that `read -q` is all that widely
used, and as it's already inconsistent depending on FIONREAD, this might
be a reasonable change.  We should probably float it on zsh-users first,
though.

> > get the "always consume one character" behavior is to use
> > 
> >         read -k1 "REPLY?Yes or no: " && do_something
> 
> Hm, no. You have to write something like
> 
> 	typeset -u REPLY
> 	read -k1 "REPLY?Yes or no: "
> 	[[ $REPLY == Y ]] && do_something

Well, yes, but you should still test for success of read.  I assumed you
were already testing $REPLY inside "do_something" ... if you don't need
the answer captured in $REPLY, you can just do

	read -q "?Yes or no: " && ...


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

end of thread, other threads:[~1998-12-08 21:25 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-12-08 12:38 typeahead problem Bernd Eggink
1998-12-08 13:01 ` Andrej Borsenkow
1998-12-08 14:07   ` Bernd Eggink
1998-12-08 14:30     ` Andrej Borsenkow
1998-12-08 15:08       ` Bernd Eggink
1998-12-08 15:54         ` Andrej Borsenkow
1998-12-08 17:39           ` Bernd Eggink
1998-12-08 18:06           ` Bart Schaefer
1998-12-08 18:38             ` Andrej Borsenkow
1998-12-08 18:38             ` Bernd Eggink
1998-12-08 21:22               ` 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).