TL; DR: In this article, I describe how I setup zed to develop in elixir and phoenix framework, and here is the gist having the settings I use
It's been a while since I use VS Code to develop elixir applications, and so far, it has been a great tool, especially when using extensions like ElixirLS, Phoenix Framework, Jump to Test, and others.
But like all tools, it has some bottlenecks, and for me, the bottleneck is when working with large projects, where I need to switch between branches multiple times during the day.
Because of that, I started to search for alternatives, and Zed seemed to be the new hype. Don't get me wrong. I know many developers love Vim, but I'm a UI boy and haven't had good experiences with it; I know it's a great editor, but it's just not my thing 😅.
So, let's go back to Zed. To install it, you can use package managers like homebrew or download it directly from their website.
To download by homebrew, you can use the following command:
$ brew install --cask zed && zed
That's it; you have Zed installed; now let's configure it for Elixir development!
One of the most important tools, at least for me, is the language server, which helps with auto-complete, lint validations, and formatting.
Since the first version of this article, many other language servers have been created for elixir, and, as far as I know, we have 5 options, elixir-ls, lexical, next-ls, and the newer ones expert and dexter.
While all the options have their highlights, I feel like the one that works better to me, with the less usage of resources like RAM and CPU, was dexter, which works pretty well on large elixir projects, using < 200MB from my experience, compared to expert, which I saw using more than 3GB multiple times.
The setup of these LSP are really similar, and most of them can be automatically installed by zed by adding this to your zed settings (use the shortcut cmd + shift + P if you're on mac, or ctrl + shift + P if you're on Windows):
"languages": {
"Elixir": {
"language_servers": ["elixir-ls"] // <- `next-ls` or `lexical`
}
}
Then, you can setup the specifics based on what language server you prefer, for ElixirLS, I like to turn off dialyzer when developing and let CIs like CircleCI or Github Actions to run that for me when I push the branch, to do so, you can add lsp config like below:
"lsp": {
"elixir-ls": {
"settings": {
"dialyzerEnabled": false
}
}
}
Pretty easy, right? But here are some caveats, I had a few issues while using LSP from zed server, as sometimes it returned 422 HTTP error for me, so I end up using the LSP locally, which is great as it will work without internet connection too, in case you need to download it again.
To do so, I'll use the dexter example, trust me, is the best option available so far 😁. First, install it using one of the following commands:
# via mise
mise plugin add dexter https://github.com/remoteoss/dexter.git && mise use -g dexter@latest
# via asdf
asdf plugin add dexter https://github.com/remoteoss/dexter.git && asdf install dexter latest && asdf set --home dexter latest
# via Homebrew
brew install remoteoss/tap/dexter
Then, use the command whereis dexter, to find the exact location of dexter, and on zed settings add:
{
"languages": {
"Elixir": {
"language_servers": ["dexter", "tailwindcss-language-server"],
"format_on_save": "on",
},
"HEEx": {
"language_servers": [
"dexter",
"tailwindcss-language-server",
"emmet-language-server",
],
},
},
"lsp": {
"dexter": {
"binary": {
"path": **"<dexter-location>"**,
"arguments": ["lsp"],
},
"settings": {
"workspaceSymbols": {
"minQueryLength": 0,
},
"dialyzerEnabled": false,
},
},
},
}
With the config above you should be able to see auto format working, as well code snippets, syntax highlight, and so on.
In the snippet above, we're setting up heex to format using mix format, elixir-ls, for elixir code that may be inside of the heex files, tailwindcss-language-server, to have tailwind classes auto-complete, and emmet-language-server, to have auto-complete for HTML (i.e. div.flex to be converted to <div class="flex"></div>).
One caveat about Emmet, you may need to do a workaround to make it work as expected. First, use cmd + shift + P, and select option zed: extensions, and install Emmet extension. Once you install it, open and edit the file ~/Library/Application\ Support/Zed/extensions/installed/emmet/extension.toml to reference heex extension:
[language_servers.emmet-language-server]
language = "HTML"
languages = ["HTML", "PHP", "ERB", "JavaScript", "TSX", "CSS", "HEEX"]
[language_servers.emmet-language-server.language_ids]
HEEX = "heex"
Well, that's pretty much it; thank you for reading this! I hope this was useful for you. If you like it or have suggestions on how I can improve this post, please leave a comment; I'll be glad to know that this is being helpful 😄.
Here's the gist having my Zed config, where I'm going to keep updating when learning more about it.
Cheers!
Top comments (5)
Intenal LSP formatting is faster than using mix
Hey Rui, yeah, I think that makes sense, and it probably explains why the vscode format is faster; thanks for your comment 🙇♂️
Basically, all you have to do is to delete the lines from your config where you format using mix.
I can confirm, as I have tried both approaches, that using LSP formatting in Zed is way faster.
Thanks for the tip Paulo, I've been using VIM and VSCode since the beginning, I'm going to test ZED and see how it will perform.
Very nice guide!
Add:
Common path in linux for 'extensions.tom' -> '~/home/{user}/.local/share/zed/extensions'