Mason and lspconfig

Mason and lspconfig

The division of labor

  • mason.nvim — a package manager for editor tooling. It downloads language servers (and formatters, linters, debug adapters) into Neovim’s data directory, no system package manager involved.
  • nvim-lspconfig — a data package: per-server launch commands, filetypes, and root-detection rules.
  • Neovim 0.11+ — provides the native activation: vim.lsp.config() to adjust a server, vim.lsp.enable() to turn it on.

Setup

With the plugins installed (vim-plug era):

require('mason').setup()
require('mason-lspconfig').setup({ensure_installed = {'lua_ls'}})

vim.lsp.config('lua_ls', {settings = {Lua = {diagnostics = {globals = {'vim'}}}}})

ensure_installed makes Mason fetch the server automatically; you can also install interactively with :Mason or :MasonInstall lua-language-server.

The vim.lsp.config call deep-merges settings over the lspconfig defaults — here telling lua-language-server that vim is a known global, which silences the most famous false diagnostic in Neovim configs.

One PATH gotcha worth knowing

Mason installs binaries into its own bin directory and puts it on Neovim’s PATH when mason.nvim loads. If mason is lazy-loaded, a file opened directly from the shell (nvim foo.lua) can attach before that happens — and the server silently fails to start. The robust fix is one early line in init.lua:

vim.env.PATH = vim.fn.stdpath('data') .. '/mason/bin:' .. vim.env.PATH

The course repo’s config ships with this fix in place.

Useful keymaps

Neovim 0.11+ provides defaults (grn rename, grr references, gra code action, K hover, [d/]d diagnostics). The one big omission is go-to-definition:

vim.keymap.set("n", "gd", vim.lsp.buf.definition, {desc="Go to definition"})