LSP Integration
Vim Intermediate/Advanced
Chapter 7 — LSP Integration
What the Language Server Protocol Is
Before the Language Server Protocol existed, every editor needed its own custom integration for every language it wanted to support well — autocomplete, go-to-definition, inline errors, all built and maintained separately, per editor, per language. With N editors and M languages, that's N×M separate integrations.
LSP standardizes the conversation instead: a language server (one implementation per language — pyright for Python, gopls for Go, a TypeScript server for JS/TS) speaks a common JSON-RPC protocol, the same client/server RPC model the site's own grpc1 course covers from the opposite side. Any editor that implements the client half of LSP can talk to any language server — N+M integrations instead of N×M. Neovim has shipped a built-in LSP client since version 0.5; you don't install a separate plugin for the client itself, only for configuration convenience (below) and completion UI.
nvim-lspconfig — Configuring Language Servers
nvim-lspconfig is a collection of ready-made configuration templates for popular language servers — it is not the LSP client itself (that's built in), just the sensible defaults that spare you from hand-writing each server's specific startup command and settings:
-- init.lua require('lspconfig').pyright.setup({})
pyright.setup({}) tells Neovim how to talk to pyright — but pyright's actual executable still has to exist on your machine first (e.g. npm install -g pyright). "I configured lspconfig and nothing happens" is almost always this: the config is correct, but the server binary was never installed. Mason.nvim is the modern convenience layer that manages installing and updating language server binaries directly from within Neovim, sparing you the separate package-manager step.
Autocompletion with nvim-cmp
The LSP client receives completion data from the language server, but Neovim's own built-in completion UI is minimal. nvim-cmp is the standard plugin providing an actual completion popup menu, pulling suggestions from multiple sources at once — the LSP client, buffer words, snippets:
-- init.lua local cmp = require('cmp') cmp.setup({ sources = { { name = 'nvim_lsp' }, -- suggestions from the language server { name = 'buffer' }, -- suggestions from words already in the buffer }, })
Diagnostics — Errors and Warnings Inline
A language server continuously reports diagnostics — errors, warnings, hints — which Neovim renders as inline virtual text and gutter signs, updating as you type:
]d # jump to the next diagnostic in the buffer [d # jump to the previous diagnostic :lua vim.diagnostic.open_float() # show full diagnostic detail for the current line in a floating window
This is the same underlying concept as the Problems panel from the site's own VS Code course — errors surfaced directly in the editor rather than only at compile/run time — just rendered inline instead of in a separate panel.
Navigation — Go to Definition, Hover, References
LSP-powered navigation is wired up through Neovim's vim.lsp.buf functions, typically bound to keys inside an on_attach function — code that runs automatically each time a language server attaches to a buffer:
local on_attach = function(client, bufnr) vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { buffer = bufnr }) vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = bufnr }) vim.keymap.set('n', 'gr', vim.lsp.buf.references, { buffer = bufnr }) end require('lspconfig').pyright.setup({ on_attach = on_attach })
| Key | Action |
|---|---|
gd | Go to definition — jump to where the symbol under the cursor is actually defined |
K | Hover — show documentation/type info for the symbol under the cursor |
gr | References — list every place the symbol is used across the project |
These keymaps reuse the exact vim.keymap.set mechanism from Chapter 6, just scoped to the buffer ({ buffer = bufnr }) so they only apply where a language server is actually attached, rather than globally.
LSP Is Not the Same as Debugging
It's easy to conflate LSP with the debugging covered in the site's VS Code course (breakpoints, stepping, the call stack) — but they're genuinely different protocols solving different problems. LSP covers editing-time intelligence: completion, diagnostics, navigation, all without running your code. Runtime debugging uses a separate standard, the Debug Adapter Protocol (DAP) — Neovim's equivalent tooling there is nvim-dap, conceptually parallel to VS Code's launch.json/breakpoints, but a distinct plugin and protocol from everything in this chapter.