Loading .erlang from the working directory

7 Mar 2023 16:04 erlang

In the previous post, I wrote about customizing the Erlang shell prompt by using the .erlang file. Erlang looks for this file in $HOME (I’m simplifying here); it doesn’t look in the current working directory. How can we fix that?

I like the way that Elixir looks for an .iex.exs file in the current directory. But Erlang (since OTP-21.0) doesn’t look for the .erlang file in the current directory.

The documentation says:

When Erlang/OTP is started, the system searches for a file named .erlang in the user’s home directory and then filename:basedir(user_config, "erlang").

On Linux, that usually resolves to $HOME/.config/erlang.

You can tell the shell to load another .erlang file by using the c:erlangrc/1 function; it takes a list of directories to look in. For example:

c:erlangrc(["."]).

We can do that when starting erl with:

erl -run c erlangrc .

(Thanks to Ruan for the tip)

How can we do that automatically?

My first thought was something like this:

ERL_ZFLAGS="-run c erlangrc ." erl

…which works fine. You could set ERL_ZFLAGS in your profile, even. As far as I can tell, it doesn’t break anything. It even loads the default .erlang file from $HOME first.

Given that it loads $HOME/.erlang first, can we take advantage of that, and do it in reverse? Yes:

% In $HOME/.erlang...
c:erlangrc(["."]).

So we’re done, right? No.

Loading arbitrary scripts from untrusted sources is a bad idea. Don’t do that.

direnv

If you’re using direnv and kerl, you could put it in your .envrc:

use erlang OTP-25.2.1
export ERL_ZFLAGS="-run c erlangrc ."

Because direnv prompts you to approve each .envrc file, we can use this to prevent automatically running .erlang until we’ve checked it.

erlang.mk

If you’re using erlang.mk, you could use the SHELL_OPTS variable:

SHELL_OPTS = -run c erlangrc .

rebar3

I couldn’t find a clean way to have this work in rebar3 shell. Look at this Github issue for inspiration.

See also