Fun Times with IEx
Today I wanted to mention just a few of the not widely discussed things that can be done with elixir’s interactive shell, IEx. Hopefully one or more are new to you and can help improve your development workflow.
- Saving Shell Command History
- Interactive Shells, Mix Tasks, and Environments
- Gracefully Shutting Down IEx
- Useful Shell Commands
- Configuring IEx - Making Inspect Pretty and Infinite
- IEx Startup Scripts - Per Project and/or Global
- Conclusion
Saving Shell Command History
If you’ve used iex before, you have probably noticed that it does not save your shell history. For instance, you start an iex shell, execute a few commands, shut it down, then bring it back up. You hit the up arrow on your keyboard and nothing happens.
Luckily, there are a couple ways to remedy this situation. First, you can specify it by hand as you start up iex:
iex --erl "-kernel shell_history enabled"
The alternative is to add the ERL_AFLAGS
environment variable to your standard UNIX/Linux/Windows shell:
- Linux:
export ERL_AFLAGS="-kernel shell_history enabled"
- Windows:
set ERL_AFLAGS "-kernel shell_history enabled"
Interactive Shells, Mix Tasks, and Environments
You probably know you can run all mix tasks in an IEx shell:
iex -S mix run
: run your elixir application with shell accessiex -S mix phx.server
: start your phoenix server with shell accessiex -S mix test test/module_test.exs:49
: execute the test at line 49 in yourtest/module_test.exs
file
You can on a per environment basis. Provided you have a specifically named environment config file in your project’s config folder, you can run your tasks in the shell for each environment. Using the above examples:
MIX_ENV=prod iex -S mix run
: same as before, but using the configuration inconfig/prod.exs
MIX_ENV=staging iex -S mix phx.server
: same as before, but using the configuration inconfig/staging.exs
MIX_ENV=preprod iex -S mix test test/module_test.exs:49
: same as before, but using the configuration inconfig/preprod.exs
Gracefully Shutting Down IEx
Most people are familiar with using Ctrl+C
to bring up IEx’s shell break menu, and either hitting Ctrl+C
again, or choosing a
for abort. However, there are times when aborting or abruptly killing your application can lead to corrupted data or files, such as when using Dets. In that case, you need a different approach, one that will gracefully shut everything down.
That’s when you use elixir’s System.stop/1
function to carefully shut everything down in your application:
Note that using System.stop(0)
is the same as calling erlang’s init:stop()
. Here’s erlang’s official description:
All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system terminates by calling halt(Status).
Useful Shell Commands
Though there are many useful shell commands provided by IEx and IEx.Helpers, I’ve listed a few below that I use on a regular basis:
r(module) - reload modules at will
IEx.Helpers.r/1
reloads a given module inside IEx. This is very usefiul when rapidly iterating and checking changes.
h(module or function) - show documentation for a module or function
IEx.Helpers.h/1
displays the coded documentation for a given module or function.
import_file(path) - load and execute scripts inside IEx
IEx.Helpers.import_file/1
executes the contents of the file as though you had typed them directy into IEx. This is great for applications where you have an *.exs
file containing some script that you want to load at will inside IEx.
For example, let’s say that for a give math project, we often find ourselves working with a few sets of prime numbers. Instead of having to retype and rerun the call, we can instead put the code in a separate .exs
file and import that when needed.
Example prime_seeds.exs
file:
And loading it with import_file/1
:
runtime_info(opts) - show runtime info for the current VM
Displays information on the current VM, including: memory, statistics, VM version, architecture and running applications.
Configuring IEx - Making Inspect Pretty and Infinite
When working in IEX, you will spend a lot of time reviewing the output of various function calls. While strings and numbers are simple to review, using inspect/1
on maps, lists, and tuple trees without using the pretty: true
option can be downright painful. On top of that, inspecting large lists or maps can be even worse. IEx configurations to the rescue!
IEx.configure/1
lets you configure your IEx shell, including the results of inspect. Speaking of inspect, running this in IEx will set these options for as long as your shell session runs.
IEx.configure(inspect: [pretty: true, limit: :infinity])
You can see an example of it in action below.
IEx.configure/1
can also configure the iex prompt, size of shell history, colors, and more.
IEx Startup Scripts - Per Project and/or Global
IEx has a special file called .iex.exs
it looks for each time IEx starts up. It looks for that project’s root directory, or failing to find it there, in the user’s home directory. Whichever it finds first, it executes.
Having a global .iex.exs
file lets you customize every IEx shell to your liking, as well as loading helper modules, functions, aliases, and imports.
Here’s an example of my global ~/.iex.exs
:
A project-level .iex.exs
file can be used to import your global .iex.exs
and handle executing any project-local aliasing, imports, or assisting functions. Below is the .iex.exs
file I use with ExDiceRoller. It changes regularly, depending on what I’m working on at that point in time.
As you can see, using the .iex.exs
file is a great way to store IEx configurations and more, such as the previously mentioned in IEx configurations for inspect.
Conclusion
IEx is a fantastic, deep, and very powerful shell that has a myriad of possible configurations and tools to aid in development. I only covered a small part of what’s possible, so I highly suggest perusing the Elixir docs for IEx and IEx.Helpers.
Post by: rishenko