2

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.

quantumpotato
  • 9,637
  • 14
  • 70
  • 146
  • Possible duplicate of [Get console user input as typed, char by char](http://stackoverflow.com/questions/39805210/get-console-user-input-as-typed-char-by-char) – Steve Vinoski Mar 12 '17 at 19:52
  • Thanks @SteveVinoski , it's close but that question is in Elixir and so is their accepted answer. The erlang curses answer given does not clearly indicate in their readme how to accept input line by line instead they show a bouncing "Hello World" so I believe this is not a duplicate and should not be closed. – quantumpotato Mar 13 '17 at 05:46

1 Answers1

7

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.

zetavolt
  • 2,989
  • 1
  • 23
  • 33
  • This actually worked, thank you. As a workaround I wrote an c program that could set `stty raw` (erl shell cannot) that calls an erlang file. Ran into issues with tcp socket consistency loading data from another erlang process, if you dare look http://stackoverflow.com/questions/42755951/inconsistent-tcp-socket-behavior-in-erlang – quantumpotato Mar 13 '17 at 05:31
  • Btw your answer works ok but using stop takesa long time to shutdown. Using `halt` instead of `stop` displays an error message to the user, I wonder if there's a solution? – quantumpotato Mar 13 '17 at 05:47
  • my goal here is to read character by character in an erlang environment.. I think my other Q ^ is on the right path, by running a separate erlang server and pinging it – quantumpotato Mar 13 '17 at 05:48
  • 1
    Aha. I just remove stop from the invoke, made get_char() loop, and this works great! – quantumpotato Mar 14 '17 at 16:52
  • Related -- how to exit without showing a crash dump http://stackoverflow.com/questions/42792422/erlang-process-hanging-when-it-tries-to-kill-itself – quantumpotato Mar 14 '17 at 17:14