I wonder if you could call something like "IEx.configure(...)" from the top
of your mix.exs and that would be enough to configure its location. Or
maybe it would only require a small tweak to make it work.

On Thu, Jun 6, 2024 at 8:22 PM Chris Miller <camiller...@gmail.com> wrote:

> Actually - I am a little confused by the startup dependencies between mix
> and iex as it seems like the Evaluator is starting after mix (or at least
> that how it appears in my tests), this patch to the IEx.Evaluator seems to
> accomplish what I was hoping to achieve (but it does make IEx depend on Mix
> which may have been something you wanted to avoid, but perhaps there is
> some more abstract way of getting this information from the mix project to
> the evaluator)
>
> ```elixir
>   defp load_dot_iex(state, path) do
>     candidates =
>       if path do
>         [path]
>       else
>         # Do not assume there is a $HOME
>         for dir <- [".", System.get_env("IEX_HOME") || System.user_home()],
>             dir != nil,
>             do: dir |> Path.join(".iex.exs") |> Path.expand()
>       end
>
>     mix_config_file =
> List.wrap(Mix.Project.get().cli()[:iex_configuration_file])
>
>     candidates
>     |> Enum.filter(&File.regular?/1)
>     |> Enum.take(1)
>     |> Enum.concat(mix_config_file)
>     |> Enum.reduce(state, fn path, state ->
>       eval_dot_iex(state, path)
>     end)
>   end
> ```
> Once again - sorry for the noise if this in not a feature you are
> interested in introducing!
>
> On Thursday, June 6, 2024 at 12:43:09 PM UTC-5 Chris Miller wrote:
>
>> Thanks for the reply Jose!  The dependency order makes sense as an issue
>> with my initial thought - one other approach is that a project could define
>> its own method of configuring IEx if there were a hook to allow that -
>> looking at the IEx.Evaluator I was able to make a pretty small patch to
>> allow for this type of configuration by adding a new public function and
>> extending the `loop` function
>>
>> ```elixir
>>   @spec load_dot_iex(pid, pid, String.t()) :: :ok | :error
>>   def load_dot_iex(evaluator, server, path) do
>>     ref = make_ref()
>>     send(evaluator, {:load_dot_iex, server, ref, self(), path})
>>
>>     receive do
>>       {^ref, result} -> result
>>     after
>>       5000 -> :error
>>     end
>>   end
>>
>>  ...
>>
>>   defp loop(%{server: server, ref: ref} = state) do
>>     receive do
>>       {:eval, ^server, code, counter, parser_state} ->
>>         {status, parser_state, state} = parse_eval_inspect(code, counter,
>> parser_state, state)
>>         send(server, {:evaled, self(), status, parser_state})
>>         loop(state)
>>
>>       {:fields_from_env, ^server, ref, receiver, fields} ->
>>         send(receiver, {ref, Map.take(state.env, fields)})
>>         loop(state)
>>
>>       {:value_from_binding, ^server, ref, receiver, var_name,
>> map_key_path} ->
>>         value = traverse_binding(state.binding, var_name, map_key_path)
>>         send(receiver, {ref, value})
>>         loop(state)
>>
>>       {:variables_from_binding, ^server, ref, receiver, var_prefix} ->
>>         value = find_matched_variables(state.binding, var_prefix)
>>         send(receiver, {ref, value})
>>         loop(state)
>>
>>       # NEW RECEIVE CASE TO LOAD A DOT IEX FILE PROGRAMMATICALY
>>       {:load_dot_iex, ^server, ref, receiver, path} ->
>>         next_state = load_dot_iex(state, path)
>>         send(receiver, {ref, :ok})
>>         loop(next_state)
>>
>>       {:done, ^server, next?} ->
>>         {:ok, next?}
>>
>>       {:done, ^ref, next?} ->
>>         {:ok, next?}
>>     end
>>   end
>> ...
>>
>> I think that combining this overriding the default mix task would allow
>> for the type of configuration that I was hoping to achieve - or if there is
>> desire for this functionality a small change could be incorporated into mix
>> to do this as a feature using `project.cli()[:iex_configuration_file]` or
>> something of the sort.
>>
>> If you don't think any of this is necessary in Elixir proper I can move
>> my work towards something at the project level, but wanted to see if there
>> was any interest in upstreaming this concept
>> On Thursday, June 6, 2024 at 11:40:51 AM UTC-5 José Valim wrote:
>>
>>> Hi Chris, thanks for writing.
>>>
>>> > • will be used when `iex` is run from that directory not in the
>>> context of that mix project
>>>
>>> The reason this happens is exactly because IEx starts before Mix, so we
>>> can't  use Mix to configure IEx. And I think that will get in the way of
>>> your proposal too. I hope this helps narrow down a bit the paths to explore.
>>>
>>> On Thu, Jun 6, 2024 at 4:23 PM Chris Miller <camil...@gmail.com> wrote:
>>>
>>>> Currently we use the `dot-iex` file to configure an iex shell.  The
>>>> `dot-iex` file that gets loaded is the first of these three things that is
>>>> found
>>>> • --dot-iex PATH command line argument supplied to the iex command
>>>> • '.iex.exs' file in the directory that iex is run from
>>>> • '.iex.exs' file in directory found in the env var "IEX_HOME" OR the
>>>> users home directory
>>>>
>>>> The issue I am facing currently is that project level shell
>>>> configuration is hard to manage in a way that achieves these goals
>>>> • will apply configuration when running a shell in the context of a
>>>> particular (mix) project
>>>> • will allow for a developer to apply their own particular customization
>>>> • does not require any additional scripts / arguments to start the
>>>> project
>>>>
>>>> Existing partial solutions for a project level iex configuration
>>>>
>>>> • create and commit a `.iex.exs` file for the project
>>>> -- PROS:
>>>>    • the file will be loaded when `iex -S mix` is run
>>>>    • configuration can be specific to the project as it is part of the
>>>> source code written for the project and tracked through whatever svc is 
>>>> used
>>>> -- CONS:
>>>>     • does not allow for an individual developer to include their own
>>>> configuration as expected (you could add an
>>>> `import_if_avaiable(".dev.iex.exs")` line to the project level `.iex.exs`
>>>> file to allow for this extension, but it makes the file name arbitrary and
>>>> could cause some confusion)
>>>>     • will be used when `iex` is run from that directory not in the
>>>> context of that mix project
>>>>
>>>> • create a project specific configuration file and use the --dot-iex
>>>> command line arg
>>>> -- PROS:
>>>>     • does not interfere with running `iex` outside of the context of
>>>> the mix project
>>>>     • can load additional configuration files by include
>>>> `import_if_avaiable` statements
>>>> -- CONS:
>>>>     • Requires including the --dot-iex arg when running the `iex -S
>>>> mix` command, which is prone to being forgotten, this could be wrapped in a
>>>> very simple start script, but you would still need to remember to run that
>>>> (I work with a largish number of elixir services and having individual
>>>> start scripts or args per project can be cumbersome to remember)
>>>>
>>>> I think an ideal solution would be a way to configure a mix project to
>>>> load a particular configuration file that will be loaded when the
>>>> IEx.Evaluator starts IN ADDITION to the existing `dot-iex` file options.  I
>>>> believe this would allow for maintainers of a project to normalize some
>>>> shell configuration while still allowing developers the full ability to add
>>>> their own configuration while also keeping the workflow of starting the
>>>> shell more standardized across projects.
>>>>
>>>> A secondary goal might be that this could be incorporated into releases
>>>> as well so that the `./bin/project remote` and similar commands could also
>>>> load some particular configuration
>>>>
>>>> Thanks in advance for any thoughts you had, and if I missed any
>>>> existing options for this type of configuration, let me know!
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "elixir-lang-core" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to elixir-lang-co...@googlegroups.com.
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/elixir-lang-core/a956613f-7ef1-435c-8aaf-ab3af8058d5dn%40googlegroups.com
>>>> <https://groups.google.com/d/msgid/elixir-lang-core/a956613f-7ef1-435c-8aaf-ab3af8058d5dn%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> --
> You received this message because you are subscribed to the Google Groups
> "elixir-lang-core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to elixir-lang-core+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/elixir-lang-core/085f777f-3b9c-4ef1-8787-d1396c13fc88n%40googlegroups.com
> <https://groups.google.com/d/msgid/elixir-lang-core/085f777f-3b9c-4ef1-8787-d1396c13fc88n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elixir-lang-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Jq7noduzak77F22F3W7o8FBU-NsrP_FMA9%3DhtV4Z4Hjw%40mail.gmail.com.

Reply via email to