Feature request: make searching for ASDF optional
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.
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.
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?)
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. :)
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.
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!
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?
ELS_DISABLE_VERSION_MANAGERS would work for me, yup!
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.
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
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?
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.
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!
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 @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.
It solves the issue for me, thanks @lukaszsamson !
@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.
@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?
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 I confirm 0.27.2 is working for me now :)
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:
- If I launch from a terminal with the right path already setup:
code .works. - If I launch VSCode from the OSX Applications, I need the direnv plugin enabled to have initialized my
PATHcorrectly 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!