How does one read keyboard input using SWI-prolog without local echo, specifically the arrow keys?

Hi everyone,

My question is old (16 years ago) … I got something in
https://swi-prolog.iai.uni-bonn.narkive.com/Sx1Ehw6M/keyboard-input, where Jan and others answered, but I would resume it,
once that I need a small game that accept ONLY arrows (left right up and dow).

I am using the predicate get_single_char(Y), as the main predicate to get the key pressed.

I am running in a Linux console… directly such:
swipl -t main -q -f readings_keyboard.pl

Inside of Swipl interpreter some times runs fine …:upside_down_face::face_with_raised_eyebrow:

HERE the ALL code for test:
My code looks like this:

%----------------------------------------------------------------------------------------
% to run directly ....$ swipl -t main -q -f readings_keyboard.pl 

main :- menu(z).
main.

menu( e ):- format("\n EXIT \n"), halt.    /* to finish the menu */
menu( _ ) :-
  % shell('clear'),
	repeat,   nl,
	%%%tty_clear,
	write('  <<< Menu >>>    '), nl,
	write('  xxxxxxxx        '), nl,
	write('  xxxxxxxx        '), nl,
	write(' e - To finish (eND)       '), nl,
	write(' Press: ^,v,>,< (right arrows) or e (exit) ==> '),
	my_read_option(R),
	action(R),
	%get_single_char(_),
	menu(R).     /* recursive call */

my_read_option(X) :- 
    ttyflush,
    get_single_char(Y), %% works 
    atom_char(X,Y), %%% OK
	  format("\n keypressed ==> ~w ~w",[X,Y]),
	  member(X,[ e,'A','B','C','D','E' ]).
  
action('A') :- format("\n UP").    %% 65 
action('B') :- format("\n DOWN").
action('C') :- format("\n RIGHT").
action('D') :- format("\n LEFT").   % 68
action(e).	 %% END
action('E') :- format("\n EXIT \n"), halt.   % 68
action(X) :- 
      atom_char(X,Y), %%% OK 
      format("\n YOU pressed ==> ~w ~w (ONLY ARROWS and e)",[X,Y]),
      get_single_char(_).
%----------------------------------------------------------------------------------------

The OUTPUT:

For example: pressing the RIGHT arrow … comes 3 codes or 3 values …

Press: ^,v,>,< (right arrows) or e (exit) ==>
keypressed ==> 7
<<< Menu >>>
xxxxxxxx
xxxxxxxx
e - To finish (eND)
Press: ^,v,>,< (right arrows) or e (exit) ==>
keypressed ==> [ 91
<<< Menu >>>
xxxxxxxx
xxxxxxxx
e - To finish (eND)
Press: ^,v,>,< (right arrows) or e (exit) ==>
keypressed ==> C 67
RIGHT
<<< Menu >>>
xxxxxxxx
xxxxxxxx
e - To finish (eND)
Press: ^,v,>,< (right arrows) or e (exit) ==>
keypressed ==> e 101
EXIT

So, when the pressed RIGHT ARROW, comes the code 7, 91 (or [) and 67 (or C) … only this last is interested or I would get.

How could get this CHAR or ARROW just in this last part?
A, B, C or D (arrows key)

Some another interesting predicate instead of
get_single_char(Y) ?
Such read_pending_chars(+StreamIn, -Chars, ?Tail)?
or
read_pending_codes (+StreamIn, -Codes, ?Tail) ?

The program sent is illustrative, its uses is to maze navigation…

I’m using: SWI-Prolog version ???
Welcome to SWI-Prolog (threaded, 64 bits, version 8.0.3)

I want the code to:
To recognize ONLY the arrows key … 4

But what I’m getting is:

3 codes …

read_key([Code|Codes]) :-
   get_single_char(Code),
   read_pending_codes(user,Codes,[]).

read_keyatom(KAtom) :-
   read_key(Codes),
   codes_keyatom(Codes,KAtom).

codes_keyatom([27,91,65],up)    :- !.
codes_keyatom([27,91,66],down)  :- !.
codes_keyatom([27,91,67],right) :- !.
codes_keyatom([27,91,68],left)  :- !.

Query

7 ?- read_keyatom(Key).
% Press the <up> key here
Key = up.
3 Likes

See also with_tty_raw/1, available in recent development versions.

thanks … I am seeing the answer only today (solved with a workaround)
thank you indeed

Jan thank you … I am seeing the answer only today (solved with a workaround)
Surely this answer will help other with this difficulty

On my side (Windows 10 + SWI Prolog 8.3.11), it works with:

codes_keyatom([16],up) :- !.
codes_keyatom([14],down) :- !.
codes_keyatom([6],right) :- !.
codes_keyatom([2],left)  :- !.

Thanks … I already solved using others keys.

claudio