To set up language support for helix, there are two things that need to be done. First, you will need to install the LSP language server for your desired language. Second, configure the language server in the languages.toml file.
The language file is stored in ~/.config/helix/languages.toml
Along the way, I started getting a TOML warning in languages.toml that my file was not set up correctly. In the end, moving all the [[languages]] sections above all the [language-server] items cleared up the issue.
Getting Started
Helix documents its language support (LSP) features in:
- Helix Documentation
- Sections 4.4 Languages
- Section 5 Guides
- Helix GitHub Wiki
Helix has a built-in command to check whether language services are installed. hx --health give a table of supported languages and whether various features are installed.
To check a specific language, use the following command:
hx --health markdown
“Markdown” gets replaced by the language you are interested in supporting.
One thing to consider is which languages you will want to have supported. For my use case, I’m looking at the following to get started:
- Go (supported out of the box)
- Markdown
- HTML
- CSS
- python
- TOML
- fish
- bash
Look at this documentation page for more info about language support in helix.
The second thing to consider is that you will need to install the binary LSP files for each language onto your system. These get installed in various ways and various operating systems. So, that could influence your decision. For example, I had rust cargo installed, but didn’t have homebrew on my Linux box. This makes me try cargo installers over homebrew first.
The third thing is considering formatting.
Markdown
I’m starting with Markdown because I found an excellent post about setting up Markdown in Helix. I spend a lot of time writing Markdown (this website is powered by Markdown files).
For Markdown, there are two good language server options. Markdown-oxide and marksman help with links and general language support and LTEX+ works on spelling and grammar.
Language Servers
Markdown Oxide
Markdown Oxide is a language server that helps with link and tag completions among other features.
Installs with the rust tool set:
cargo install --locked --git https://github.com/Feel-ix-343/markdown-oxide.git markdown-oxide
Marksman
Marksman assists with Markdown by providing completions, go to definitions, references, and diagnostics.
Install Marksman with homebrew.
brew install marksman
ltex-ls-plus
LTEX+ implements grammar and spell checking for Markdown files.
Tried to configure LTEXT+ to read from a dictionary.txt file. It did not seem to work. So, moved on to setting up Harper as a grammar checker.
Harper
Harper is another grammar and spelling checker option.
Installed Harper with Homebrew using the brew install harper command.
Also created a file ~/.config/harper-ls/dictionary.txt that contains a list of words, one word per line.
Formatter
DPrint and Prettier are both excellent options for formatting your Markdown documents.
- DPrint Formatter
- Prettier is also an option.
Configuration: languages.toml for Markdown
Here is my current language configuration for Markdown. I am running marksman and LTEX+ as language servers and have Markdown Oxide commented out. I’m also running dprint for formatting, but the syntax for prettier is included but commented out.
The comment-tokens cause the comment character to be duplicated down to the next line when hitting enter. This means if you’re writing a list using dashes, Helix will automatically add another “-” when you start another line.
[[language]]
name = "markdown"
language-servers = ["marksman", "ltex-ls-plus"]
# language-servers = ["markdown-oxide"]
formatter = { command = "dprint", args = ["fmt", "--stdin", "md"] }
comment-tokens = ["-", "+", "*", "- [ ]", ">"]
# formatter = { command = 'prettier', args = ["--parser", "markdown"] }
auto-format = true
Here is an example of the health option after configuring for Markdown.
>>> hx --health markdown
Configured language servers:
✓ marksman: /home/linuxbrew/.linuxbrew/bin/marksman
✓ ltex-ls-plus: /home/keith/scripts/ltex-ls-plus
Configured debug adapter: None
Configured formatter: dprint
Binary for formatter: /home/linuxbrew/.linuxbrew/bin/dprint
Tree-sitter parser: ✓
Highlight queries: ✓
Textobject queries: ✘
Indent queries: ✘
TOML
Language Server
To install cargo install taplo-cli --locked
Taplo can do a lot more. So, it is worth checking out if working with more .toml files.
After installing taplo, found that hx --health toml was also looking for a tool named ’tombi’ Installed with uv tool install tombi.
Formatter
Taplo is the configured formatter.
Configuration: languages.toml
[[language]]
formatter = { command = "taplo", args = ["fmt", "-"] }
auto-format = true
Python
Language Server
I currently have pylsp and ruff set up. Jedi-language-server is also an option.
uv tool install python-lsp-server
uv tool install ruff
uv tool install jedi-language-server
Formatter
Ruff is the configured formatter.
Configuration: languages.toml
[[language]]
name = "python"
language-servers = ["pylsp", "ruff"]
formatter = { command = "ruff", args = ["format", "--line-length", "88", "-"] }
auto-format = true
[language-server.pylsp.config.pylsp]
plugins.pylsp_mypy.enabled = true
plugins.pylsp_mypy.live_mode = true
Fish
Language Server
brew install fish-lsp
Adding completions to the fish shell:
fish-lsp complete > ~/.config/fish/completions/fish-lsp.fish
Formatter
The fish shell comes with a fish_indent tool that can be used to format your fish code.
languages.toml
[[language]]
name = "fish"
language-servers = ["fish-lsp"]
file-types = ["fish"]
formatter = { command = "fish_indent" }
auto-format = true
[language-server.fish-lsp]
command = "fish-lsp"
args = ["start"]
environment = { "fish_lsp_show_client_popups" = "false" }
HTML
Language Server
For HTML, use vscode-langservers-extracted which includes:
vscode-html-language-servervscode-css-language-servervscode-json-language-servervscode-eslint-language-server
# Installation commands
npm i -g vscode-langservers-extracted
# emmet
npm install -g emmet-ls
Formatter
Configuration: languages.toml
[[language]]
name = "html"
language-servers = ["vscode-html-language-server", "emmet-ls"]
# formatter = { command = 'npx', args = ["prettier", "--parser", "html"] }
formatter = { command = 'prettier', args = ["--parser", "html"] }
auto-format = true
[language-server.emmet-ls]
command = "emmet-ls"
args = ["--stdio"]
CSS
The language server for CSS was included when installing vscode-langservers-extracted as shown above in HTML
Language Server
Formatter
languages.toml
[[language]]
name = "css"
language-servers = ["vscode-css-language-server"]
formatter = { command = 'prettier', args = ["--config", ".prettierrc", "--parser", "css"] }
auto-format = true
Bash
Language Server
I’m also including shell check here, since it is a stand-alone tool that checks the integrity of shell scripts.
npm i -g bash-language-server
sudo apt install shellcheck
sudo apt install shfmt
Formatter
Using shfmt. I like to have 4 spaces for indentation, so I’m using -i 4 as format arguments.
Configuration: languages.toml
[[language]]
name = "bash"
language-servers = ["bash-language-server"]
formatter = { command = 'shfmt', args = ["-i", "4"] }
file-types = ["sh"]