Yeah, we can add a IEx.configure(dot_iex: "..."), which takes precedence over the other ones if set. And we should read it in the same place we read everything else.
On Thu, Jun 6, 2024 at 9:08 PM Chris Miller <camiller...@gmail.com> wrote: > I hadn't considered the config, but thats an interesting thought - not > entirely sure if I totally get your though on the matter, but I was able to > extend the IEx.Config to track a new key (:configuration_files) and then > extended the IEx.Evaluator to pull that value from the config and load the > configured files plus the `.iex.exs` file. This allows the feature to be > used either through a call to `IEx.configure/1` before the evaluator > starts, or the config can be added into any config file, which would allow > you to easily swap config files per env if desired > > On Thursday, June 6, 2024 at 1:50:44 PM UTC-5 José Valim wrote: > >> 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 <camil...@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-co...@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/a01b0032-13ee-45a1-b59b-5320a70e3322n%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/a01b0032-13ee-45a1-b59b-5320a70e3322n%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/CAGnRm4JX6KYe1En8WsCQeLhHF8SXnMB7jqps-qcwYKQwNWRimw%40mail.gmail.com.