Which Elixir/Erlang released stopped the IEx prompt from being overwritten?

A common complaint that I had on earlier Elixir/Erlang versions that any output from my server (especially common when I’m running a phoenix app via iex -S mix phx.server) would overwrite whatever info you had typed at the prompt. But a semi-recent (last year or so) Elixir or Erlang/OTP upgrade has fixed this issue!

This is how it works now :tada:

Peek 2024-04-06 15-55

Does anyone know which version added this great feature?

5 Likes

It seems that it is related more to the Erlang itself.
There is a shell rewrite in Erlang 26. It introduced many useful features, like multiline editing and this one too.

Here are examples using podman (you can replace it with docker).

Erlang 25:

podman run --rm -it elixir:1.14-otp-25-alpine iex
Erlang/OTP 25 [erts-13.2.2.6] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.14.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Task.start(fn -> Process.sleep(1500); IO.puts("puts"); require Logger; Logger.info("log") end)
{:ok, #PID<0.110.0>}
puts
iex(2)>
11:16:25.455 [info] log

Erlang 26:

podman run --rm -it elixir:1.14-otp-26-alpine iex
Erlang/OTP 26 [erts-14.2.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.14.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Task.start(fn -> Process.sleep(1500); IO.puts("puts"); require Logger; Logger.info("log") end)
{:ok, #PID<0.114.0>}
puts

11:16:44.647 [info] log
iex(2)>
4 Likes

As @RomanKotov said, it was part of the things we fixed in the shell rewrite in Erlang/OTP 26.

7 Likes

Thank you both for the confirmation! I think this might be my favorite improvement in OTP 26 :blush:

3 Likes

There’s been a lot of quality-of-life improvements in recent times. I’m a big fan of being able to use Ctrl + L to clear the shell.

3 Likes

Elixir doesn’t have it (yet?), but being able to auto-complete items in a propertylist/map is great!

For example:

1> gen_tcp:connect("127.0.0.1",80,[<TAB>
typespecs
gen_tcp:connect(Address, Port, Opts)
gen_tcp:connect(Address, Port, Opts, Timeout)
gen_tcp:connect_option() ::     
{active, ...}                   binary                          
{bind_to_device, ...}           {buffer, ...}                   
{debug, ...}                    {delay_send, ...}               
{deliver, ...}                  {dontroute, ...}                
{exclusiveaddruse, ...}         {exit_on_close, ...}            
{fd, ...}                       {header, ...}                   
{high_msgq_watermark, ...}      {high_watermark, ...}           
{ifaddr, ...}                   inet                            
inet6                           {ip, ...}                       
{ipv6_v6only, ...}              {keepalive, ...}                
{linger, ...}                   list                            
local                           {low_msgq_watermark, ...}       
{low_watermark, ...}            {mode, ...}                     
{netns, ...}                    {nodelay, ...}                  
{packet, ...}                   {packet_size, ...}              
{port, ...}                     {priority, ...}                 
{raw, ...}                      {recbuf, ...}                   
{recvtclass, ...}               {recvtos, ...}                  
{recvttl, ...}                  {reuseaddr, ...}                
{reuseport, ...}                {reuseport_lb, ...}             
{send_timeout, ...}             {send_timeout_close, ...}       
{show_econnreset, ...}          {sndbuf, ...}                   
{tclass, ...}                   {tcp_module, ...}               
{tos, ...}                      {ttl, ...}
inet:inet_backend() ::     
{inet_backend, ...}
1> gen_tcp:connect("127.0.0.1",80,[{active,<TAB>
typespecs
gen_tcp:connect(Address, Port, Opts)
gen_tcp:connect(Address, Port, Opts, Timeout)
false                         once                          
range(op (- 32768), 32767)    true
5 Likes