Skip to content

Add dot_iex IEx.Config key to take precedence over existing configurations #13647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions lib/iex/lib/iex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@ defmodule IEx do

## The .iex.exs file

When starting, IEx looks for a local `.iex.exs` file (located in the current
working directory), then for a global `.iex.exs` file located inside the
directory pointed by the `IEX_HOME` environment variable (which defaults
to `~`) and loads the first one it finds (if any).
When starting, IEx looks for a configured path, then for a local `.iex.exs` file
(located in the current working directory), then for a global `.iex.exs` file
located inside the directory pointed by the `IEX_HOME` environment variable
(which defaults to `~`) and loads the first one it finds (if any).

The code in the chosen `.iex.exs` file is evaluated line by line in the shell's
context, as if each line were being typed in the shell. For instance, any modules
Expand Down Expand Up @@ -356,8 +356,9 @@ defmodule IEx do
iex(1)> value
13

It is possible to load another file by supplying the `--dot-iex` option
to IEx. See `iex --help`.
It is possible to load another file by configuring the `iex` application's `dot_iex`
value (`config :iex, dot_iex: "PATH"` or `IEx.Config.configure(dot_iex: "PATH")`)
or supplying the `--dot-iex` option to IEx. See `iex --help`.

In case of remote nodes, the location of the `.iex.exs` files are taken
relative to the user that started the application, not to the user that
Expand Down Expand Up @@ -399,6 +400,7 @@ defmodule IEx do
* `:alive_prompt`
* `:alive_continuation_prompt`
* `:parser`
* `:dot_iex`

They are discussed individually in the sections below.

Expand Down Expand Up @@ -504,6 +506,11 @@ defmodule IEx do
or `{:incomplete, buffer}`.

If the parser raises, the buffer is reset to an empty string.

## dot_iex

Configure the file loaded into your IEx session when it starts.
See more information [in the `.iex.exs` documentation](`m:IEx#module-the-iex-exs-file`).
"""
@spec configure(keyword()) :: :ok
def configure(options) do
Expand Down
8 changes: 7 additions & 1 deletion lib/iex/lib/iex/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule IEx.Config do
:alive_prompt,
:alive_continuation_prompt,
:width,
:parser
:parser,
:dot_iex
]

# Read API
Expand Down Expand Up @@ -88,6 +89,10 @@ defmodule IEx.Config do
end
end

def dot_iex() do
Application.get_env(:iex, :dot_iex)
end

# Used by default on evaluation cycle
defp default_color(:eval_interrupt), do: [:yellow]
defp default_color(:eval_result), do: [:yellow]
Expand Down Expand Up @@ -193,6 +198,7 @@ defmodule IEx.Config do
defp validate_option({:alive_continuation_prompt, new}) when is_binary(new), do: :ok
defp validate_option({:width, new}) when is_integer(new), do: :ok
defp validate_option({:parser, tuple}) when tuple_size(tuple) == 3, do: :ok
defp validate_option({:dot_iex, path}) when is_binary(path), do: :ok

defp validate_option(option) do
raise ArgumentError, "invalid configuration #{inspect(option)}"
Expand Down
6 changes: 5 additions & 1 deletion lib/iex/lib/iex/evaluator.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule IEx.Evaluator do
@moduledoc false

alias IEx.Config

@doc """
Eval loop for an IEx session. Its responsibilities include:

Expand Down Expand Up @@ -242,7 +244,9 @@ defmodule IEx.Evaluator do
ref: ref
}

case opts[:dot_iex_path] do
dot_iex_path = opts[:dot_iex_path] || Config.dot_iex()

case dot_iex_path do
"" -> state
path -> load_dot_iex(state, path)
end
Expand Down
15 changes: 15 additions & 0 deletions lib/iex/test/iex/interaction_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,21 @@ defmodule IEx.InteractionTest do
input = "nested_var\nmy_variable\nmy_fun_nested()"
assert capture_iex(input, [], dot_iex_path: path) == "42\n13\n:nested"
end

@tag :tmp_dir
test "configured .iex", %{tmp_dir: tmp_dir} do
path =
write_dot_iex!(tmp_dir, "configured-dot-iex", """
defmodule ConfiguredDotIEx do
def my_fun_single, do: :single
end
import ConfiguredDotIEx
my_variable = 42
""")

assert capture_iex("{my_fun_single(), my_variable}", [dot_iex: path], dot_iex_path: nil) ==
"{:single, 42}"
end
end

defp write_dot_iex!(tmp_dir, name, contents) do
Expand Down
6 changes: 3 additions & 3 deletions lib/iex/test/test_helper.exs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ defmodule IEx.Case do
end
end

keys = [:default_prompt, :alive_prompt, :inspect, :colors, :history_size]
@iex_env Application.get_all_env(:iex) |> Keyword.take(keys)
@keys [:default_prompt, :alive_prompt, :inspect, :colors, :history_size, :dot_iex]
@iex_env Application.get_all_env(:iex) |> Keyword.take(@keys)

setup do
on_exit(fn ->
env = @iex_env
Enum.each(env, fn {k, _} -> Application.delete_env(:iex, k) end)
Enum.each(@keys, &Application.delete_env(:iex, &1))
IEx.configure(env)
end)

Expand Down