Supporting line editing in terminal input

Hello,

What’s the recommended approach for building an interactive terminal UI in Elixir with custom line editing and tab completion? At a minimum, it should support navigating with arrow keys, home/end, Ctrl-A / Ctrl-E should go to the beginning/end of the line, etc.

I tried :edlin but found its documentation lacking. Looking for alternatives or any examples how to use :edlin properly.

Best Regards,
Victor.

Proper interactive terminal applications like text editors have been a little limited historically because the erlang tooling for interacting with the terminal has only supported a “cooked” mode of reading input, requiring newlines to send input to your program. There were some workarounds involving spawning a tty_sl port or stty port with the right flags, but those approaches also came with some limitations and deprecations, including not capturing all metakey keyboard inputs fidelitously (fighting with erlang interactive shell key combos).

Serendipitously, upcoming support for a non-cooked “raw” mode in erlang tooling was PRd a month ago, see forum discussion here: Raw terminal mode coming to OTP 28!

That PR even has (erlang) guides for making your own interactive terminal game and shell, so I’d say now is a great time to be exploring this space!

3 Likes

Thank you Chris, this is exactly the kind of input I was looking for! Will look in the new Erlang tooling; one more reason to finish reading Joe Armstrong’s Erlang book.

Hi, it’s great that raw terminal mode is coming to OTP 28, which means this functionality will be available by default when Elixir 1.19 and Erlang/OTP 28 release around May/June.

I’m looking for a way to enable similar functionality before then. I’ve tried:

  1. Compiling Erlang from master, but this conflicts with burrito which I need for app deployment
  2. Understanding how iex uses edlin, but the process is too complex to extract just the line editing components

Does anyone have a minimal example that enables either:

  • Line editing with edlin
  • A basic getch function that captures keystrokes (including arrows and control symbols)

I found this snippet from IEx.CLI but am unsure how to integrate it:

:user_drv.start([:"tty_sl -c -e", old_tty_args()])

Any guidance would be appreciated!