elixir-ls icon indicating copy to clipboard operation
elixir-ls copied to clipboard

Feature request: make searching for ASDF optional

Open Trevoke opened this issue 11 months ago • 20 comments

I'm in an environment where we use Nix very heavily to override everything, and while I do have asdf installed, it turns out to, most of the time, not be the versions of Elixir/Erlang that I need.

I fixed it locally by changing this line in launch.sh to have a bogus path to search for ASDF :

ASDF_DIR=${ASDF_DIR:-"${HOME}/.asdfx"}

There may be a larger decision over whether elixir-ls should do this at all, or whether the paths to the executable should be assumed to be known in the environment at launch time.

In emacs for instance, for Nix reasons, I am using direnv which triggers nix, so I use this: https://github.com/purcell/envrc

Basically it runs direnv for a project when I open the first buffer (and it reuses the values for each subsequent open buffers), and that gives me things like a custom PATH for each project, so emacs knows the correct version of elixir and erlang for the given buffer.

Trevoke avatar Jan 24 '25 19:01 Trevoke

I'm curious if https://github.com/elixir-lsp/elixir-ls?tab=readme-ov-file#local-setup is not suitable in your case. You can place your custom hacks in your local setup script.

lukaszsamson avatar Jan 28 '25 18:01 lukaszsamson

I think you're right, that would work, thanks! I guess there is a question about whether that script should look at ASDF at all -- maybe using ASDF would be a great example of how to configure one's own scripts (it could be shipped with the release, as a documented code example, maybe?)

Trevoke avatar Feb 06 '25 16:02 Trevoke

I should add a note that the documentation listed there doesn't work for me because my problem is specifically the reference to ASDF - in our case, the correct version of elixir is determined by Nix. The documentation you listed to hooks into the script further down than looking for ASDF, which means the launch script modifies the PATH. That is to say, we are hacking the path, and we don't need our path hacks to be overridden by the launcher when it finds ASDF, as that override would break our overrides.

So for me, I just hack the launch script and tell it to look for asdf where it won't find it.

So I think there is probably something to allowing some leeway for how the launch script looks for the executables.

If that makes sense. :)

Trevoke avatar Feb 28 '25 17:02 Trevoke

I have the exact same use-case.

I was thinking that a useful PR to the launch script might be to have it start with a check for an existing elixir in the path, and not go any further with the asdf/mise/etc checks if there's already one there.

Would that work?

The other solution I thought of was to have another conventional script (maybe ~/.config/elixir_ls/launch.sh) that, if present, is used instead of the built-in one. That would might make for a nice general-purpose back-door.

mattwynne avatar Feb 28 '25 19:02 mattwynne

I think something might have happened in the recent release, because I'm sure I previously had it working by setting ASDF_DIR= in my .envrc, which runs before the launch.sh script in my environment. I could be mistaken though, there's a lot of moving parts here!

mattwynne avatar Feb 28 '25 20:02 mattwynne

The documentation you listed to hooks into the script further down than looking for ASDF, which means the launch script modifies the PATH.

I stand corrected.

I was thinking that a useful PR to the launch script might be to have it start with a check for an existing elixir in the path, and not go any further with the asdf/mise/etc checks if there's already one there.

I don't think it is a good assumption. It's similar case as with python. It's always in the path but most of the times you wouldn't use the system one in your project.

The other solution I thought of was to have another conventional script (maybe ~/.config/elixir_ls/launch.sh) that, if present, is used instead of the built-in one. That would might make for a nice general-purpose back-door.

That sounds like github issue generator :)

I think something might have happened in the recent release, because I'm sure I previously had it working by setting ASDF_DIR= in my .envrc, which runs before the launch.sh script in my environment.

asdf v0.16 introduced breaking changes which make it necessary to check if asdf command is available instead of relying on ASDF_DIR env.

@mattwynne @Trevoke Do you think one env flag, e.g. ELS_DISABLE_VERSION_MANAGERS would solve your case? Or would you need a separate ones for asdf, mise, vfox?

lukaszsamson avatar Mar 01 '25 08:03 lukaszsamson

ELS_DISABLE_VERSION_MANAGERS would work for me, yup!

mattwynne avatar Mar 03 '25 19:03 mattwynne

Hey, after almost 3 hour debugging, I came here to add a few things, like my colleagues above, I don't have the vanilla asdf installation in my machine, but even after setting $ASDF_DIR correctly as mentioned above, the LSP server kept exiting, only printing that it had found an asdf installation in my machine and nothing more.

I doubled and tripled checked it, since the documentation and the launch script requests us to set ASDF_DIR, I looked into ASDF doc, which path I should set, and as it mentions, it is the location of core asdf scripts, so I set it to the installation path on my machine (/opt/homebrew/Cellar/asdf/0.16.2/) but it also didn't work.

That was when I read with more attention the LSP message, saying that it was trying to add asdf's shims folder to the $PATH. The main point is, the shims folder isn't in the ASDF core scripts path, it is in the same folder where ASDF install its plugins, and this path is kept in the ASDF_DATA_DIR environement variable, not in ASDF_DIR, as the documentation states, and your launch script tries to find.

And that was my issue, because indeed, in my machine, I've set asdf's data dir to a specific path (~/.asdf-data/). so running $ export ASDF_DIR=$ASDF_DATA_DIR elixir-ls is what makes it work for me....

So, not only would be good to have a way of disabling this ASDF's hardcoded path, but also would be good to correct both the documentation and the launch script to get the path from the correct environment variable.

ashton avatar Mar 08 '25 02:03 ashton

So, not only would be good to have a way of disabling this ASDF's hardcoded path, but also would be good to correct both the documentation and the launch script to get the path from the correct environment variable.

Please create a PR. Note that the script should for now be backwards compatible with pre 0.16

lukaszsamson avatar Mar 08 '25 08:03 lukaszsamson

but what would be the recommended approach? Shouldn't just elixir_ls just expect to have elixir in path? Instead of trying to install it?

ashton avatar Mar 10 '25 15:03 ashton

To be honest, the language server should just rely on whatever is in PATH, maybe provide flags and environment variables to alter the elixir and tools used.

On top of that, VScode plugin or a neovim plugin or whatever else one uses, can use those variables as necessary to select the correct version of elixir per project, in an adhoc manor.

I have never been a friend of this tight ASDF integration in the startup script, and am pretty sure I have left my concerns back when it was implemented or at least in early tickets after the introduction of the feature.

With the recent rise of ASDF alternatives I think it is a good time to rip out this functionality and push it towards the client or plugin used.

NobbZ avatar Mar 12 '25 11:03 NobbZ

Just a throw away comment. I was having problems today, as I had upgraded to asdf 16. Thought it was down to me experimenting with an umbrella app, switched back to a clean new app and no joy. Anyhow got mise installed and elixir-ls works like a champ again. Thanks for your hard work in keeping these amazing tools going!

colindensem avatar Mar 13 '25 15:03 colindensem

I don't believe that launch.sh should override ASDF_DATA_DIR at all, if it is already customized in the user's environment. I currently have a custom ASDF_DATA_DIR environment variable set, per the ASDF v16+ docs, but the current launch.sh script is manually exporting it's own (incorrect in my case) ASDF_DATA_DIR variable that is blowing away the correct one that is already set in my user env

This is similar to @ashton comment above

I can try to work on an update to the launch.sh script this week to be a bit more robust for this use case.

cpjolicoeur avatar Mar 15 '25 17:03 cpjolicoeur

@cpjolicoeur @ashton @matisnape @michalwski I believe https://github.com/elixir-lsp/elixir-ls/commit/1ba706dc2a0f378854f2ba43e3c937b4e048203d should resolve your issues with asdf. With that change the launch script will not overwrite asdf envs.

@Trevoke @mattwynne even if we add ELS_DISABLE_VERSION_MANAGERS will not work with asdf >= 0.16. If the command is available and shims are on the PATH they will be used. Currently asdf does not need any explicit activation.

lukaszsamson avatar Mar 23 '25 11:03 lukaszsamson

It solves the issue for me, thanks @lukaszsamson !

michalwski avatar Mar 24 '25 06:03 michalwski

@lukaszsamson appreciate the follow-up. I'll try it out today or tomorrow and report back if I'm still seeing the same issues. Thanks.

cpjolicoeur avatar Mar 24 '25 12:03 cpjolicoeur

@lukaszsamson one bit of my context that might be important is that I habitually fire up VSCode using code . from a terminal where I'm already using nix and direnv to manage the PATH, such that if I run which elixir I see this:

/nix/store/kb4s4dwinfbi2cyp52mn1ql624b8zxw7-elixir-1.18.2/bin/elixir

...which is the elixir I want to use for everything, including elixir-ls.

What me (and my colleagues who use VSCode) do for now is manually modify the launch.sh script to just not do any of the version manager stuff. So if there was some way for me to turn that all off with an environment variable, I think that would still work for me.

Is the version manager stuff intended for when you start VSCode up from outside of a terminal?

mattwynne avatar Mar 24 '25 22:03 mattwynne

If VSCode is launched from UI it does not share the terminal environment. The script needs to be able to find out preferred shell and activate version managers if needed. Pleas check if v0.27.2 resolves your issue. Now if asdf v0.16+ is detected the launch script will not attempt to change anything

lukaszsamson avatar Mar 24 '25 22:03 lukaszsamson

@lukaszsamson I confirm 0.27.2 is working for me now :)

matisnape avatar Mar 26 '25 16:03 matisnape

If VSCode is launched from UI it does not share the terminal environment. The script needs to be able to find out preferred shell and activate version managers if needed. Pleas check if v0.27.2 resolves your issue. Now if asdf v0.16+ is detected the launch script will not attempt to change anything

I beg your pardon! After some fiddling around with this today, I can see that there are two different ways that the nix elixir ends up in my path when elixir-ls starts up:

  1. If I launch from a terminal with the right path already setup: code . works.
  2. If I launch VSCode from the OSX Applications, I need the direnv plugin enabled to have initialized my PATH correctly before elixir-ls starts.

In any case, it appears to be working now with v0.27.2 👍🏻

Thanks for your hard work maintaining this plugin!

mattwynne avatar Mar 27 '25 14:03 mattwynne