quantumpotato
quantumpotato

Reputation: 9767

Read a character input from Erlang without requiring the Return key pressed from the prompt

I'm looking at the io module http://erlang.org/doc/man/io.html#read-1

and finding that reading input uses a Prompt and waits for the user to press Enter (Return?).

How do read 1 character at a time without requiring the enter press?

EDIT

I have tried

io:setopts([{binary, true}]) but this doesn't change it.

Upvotes: 2

Views: 1494

Answers (1)

zetavolt
zetavolt

Reputation: 3227

Strap yourself in quantumpotato, you are about to enter a world of pain you never knew existed.


A responsible programmer would tell you that there is no way to do this, certainly not a portable one.

Now, the phrase "not portable" has been diluted by pedantic fever dreams like CHAR_BIT != 8 to subtly persuade everyone that 'not portable' means either "some LSD-addled system built in the late 60s can't run this" or "Won't run on Windows".

No, what you're about to encounter is the sort of portability problem which caused our ancestors to volunteer to use autotools. Really, truly, not portable across different, even POSIX "compliant", systems.

As you might imagine, the sane way to do this is to rely on something like Ncurses, but as is true of so many of the necessities of life, no non-NIF implementation exists for Erlang.

In spite of all these warnings I just gave you, here's what I have done in a pinch in the past:

-module(thing).
-compile(export_all).

get_char() ->
    Ch = io:get_chars("p: ", 1),
    io:fwrite("Ch: ~w", [Ch]).

start() ->
    io:setopts([{binary, true}]),
    get_char().

Alone, this won't work of course. So you need to invoke your script from another that set's the appropriate termios input flags. As I mentioned earlier, this has been a real crapshoot in the past and I haven't heard anything that would lead me to believe the situation has changed.

#!/bin/sh
stty --f /dev/tty icanon raw
erl -pa ./ -run thing start -run init stop -noshell
stty echo echok icanon -raw

It is possible to invoke "stty" or send magic chars from within an Erlang program as well, but if memory serves you need to invoke erl with -noshell and add additional stty incantations like time and echo 0.

Another problem I've experienced in the past is that while you can use get_chars safely, other io functions will fail because some of them have their own built-in 'line cooking'.

If all of this hasn't yet persuaded you that computers have been a disaster for the human race, you can read up more about the details of this in the excellent book The Linux Programming Interface.

Good luck.

Upvotes: 7

Related Questions