How To Integrate Esbonio with Neovim

This guide covers how to setup esbonio with Neovim’s built-in language client.

Installation

Note

The esbonio Python package does not need to be installed into the same environment as your project dependencies. A single, global installation is all that is required.

It’s recommended to install the language server using a tool like uv:

uv tool install --prerelease allow esbonio

or pipx:

pipx install --pip-args='--pre' esbonio

Of course, you can use pip to install esbonio into a virtual environment of your choosing, the most important thing is that the esbonio command is available on your PATH:

$ esbonio --help
usage: esbonio [-h] [-p PORT] [--version] [-i MOD] [-e MOD]

The Esbonio language server

options:
  -h, --help         show this help message and exit
  -p, --port PORT    start a TCP instance of the language server listening on the given port.
  --version          print the current version and exit.

modules:
  include/exclude language server modules.

  -i, --include MOD  include an additional module in the server configuration, can be given multiple times.
  -e, --exclude MOD  exclude a module from the server configuration, can be given multiple times.

Configuration

Every Neovim configuration is unique, so we provide just a minimal example configuration that uses the vim.lsp.config() mechanism introduced in Neovim v0.11. See the Tips and Tricks section below for examples on how you might want to extend your configuration once you have the basics setup.

The following configuration should be all you need to instruct Neovim to launch the esbonio language server within your Sphinx projects.

vim.lsp.config('esbonio', {
  cmd = {'esbonio'},
  filetypes = { 'rst' }, -- or 'markdown' if you use MyST
  root_markers = { '.git' },
})
vim.lsp.enable('esbonio')

However, to be useful you will also need to ensure that the esbonio.sphinx.pythonCommand and esbonio.sphinx.buildCommand options are configured for your project. The recommended way to do this is via your project’s pyproject.toml file, for example

[tool.esbonio.sphinx]
buildArguments = ["sphinx-build", "-M", "dirhtml", ".", "${defaultBuildDir}"]
pythonCommand = ["hatch", "-e", "docs", "run", "python"]

Tip

See How To Configure the Sphinx Build Environment and How To Configure the Sphinx Build guides for more examples of these settings.

If you don’t have a pyproject.toml file, or would prefer to set these options directly in neovim you can include a settings table

vim.lsp.config('esbonio', {
  cmd = {'esbonio'},
  filetypes = { 'rst' }, -- or 'markdown' if you use MyST
  root_markers = { '.git' },
  settings = {
    esbonio = {
      sphinx = {
        buildCommand = {'sphinx-build', '-M', 'dirhtml', '.', '${defaultBuildDir}'},
        pythonCommand = {'hatch', '-e', 'docs', 'run', 'python'},
      }
    },
  },
})
vim.lsp.enable('esbonio')

The settings table can be used to set any configuration value supported by the server. See the Configuration Reference for details on all available options.

Example

See the init.lua file below for a complete, minimal example configuration. If you want to try it out, you can download it here and load it by running the command nvim -u init.lua.

-- Basic options
vim.opt.number = true
vim.opt.shiftwidth = 3

-- Diagnostics
vim.diagnostic.config({
  virtual_lines = { current_line = true },
})

-- LSP Config
vim.lsp.config('esbonio', {
  cmd = { 'esbonio' },
  filetypes = { 'rst' },
  root_markers = { '.git' },
  settings = {
    esbonio = {
      -- sphinx = {
      --   See: See: https://docs.esbon.io/en/latest/lsp/howto/configure-the-sphinx-build-cmd.html
      --   buildCommand = { 'sphinx-build', '-M', 'dirhtml', '.', './_build' },
      --
      --   See: https://docs.esbon.io/en/latest/lsp/howto/configure-the-sphinx-build-env.html
      --   pythonCommand = { 'hatch', '-e', 'docs', 'run', 'python' },
      -- },
      -- logging = {
      --   level = 'debug',
      --   filepath = 'esbonio.log'
      -- },
    },
  },
})
vim.lsp.enable('esbonio')
-- vim.lsp.set_log_level('DEBUG')

Tips and Tricks

sphinx-build progress notifications

esbonio uses the window/workDoneProgress/create mechanism to report the progress of background Sphinx builds. You can use a plugin like fidget to provide a UI for these.

Troubleshooting

The :checkhealth vim.lsp command will show you details about your current configuration

:checkhealth vim.lsp
vim.lsp:                                     require("vim.lsp.health").check()

- LSP log level : DEBUG
- ⚠️ WARNING Log level DEBUG will cause degraded performance and high disk usage
- Log path: /var/home/username/.local/state/nvim/lsp.log
- Log size: 267 KB

vim.lsp: Active Clients ~
- esbonio (id: 1)
  - Version: 1.0.0b11
  - Root directory: /tmp/rst
  - Command: { "esbonio" }
  - Settings: {
      esbonio = {
        logging = {
          level = "debug"
        },
        sphinx = {
          buildCommand = { "sphinx-build", ".", "./_build" },
          pythonCommand = { "python" }
        }
      }
    }
  - Attached buffers: 1

vim.lsp: Enabled Configurations ~
- esbonio:
  - cmd: { "esbonio" }
  - filetypes: rst
  - root_markers: .git
  - settings: {
      esbonio = {
        logging = {
          level = "debug"
        },
        sphinx = {
          buildCommand = { "sphinx-build", ".", "./_build" },
          pythonCommand = { "python" }
        }
      }
    }


vim.lsp: File Watcher ~
- file watching "(workspace/didChangeWatchedFiles)" disabled on all clients

vim.lsp: Position Encodings ~
- No buffers contain mixed position encodings