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 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.

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-server
  • vscode-css-language-server
  • vscode-json-language-server
  • vscode-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"]

References