I was looking at code (as used in prolog_pack.pl
) to query the user for a Y/N answer.
This code doesn’t use line discipline whereby the input needs to be terminated by a EOL (that would be the case when reading user input via read_line_to_string/2 for example) but just gets the next character from “the input buffer” (not sure who provides that, but it’s somewhere) with get_single_char/1 :
read_yes_no(YesNo, Default) :-
get_single_char(Code),
code_yes_no(Code, Default, YesNo),
!.
code_yes_no(0'y, _, yes).
code_yes_no(0'Y, _, yes).
code_yes_no(0'n, _, no).
code_yes_no(0'N, _, no).
code_yes_no(_, none, _) :- !, fail.
code_yes_no(C, Default, Default) :-
answered_default(C).
answered_default(0'\r).
answered_default(0'\n).
answered_default(0'\s).
get_single_char/1 blocks until there is something in the buffer (or an EOF is signalled).
Here lies a problem: If the user typed y
twice on a preceding question, the the second y
will be picked up by the get_single_char/1 meant for the subsequent question. This leads to erroneous results (that’s a problem that does not occur when reading read_line_to_string/2 as the user has to hit RETURN at least, so I really prefer read_line_to_string/2, which also works nicely with a pipe-from-the-yes
-command).
To make sure I’m getting the right y
, I want to drain the input buffer before starting with the next question, i.e. read characters in non-blocking mode until no characters are left, then ask. (What happens if someone pipes an infinite stream of y
into the program? I guess that would be bad and subject to random outcomes.)
Is it possible to read characters in non-blocking mode?
The library for Primitive character I/O doesn’t seem to provide such a facility.
Indeed, even in C, you need to do a call to fcntl
: Nonblocking Get Character
Note that I’m not even sure in which regime I’m working here:
the POSIX manual and all other related documentation explicitly says never to mix IO done on
FILE*
s and file descriptors
This is probably working on top of the filedescriptors (i.e. man 3P read
).