C.W.K.
Stream
Lesson 04 of 04 · published

Native LSP in Neovim 0.11+

~16 min · neovim, lsp, code-intelligence

Level 0Trapped
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

Code intelligence without nvim-lspconfig

Until Neovim 0.10 you needed nvim-lspconfig + manually installed servers. Neovim 0.11 introduced native APIs — vim.lsp.config() to declare a server, vim.lsp.enable() to turn it on — that make basic LSP setup a 5-line affair. nvim-lspconfig still helps for complex setups, but for the common path you don't need it.

What "LSP" gives you

  • Go to definition (K for hover, gd in most setups, or vim.lsp.buf.definition()).
  • Find references — every place a symbol is used.
  • Rename — refactor a symbol across the project.
  • Code actions — quick fixes, auto-imports, refactors offered by the language server.
  • Diagnostics — errors and warnings inline.
  • Document symbols — outline of the file.
  • Signature help in Insert mode.

The default mappings (Neovim 0.11+)

Out of the box, with no config, these work as soon as a server attaches: grn rename, grr references, gri implementation, gra code action, gO document symbols, K hover, Ctrl-S signature help (Insert mode), [d / ]d previous / next diagnostic. They're mnemonic — g for "go," r for "references," n for "name (rename)."

Configuring a server

You install the server binary (via your package manager, brew, cargo, npm, etc., or with mason.nvim), then declare it in your config. Three popular ones:

Mason — the optional package manager for servers

mason.nvim installs LSP servers, formatters, linters, and DAP adapters from inside Neovim with :Mason. Optional in 0.11+ — you can install servers via brew/apt yourself — but convenient when you bounce between machines.

Servers are the source of truth. The Neovim LSP client doesn't know about Python or TypeScript — it just speaks the LSP protocol to whatever server you point it at. If autocomplete or diagnostics feel off, the bug is almost always in the server's config, not in Neovim. Read the server's docs, not Neovim's.

Code

Configure three common LSP servers — Neovim 0.11+·lua
-- Lua language server (for editing your own Neovim config)
vim.lsp.config("lua_ls", {
  cmd = { "lua-language-server" },
  root_markers = { ".luarc.json", ".git" },
  settings = {
    Lua = {
      runtime = { version = "LuaJIT" },
      workspace = {
        checkThirdParty = false,
        library = vim.api.nvim_get_runtime_file("", true),
      },
      diagnostics = { globals = { "vim" } },
    },
  },
})

-- Python
vim.lsp.config("pyright", {
  cmd = { "pyright-langserver", "--stdio" },
  root_markers = { "pyproject.toml", "setup.py", "setup.cfg", ".git" },
})

-- TypeScript / JavaScript
vim.lsp.config("ts_ls", {
  cmd = { "typescript-language-server", "--stdio" },
  root_markers = { "tsconfig.json", "package.json", ".git" },
})

-- Turn them on
vim.lsp.enable({ "lua_ls", "pyright", "ts_ls" })
Default LSP keymaps (Neovim 0.11+) — already wired·vim
K            " hover documentation
grn          " rename symbol
grr          " find references
gri          " go to implementation
gra          " code action
gO           " document symbols (outline)
Ctrl-S       " signature help (Insert mode)
[d   ]d      " previous / next diagnostic
Ctrl-W d     " show diagnostic float at cursor
Optional — Mason for installing servers·lua
-- Add to lazy.nvim plugin spec
{
  "williamboman/mason.nvim",
  cmd = "Mason",
  build = ":MasonUpdate",
  opts = {},
}

-- Then :Mason to open the UI and install servers
Sane diagnostic display·lua
vim.diagnostic.config({
  virtual_text = { prefix = "●", spacing = 2 },
  signs = true,
  underline = true,
  update_in_insert = false,   -- diagnostics don't shift while you type
  severity_sort = true,
  float = { border = "rounded", source = true },
})

External links

Exercise

Pick one language you use daily (Python, JavaScript, Lua). Install its LSP server (e.g. pip install pyright, npm install -g typescript-language-server typescript, brew install lua-language-server). Add the corresponding vim.lsp.config + vim.lsp.enable lines to your init.lua. Open a project file. Test K (hover), grn (rename), gra (code action). Run :LspInfo to confirm the server attached.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.