Emacs - Elixir Setup Configuration Wiki

So currently having no issues with this configuration, only minor problem is that popups in GUI mode are a bit too big, anybody know how to change this?
Example:
https://i.imgur.com/Y8tRDfq.jpg

I actually just disable that with '(lsp-ui-doc-enable nil) in spacemacs custom-set-variables. But it would probably be better to raise an error on lsp-ui. It looks like there is a semi-related issue open already: https://github.com/emacs-lsp/lsp-ui/issues/267 And perhaps you could try setting lsp-ui-doc-use-webkit to t?

Doesnā€™t do anything :frowning: Iā€™ll just disable it for now and keep watching the issue.

FWIW, the scala LSP doesnā€™t have these big popups

Iā€™m trying to use elixir_ls on a monorepo with an elixir application in a subdirectory in spacemacs. lsp-mode works when I use it on a standalone elxiir repo, with flycheck errors showing up.

From googling it seems I need to set ElixirLS.ProjectDir - https://github.com/JakeBecker/elixir-ls/issues/29. Iā€™ve tried doing this with :lsp-add-project-dir and :lsp-switch-project-dir, but that doesnā€™t seem to help. Has anyone had any success with this scenario?

Thanks for putting this wiki together first of all.

I used to get this working on spacemacs, but I have a new laptop at work and although I copied all my spacemacs and emacs settings, I cannot get elixir_ls to work.

Iā€™m getting the following error:

LSP :: elixir-ls has exited (exited abnormally with code 127)

I think it may have sth to do with elixir version. I initially installed 1.8 using homebrew, but having re-read the instructions, I installed asdf and I think I switched to the recommended version of Elixir. But still no joy and elixir-ls seems to be crashing when I open an Elixir file in spacemacs.

Any idea how to troubleshoot this?

1 Like

@clag try to add this line before the one you are using:

(require 'eglot)

Ok. I found that spacemacs cannot find the elixir binary.

code/elixir/elixir-ls/release/language_server.sh: line 18: elixir: command not found

I tried adding ~/.asdf/shims to the path but still not working. But I think I may be on the right track. Just need to figure out how to support asdf in spacemacs.

Does your .spacemacs.env (~/.spacemacs.env or ~/.spacemacs.d/.spacemacs.env) have elixir in $PATH?

I added ~/.asdf/shims to $PATH in ~/.spacemacs.env and checked the value of exec-path variable in spacemacs and it now contains the path to elixir from from asdf but elixir-ls is still not starting with the same error.

I instrumented the language_server.sh script by adding:

>&2 echo Environment is
>&2 env
>&2 echo elixir is
>&2 which elixir

And now can see in the *elixir-ls::stderr* buffer that something is resetting the $PATH to:

Environment is
...
PATH=/usr/bin:/bin:/usr/sbin:/sbin
...
elixir is
/Users/myuser/code/elixir/elixir-ls/release/language_server.sh: line 24: elixir: command not found
2 Likes

What operating system is this? Also what shell are you using? Iā€™m wondering if this is a difference between something like ~/.bash_profile and ~/.bashrc. My ~/.bash_profile contains . ~/.bashrc to source my whole bashrc (although in this case you only need the correct $PATH)

The operating system is macOS Mojave. Shell is zsh + oh-my-zsh plugins.

I found a post on Reddit suggesting to delete emac.d/melpa: https://www.reddit.com/r/emacs/comments/ab34v5/lspmode_unable_get_up_and_running/

Having done so I found that my .spacemacs.env had two PATH= lines so I deleted the one which had fewer directories. Not sure which step fixed it because unfortunately I did both things at the same time but everything is working now.

Iā€™ve later added the incomplete PATH= back to my .spacemacs.env and itā€™s still working so it looks more like purging melpa packages and re-installing them did the trick.

I had moved my .emacs.d directory from a different laptop which was running a different version of MacOS so there may have been some binaries there which were not compatible with the current OS ?

Thanks for the help!

1 Like

Ah, interesting. I wonder what in your melpa directory ended up modifying the PATH. Glad you got it working!

Is the main elixir-ls repo actively maintained again? I see it has new commits.

Btw, I just setup my emacs for elixir development. Thanks for this guide! This is all the configuration I needed to get a very functional setup. Maybe someone finds it useful.

(use-package elixir-mode)

(use-package yasnippet)

(use-package lsp-mode
  :bind ("C-c h" . lsp-describe-thing-at-point)
  :commands lsp
  :ensure t
  :diminish lsp-mode
  :hook
  (elixir-mode . lsp)
  :init
  (add-to-list 'exec-path "D:/repos/elixir-ls/release")
  (setq lsp-ui-doc-enable nil))

(use-package company)

(use-package company-lsp
  :bind
  ("M-SPC" . company-complete)
  :config
  (push 'company-lsp company-backends)
  (setq company-idle-delay 0)
  (setq company-minimum-prefix-length 1))
3 Likes

Yeah it is currently being maintained. Updated the wiki accordingly. And thanks for sharing your configuration!

1 Like

Iā€™m also struggling to get syntax highlighting working. The language server highlights errors once, when opening the project for the first time. After saving, errors are not updated. In addition, jumping to definitions doesnā€™t seem to work properly either. Hereā€™s my relevant setup:

Elixir 1.8.1
Erlang 21
ElixirLS JakeBecker v0.2.25

(use-package flycheck
  :hook (after-init-hook . global-flycheck-mode))

(use-package lsp-mode)

(use-package lsp-ui
  :config
  (define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
  (define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)
  (setq lsp-ui-sideline-enable t
        lsp-ui-doc-enable t
        lsp-ui-doc-delay 1.0
        lsp-ui-doc-position 'bottom
        lsp-ui-flycheck-enable t
        lsp-ui-imenu-enable t
        lsp-ui-sideline-ignore-duplicate t))

(use-package company-lsp
  :config
  (push 'company-lsp company-backends))

(add-to-list 'exec-path (expand-file-name "~/.emacs.d/elixir-lsp/"))

(use-package elixir-mode
  :config
  (add-hook
   'elixir-mode-hook
   #'lsp))

Iā€™m using lsp-mode for C++ with no problems, so I doubt itā€™s the issue. Any ideas? The log shows:

Started ElixirLS
Elixir version: "1.8.1 (compiled with Erlang/OTP 20)"
Erlang version: "21"

22:07:31.476 [warn]  Did not receive workspace/didChangeConfiguration notification after 5 seconds. Using default settings.
Compiling with Mix env test
Compiling 5 files (.ex)
<<<compile errors here>>>

Compile took 127 milliseconds

What compilation errors are you receiving? And is syntax highlighting in general not working, or just the highlighting of errors?

Shouldnā€™t this line:

(add-to-list 'exec-path (expand-file-name "~/.emacs.d/elixir-lsp/"))

contain release at the end, like this:

(add-to-list 'exec-path (expand-file-name "~/.emacs.d/elixir-lsp/release/"))

Thanks for the replies!

Sorry, I should have clarified. Iā€™ve attached a screenshot of an example program and the error, after which elixir-lsp becomes unresponsive.

Example File (In mix project):

defmodule LspTest do

  foo
  bar
  baz

  @moduledoc """
  Documentation for LspTest.
  """

  @doc """
  Hello world.

  ## Examples

      iex> LspTest.hello()
      :world

  """
  def hello do
    foobar
    :world
  end
end

LSP Output:

09:14:27.362 [error] Process #PID<0.132.0> raised an exception
** (FunctionClauseError) no function clause matching in ElixirSense.Core.Source.tokenize_prefix/1
    lib/elixir_sense/core/source.ex:152: ElixirSense.Core.Source.tokenize_prefix({:ok, []})
    lib/elixir_sense/core/source.ex:138: ElixirSense.Core.Source.which_func/1
    lib/elixir_sense/providers/signature.ex:19: ElixirSense.Providers.Signature.find/5
    (language_server) lib/language_server/providers/signature_help.ex:4: ElixirLS.LanguageServer.Providers.SignatureHelp.signature/3
    (language_server) lib/language_server/server.ex:425: anonymous fn/3 in ElixirLS.LanguageServer.Server.handle_request_async/2

09:14:39.031 [error] Process #PID<0.139.0> raised an exception
** (FunctionClauseError) no function clause matching in ElixirSense.Core.Source.tokenize_prefix/1
    lib/elixir_sense/core/source.ex:152: ElixirSense.Core.Source.tokenize_prefix({:ok, [{:identifier, {1, 1, nil}, :defmodule}, {:alias, {1, 11, nil}, :LspTest}, {:identifier, {1, 19, nil}, :d}]})
    lib/elixir_sense/core/source.ex:138: ElixirSense.Core.Source.which_func/1
    lib/elixir_sense/providers/signature.ex:19: ElixirSense.Providers.Signature.find/5
    (language_server) lib/language_server/providers/signature_help.ex:4: ElixirLS.LanguageServer.Providers.SignatureHelp.signature/3
    (language_server) lib/language_server/server.ex:425: anonymous fn/3 in ElixirLS.LanguageServer.Server.handle_request_async/2

09:14:41.932 [error] Process #PID<0.154.0> raised an exception
** (FunctionClauseError) no function clause matching in ElixirSense.Core.Source.tokenize_prefix/1
    lib/elixir_sense/core/source.ex:152: ElixirSense.Core.Source.tokenize_prefix({:ok, [{:identifier, {1, 1, nil}, :defmodule}, {:alias, {1, 11, nil}, :LspTest}, {:do, {1, 19, nil}}, {:eol, {1, 21, 2}}, {:identifier, {3, 3, nil}, :foo}, {:eol, {3, 6, 1}}, {:identifier, {4, 3, nil}, :bar}, {:eol, {4, 6, 1}}, {:identifier, {5, 3, nil}, :baz}, {:eol, {5, 6, 2}}, {:at_op, {7, 3, nil}, :@}, {:identifier, {7, 4, nil}, :moduledoc}, {:bin_heredoc, {7, 14, nil}, ["Documentation for LspTest.\n"]}, {:eol, {9, 6, 2}}, {:at_op, {11, 3, nil}, :@}, {:identifier, {11, 4, nil}, :doc}, {:bin_heredoc, {11, 8, nil}, ["Hello world.\n\n## Examples\n\n    iex> LspTest.hello()\n    :world\n\n"]}, {:eol, {19, 6, 1}}, {:identifier, {20, 3, nil}, :def}, {:do_identifier, {20, 7, nil}, :hello}, {:do, {20, 13, nil}}, {:eol, {20, 15, 1}}, {:identifier, {21, 5, nil}, :foobar}, {:eol, {21, 11, 1}}, {:atom, {22, 5, nil}, :world}, {:eol, {22, 11, 1}}, {:end, {23, 3, nil}}, {:eol, {23, 6, 1}}, {:end, {24, 1, nil}}, {:eol, {24, 4, 1}}]})
    lib/elixir_sense/core/source.ex:138: ElixirSense.Core.Source.which_func/1
    lib/elixir_sense/providers/signature.ex:19: ElixirSense.Providers.Signature.find/5
    (language_server) lib/language_server/providers/signature_help.ex:4: ElixirLS.LanguageServer.Providers.SignatureHelp.signature/3
    (language_server) lib/language_server/server.ex:425: anonymous fn/3 in ElixirLS.LanguageServer.Server.handle_request_async/2

09:15:20.077 [error] Process #PID<0.156.0> raised an exception
** (FunctionClauseError) no function clause matching in ElixirSense.Core.Source.tokenize_prefix/1
    lib/elixir_sense/core/source.ex:152: ElixirSense.Core.Source.tokenize_prefix({:ok, [{:identifier, {1, 1, nil}, :defmodule}, {:alias, {1, 11, nil}, :LspTest}, {:do, {1, 19, nil}}, {:eol, {1, 21, 2}}, {:identifier, {3, 3, nil}, :foo}, {:eol, {3, 6, 1}}, {:identifier, {4, 3, nil}, :bar}, {:eol, {4, 6, 1}}, {:identifier, {5, 3, nil}, :baz}, {:eol, {5, 6, 2}}, {:at_op, {7, 3, nil}, :@}, {:identifier, {7, 4, nil}, :moduledoc}, {:bin_heredoc, {7, 14, nil}, ["Documentation for LspTest.\n"]}, {:eol, {9, 6, 2}}, {:at_op, {11, 3, nil}, :@}, {:identifier, {11, 4, nil}, :doc}, {:bin_heredoc, {11, 8, nil}, ["Hello world.\n\n## Examples\n\n    iex> LspTest.hello()\n    :world\n\n"]}, {:eol, {19, 6, 1}}, {:identifier, {20, 3, nil}, :def}, {:do_identifier, {20, 7, nil}, :hello}, {:do, {20, 13, nil}}, {:eol, {20, 15, 1}}, {:identifier, {21, 5, nil}, :foobar}, {:eol, {21, 11, 1}}, {:atom, {22, 5, nil}, :world}, {:eol, {22, 11, 1}}, {:end, {23, 3, nil}}, {:eol, {23, 6, 1}}, {:end, {24, 1, nil}}, {:eol, {24, 4, 1}}]})
    lib/elixir_sense/core/source.ex:138: ElixirSense.Core.Source.which_func/1
    lib/elixir_sense/providers/signature.ex:19: ElixirSense.Providers.Signature.find/5
    (language_server) lib/language_server/providers/signature_help.ex:4: ElixirLS.LanguageServer.Providers.SignatureHelp.signature/3
    (language_server) lib/language_server/server.ex:425: anonymous fn/3 in ElixirLS.LanguageServer.Server.handle_request_async/2

I downloaded the pre-built server at https://github.com/JakeBecker/elixir-ls/releases/download/v0.2.25/elixir-ls.zip , which doesnā€™t use the release folder. Iā€™ve also tried building it myself, and have changed the folder accordingly with no avail.

Something I had to do when I was getting random lsp errors from elixir-ls was to upgrade the dependencies in the project mix deps.upgrade --all to update the dialyzer dependency to rc6. Itā€™s worth a shot.

Also my coworker had issues when his erlang version updated and he had to rebuild elixir-ls to get it to go away.

Sorry no direct answer but some things to try

Hi guys.

I have followed the wiki to install LSP, and itā€™s working pretty well. My problem though, itā€™s that I cannot use ā€œgo to definitionā€, and I donā€™t know why. When I try to use it, my Spacemacs says something like

No workspace could handle textDocument/definition

Any ideas? Probably Iā€™m doing something wrong.

Thanks for your help.