LSP
Blak is built on Neovim 0.12’s native LSP API. Servers are configured through vim.lsp.config and Mason-backed servers are enabled through mason-lspconfig’s vim.lsp.enable() integration. There is no lspconfig.setup() wrapper call anywhere in the codebase.
The native plumbing lives in lua/blak/plugins/lsp.lua. LSP keymaps are bound on LspAttach in lua/blak/core/keymaps.lua.
The flow
Section titled “The flow”- Blak collects servers from
lsp.serversin the merged config (defaults +user.lua+ extras). - For each server, it assigns
vim.lsp.config[name] = settings. This replaces Blak’s previous overrides on reload while retaining the server’s upstream runtime defaults. - When
mason.automatic_installis true,mason-lspconfigrequests the configured Mason-backed server binaries. - If
lsp.automatic_enableis true (default),mason-lspconfigcallsvim.lsp.enable(name)for configured, installed Mason-backed servers. - When a buffer matches, Neovim auto-attaches the server and fires
LspAttach. - Blak’s
LspAttachautocmd binds the buffer-local LSP keymaps.
Default servers
Section titled “Default servers”Only one server ships by default — lua_ls, since Blak itself is Lua.
lsp = { servers = { lua_ls = { settings = { Lua = { runtime = { version = "LuaJIT" }, diagnostics = { globals = { "vim" } }, workspace = { checkThirdParty = false, }, telemetry = { enable = false }, }, }, }, },}Blak injects lua_ls.settings.Lua.workspace.library lazily when LSP setup runs, so config startup does not scan the full runtime path. Set workspace.library yourself if you want to replace that generated library.
Other servers ship via language extras: ts_ls, tsgo, eslint, pyright, basedpyright, ruff, rust_analyzer, taplo, gopls, marksman.
For TypeScript, use either lang.typescript for the stable ts_ls path or lang.typescript-tsgo for the experimental native tsgo language server.
For Python, use lang.python for the basic Pyright path or lang.python-pro for BasedPyright plus Ruff’s native language server.
Adding a server
Section titled “Adding a server”In your user.lua:
return { lsp = { servers = { zls = { settings = { zls = { enable_inlay_hints = true } }, }, }, }, mason = { ensure_installed = { "zls" }, -- if Mason knows it },}Or as an extra — see Writing an extra.
If a server is installed outside Mason and you still want it enabled automatically, register it in user.lua and call vim.lsp.enable("server_name") from a User BlakReady autocmd.
Reload rebuilds server configuration for future clients. Restart Neovim when changing settings for a language server that is already running.
Diagnostics
Section titled “Diagnostics”The default diagnostic UI:
diagnostics = { virtual_text = { spacing = 2, source = "if_many" }, virtual_lines = false, signs = true, underline = true, update_in_insert = false, severity_sort = true, float = { border = "rounded", source = "if_many" },}Override anything you want in user.lua:
return { lsp = { diagnostics = { virtual_text = false, virtual_lines = true, -- multi-line block under each diagnostic }, },}LSP keymaps
Section titled “LSP keymaps”Bound on LspAttach so they’re only available when a server is attached:
| Mapping | Action |
|---|---|
gd |
Definition |
gD |
Declaration |
gI |
Implementation |
gr |
References |
K |
Hover |
<leader>ca |
Code action |
<leader>cr |
Rename |
<leader>cf |
Format |
<leader>cs |
Document symbols (picker) |
<leader>cS |
Workspace symbols (picker) |
Disabling automatic enable
Section titled “Disabling automatic enable”return { lsp = { automatic_enable = false },}Then call vim.lsp.enable("server_name") yourself when you want to start it.
Inspecting what’s running
Section titled “Inspecting what’s running”:lua = vim.lsp.get_clients() " all active clients:lua = vim.lsp.config.lua_ls " the config you registered:checkhealth vim.lsp " native health checksOn Neovim nightly
Section titled “On Neovim nightly”Blak supports stable and nightly. Nightly changes to vim.lsp.config() or vim.lsp.enable() can cause loud errors after a Neovim upgrade. The mitigation:
- Upgrade Neovim.
- Update the Blak Git checkout for distribution fixes and use
:BlakUpdatefor plugin updates. See Updates. - If a plugin update breaks, use
:BlakRollbackand report. This does not roll back Neovim itself or the Blak checkout.