Drill 05: LSP Configuration
LSP configuration: nvim-lspconfig, mason, native API, and diagnostics.
| Essential for understanding domus-nvim LSP setup. |
Run This Drill
bash ~/atelier/_bibliotheca/domus-captures/docs/modules/ROOT/examples/lua-drills/05-lsp.sh
Drill Script
#!/bin/bash
# LUA DRILL 05: LSP CONFIGURATION
# Topics: nvim-lspconfig, mason, keymaps, diagnostics
echo "=================================================================="
echo " LUA DRILL 05: LSP CONFIGURATION "
echo "=================================================================="
echo ""
echo "Understanding LSP setup in modern Neovim"
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 5.1: LSP BASICS"
echo "What LSP provides and how it works"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- LSP = Language Server Protocol
-- Neovim is the CLIENT, language servers are SERVERS
--
-- Flow:
-- 1. Neovim opens file
-- 2. LSP client attaches to buffer
-- 3. Client sends document to server
-- 4. Server provides: completions, diagnostics, hover, goto definition, etc.
-- Check attached LSP clients
:lua print(vim.inspect(vim.lsp.get_active_clients()))
-- Check LSP for current buffer
:lua print(vim.inspect(vim.lsp.buf_get_clients()))
-- Common language servers:
-- lua_ls (Lua)
-- pyright (Python)
-- rust_analyzer (Rust)
-- tsserver (TypeScript/JavaScript)
-- gopls (Go)
-- clangd (C/C++)
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 5.2: NVIM-LSPCONFIG SETUP"
echo "Traditional LSP configuration"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- lua/domus/plugins/config/lsp/init.lua
-- Define capabilities (what client supports)
local capabilities = vim.lsp.protocol.make_client_capabilities()
-- If using nvim-cmp, extend capabilities
-- capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities)
-- Define on_attach (runs when LSP attaches to buffer)
local on_attach = function(client, bufnr)
local keymap = vim.keymap.set
local opts = {buffer = bufnr, silent = true}
-- Navigation
keymap('n', 'gd', vim.lsp.buf.definition, opts)
keymap('n', 'gD', vim.lsp.buf.declaration, opts)
keymap('n', 'gi', vim.lsp.buf.implementation, opts)
keymap('n', 'gr', vim.lsp.buf.references, opts)
keymap('n', 'K', vim.lsp.buf.hover, opts)
-- Actions
keymap('n', '<leader>rn', vim.lsp.buf.rename, opts)
keymap('n', '<leader>ca', vim.lsp.buf.code_action, opts)
keymap('n', '<leader>f', function()
vim.lsp.buf.format({async = true})
end, opts)
-- Diagnostics
keymap('n', '[d', vim.diagnostic.goto_prev, opts)
keymap('n', ']d', vim.diagnostic.goto_next, opts)
keymap('n', '<leader>d', vim.diagnostic.open_float, opts)
end
-- Setup individual servers
local lspconfig = require('lspconfig')
lspconfig.lua_ls.setup({
capabilities = capabilities,
on_attach = on_attach,
settings = {
Lua = {
diagnostics = {globals = {'vim'}},
workspace = {checkThirdParty = false},
},
},
})
lspconfig.pyright.setup({
capabilities = capabilities,
on_attach = on_attach,
})
lspconfig.rust_analyzer.setup({
capabilities = capabilities,
on_attach = on_attach,
})
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 5.3: MASON + MASON-LSPCONFIG"
echo "Auto-install and manage LSP servers"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Mason installs LSP servers, formatters, linters
-- Mason-lspconfig bridges mason and nvim-lspconfig
-- lua/domus/plugins/specs/lsp.lua
return {
{
"williamboman/mason.nvim",
build = ":MasonUpdate",
opts = {},
},
{
"williamboman/mason-lspconfig.nvim",
dependencies = {"williamboman/mason.nvim"},
opts = {
ensure_installed = {
"lua_ls",
"pyright",
"rust_analyzer",
},
automatic_installation = true,
},
},
{
"neovim/nvim-lspconfig",
dependencies = {"williamboman/mason-lspconfig.nvim"},
config = function()
require("domus.plugins.config.lsp")
end,
},
}
-- Mason-lspconfig can auto-setup servers:
require("mason-lspconfig").setup_handlers({
-- Default handler
function(server_name)
require("lspconfig")[server_name].setup({
capabilities = capabilities,
on_attach = on_attach,
})
end,
-- Custom handler for lua_ls
["lua_ls"] = function()
require("lspconfig").lua_ls.setup({
capabilities = capabilities,
on_attach = on_attach,
settings = {
Lua = {diagnostics = {globals = {'vim'}}}
}
})
end,
})
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 5.4: NEOVIM 0.11+ NATIVE LSP"
echo "Using vim.lsp.config without lspconfig"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Neovim 0.11+ has native LSP config API
-- No nvim-lspconfig needed for basic setup
-- Configure a server
vim.lsp.config.lua_ls = {
cmd = {"lua-language-server"},
filetypes = {"lua"},
root_markers = {".git", ".luarc.json", "init.lua"},
settings = {
Lua = {
diagnostics = {globals = {"vim"}},
},
},
}
vim.lsp.config.pyright = {
cmd = {"pyright-langserver", "--stdio"},
filetypes = {"python"},
root_markers = {".git", "pyproject.toml", "setup.py"},
}
vim.lsp.config.rust_analyzer = {
cmd = {"rust-analyzer"},
filetypes = {"rust"},
root_markers = {".git", "Cargo.toml"},
}
-- Enable configured servers
vim.lsp.enable({"lua_ls", "pyright", "rust_analyzer"})
-- This is useful for Termux where Mason doesn't work
-- Install LSPs via pkg/npm, then use vim.lsp.config
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "DRILL 5.5: DIAGNOSTICS"
echo "Configure error/warning display"
echo "------------------------------------------------------------------"
echo ""
cat << 'NVIMEOF'
-- Diagnostic configuration
vim.diagnostic.config({
virtual_text = true, -- Show inline text
signs = true, -- Show signs in gutter
underline = true, -- Underline errors
update_in_insert = false, -- Don't update while typing
severity_sort = true, -- Sort by severity
float = {
border = "rounded",
source = "always",
},
})
-- Custom signs
local signs = {Error = " ", Warn = " ", Hint = " ", Info = " "}
for type, icon in pairs(signs) do
local hl = "DiagnosticSign" .. type
vim.fn.sign_define(hl, {text = icon, texthl = hl, numhl = hl})
end
-- Useful diagnostic commands in normal mode:
-- vim.diagnostic.open_float() -- Show diagnostic in float
-- vim.diagnostic.goto_next() -- Go to next diagnostic
-- vim.diagnostic.goto_prev() -- Go to previous
-- vim.diagnostic.setloclist() -- All diagnostics in location list
-- vim.diagnostic.hide() -- Hide diagnostics
-- vim.diagnostic.show() -- Show diagnostics
NVIMEOF
echo ""
# ---------------------------------------------------------------------------
echo "------------------------------------------------------------------"
echo "YOUR TURN - TRY THESE:"
echo "------------------------------------------------------------------"
echo ""
echo "1. Check active LSP clients:"
echo " :lua print(vim.inspect(vim.lsp.get_active_clients()))"
echo ""
echo "2. Check LSP capabilities:"
echo " :lua print(vim.inspect(vim.lsp.get_active_clients()[1].server_capabilities))"
echo ""
echo "3. Manual LSP commands:"
echo " :lua vim.lsp.buf.hover()"
echo " :lua vim.lsp.buf.definition()"
echo ""
echo "4. Diagnostic commands:"
echo " :lua vim.diagnostic.open_float()"
echo " :lua print(vim.inspect(vim.diagnostic.get()))"
echo ""
echo "------------------------------------------------------------------"
echo "KEY TAKEAWAYS:"
echo "1. on_attach runs when LSP connects to buffer"
echo "2. capabilities tell server what client supports"
echo "3. Mason installs servers, mason-lspconfig bridges"
echo "4. Neovim 0.11+: vim.lsp.config + vim.lsp.enable()"
echo "5. vim.diagnostic.config() for display options"
echo "------------------------------------------------------------------"