How to pretty print a list of Erlang terms?

I have not able to figure out how to pretty print a Erlang list of terms.

root@d02f07e82e1f:/# erl
Erlang/OTP 22 [erts-10.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.4  (abort with ^G)
1> rp(lists:sort(erlang:loaded())).
[application,application_controller,application_master,
 atomics,beam_lib,binary,c,code,code_server,counters,dict,
 edlin,epp,erl_abstract_code,erl_anno,erl_distribution,
 erl_eval,erl_init,erl_internal,erl_lint,erl_parse,
 erl_prim_loader,erl_scan,erl_signal_handler,erl_tracer,
 erlang,error_handler,error_logger,erts_code_purger,
 erts_dirty_process_signal_handler,erts_internal,
 erts_literal_area_collector,ets,file,file_io_server,
 file_server,filename,gb_sets,gb_trees,gen,gen_event,
 gen_server,global,global_group,group,group_history,heart,
 hipe_unified_loader,inet,inet_config,inet_db,
 inet_gethost_native,inet_parse,inet_udp,init,io,io_lib,
 io_lib_format,kernel,kernel_config,kernel_refc,lists,logger,
 logger_backend,logger_config,logger_filters,
 logger_formatter,logger_h_common,logger_handler_watcher,
 logger_olp,logger_proxy,logger_server,logger_simple_h,
 logger_std_h,logger_sup,maps,net,net_kernel,orddict,ordsets,
 os,otp_internal,persistent_term,prim_buffer,prim_eval,
 prim_file,prim_inet,prim_zip,proc_lib,proplists,queue,
 ram_file,raw_file_io,raw_file_io_raw,rpc,sets,shell,socket,
 standard_error,string,supervisor,supervisor_bridge,timer,
 unicode,unicode_util,user_drv,user_sup,zlib]
ok

I would like to have this output:

root@d02f07e82e1f:/# erl
Erlang/OTP 22 [erts-10.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.4  (abort with ^G)
1> rp(lists:sort(erlang:loaded())).
[
  application,
  application_controller,
  application_master,
  # ommited
]

Is this possible?

1 Like

I’m not sure how to do it from erl, but this works in iex:

iex(1)> IO.inspect(:lists.sort(:erlang.loaded()), limit: :infinity, width: 0)
[Access,
 Agent,
 Agent.Server,
 Application,
 ...
 :user_drv,
 :user_sup,
 :zlib]

Even if there’s not a built-in function for this in Erlang, I imagine you could load your own utility to do the same thing.

If its only to the console and only for lists then this could work:

def pretty_print_list(List) ->
  erlang:display("["),
  lists:foreach(fun(Y) -> erlang:display(Y) end, List),
  erlang:display("]").

but a few extra true's will be printed

1 Like

I was looking for a native way of doing it, because I though with my buttons that obviously the language would have it in order to make our life’s easier, but it seems not :frowning:

Anyway the main purpose of needing this is to do a smoke test in the end of a docker build and have all modules printed line by line so that I can make a diff and see what changed between building from different sources the same Erlang version.

Well my use case is to do a smoke test in the end of a Docker build and see the diffs, as I already mentioned in the other comment, thus I am not sure how I can use your approach, but thanks for sharing.

I will try to see if I can make it work, but probably I will resort to do some bash magic on it.

Then you really should do like that! Sort the list and then iterate over its elements and print them each on a single line. I would not rely on something built in here where formatting might chance without notice because something in the environment changed.

Terminal width might be something relevant here.

2 Likes

io:fwrite("~20p~n", [Term]) will pretty print it if there is more elements than width (in this case 20, by default 80 characters).

2 Likes

Thanks for the suggestion, but that does not work with the command I am trying to use to list the installed modules.

I think I will go with the bash magic :wink:

Do you want that to result with text on stdout or rather you want it to be available as string within application? Because io:fwrite("~1p~n", [erlang:loaded()]). works for me.

2 Likes

Oh it also works for me now… I see now that I was missing the square brackets [ ] around the erlang function call… newbie mistake.

1 Like

Based on your suggestion, this is my final command:

erl -eval 'io:fwrite("~1p~n", [lists:sort(erlang:loaded())]), halt().'  -noshell
``
2 Likes