Skip to content

Instantly share code, notes, and snippets.

@eduardoarandah
Created July 1, 2026 20:43
Show Gist options
  • Select an option

  • Save eduardoarandah/b2a426e56e3b436c5d16549f6f4465e6 to your computer and use it in GitHub Desktop.

Select an option

Save eduardoarandah/b2a426e56e3b436c5d16549f6f4465e6 to your computer and use it in GitHub Desktop.
Useful neovim commands to control native LSP (Neovim 0.12+) :LspInfo, :LspRestart, :LspStop
-- User commands to control native LSP (Neovim 0.12+)
-- Replace :LspInfo, :LspRestart, :LspStop, etc. that used to be provided by nvim-lspconfig
--
-- :LspList → clients attached to the current buffer
-- :LspInfo → :checkhealth vim.lsp (the official replacement for LspInfo)
-- :LspLog → opens the LSP log in a new tab
-- :LspStop [name] → stops clients (! to force)
-- :LspStart → re-triggers autostart on the current buffer
-- :LspRestart [name] → restarts clients and re-attaches the buffers
-- :LspCapabilities → inspect the server's capabilities
-- ── Helpers ──────────────────────────────────────────────────────────
-- Target clients: by name(s) passed as args, or the ones from the current buffer
local function get_target_clients(fargs)
if fargs and #fargs > 0 then
local clients = {}
for _, name in ipairs(fargs) do
vim.list_extend(clients, vim.lsp.get_clients({ name = name }))
end
return clients
end
return vim.lsp.get_clients({ bufnr = 0 })
end
-- Autocomplete with names of active clients
local function complete_client_names(arglead)
local seen, names = {}, {}
for _, client in ipairs(vim.lsp.get_clients()) do
if not seen[client.name] and vim.startswith(client.name, arglead) then
seen[client.name] = true
table.insert(names, client.name)
end
end
return names
end
-- ── :LspList ─────────────────────────────────────────────────────────
vim.api.nvim_create_user_command("LspList", function()
local clients = vim.lsp.get_clients({ bufnr = 0 })
if vim.tbl_isempty(clients) then
vim.notify("No LSP clients attached to this buffer", vim.log.levels.WARN)
return
end
local lines = {}
for _, c in ipairs(clients) do
table.insert(lines, string.format("[%d] %s", c.id, c.name))
table.insert(lines, string.format(" root: %s", c.root_dir or "(no root_dir)"))
table.insert(lines, string.format(" cmd: %s", type(c.config.cmd) == "table" and table.concat(c.config.cmd, " ") or "(function)"))
end
vim.notify(table.concat(lines, "\n"), vim.log.levels.INFO)
end, { desc = "List LSP clients attached to the current buffer" })
-- ── :LspInfo ─────────────────────────────────────────────────────────
-- In 0.12 the official replacement is :checkhealth vim.lsp
vim.api.nvim_create_user_command("LspInfo", function()
vim.cmd("checkhealth vim.lsp")
end, { desc = "LSP info (checkhealth vim.lsp)" })
-- ── :LspLog ──────────────────────────────────────────────────────────
vim.api.nvim_create_user_command("LspLog", function()
vim.cmd("tabnew " .. vim.fn.fnameescape(vim.lsp.get_log_path()))
end, { desc = "Open the LSP log" })
-- ── :LspStop ─────────────────────────────────────────────────────────
-- :LspStop → stops the clients of the current buffer
-- :LspStop intelephense → stops a client by name
-- :LspStop! → forces shutdown (SIGKILL)
vim.api.nvim_create_user_command("LspStop", function(opts)
local clients = get_target_clients(opts.fargs)
if vim.tbl_isempty(clients) then
vim.notify("No clients found to stop", vim.log.levels.WARN)
return
end
for _, client in ipairs(clients) do
client:stop(opts.bang)
vim.notify("Stopped: " .. client.name)
end
end, {
nargs = "*",
bang = true,
complete = complete_client_names,
desc = "Stop LSP clients",
})
-- ── :LspStart ────────────────────────────────────────────────────────
-- Re-triggers the FileType event of the current buffer, which re-executes
-- autostart (works with both lspconfig and vim.lsp.enable)
vim.api.nvim_create_user_command("LspStart", function()
vim.api.nvim_exec_autocmds("FileType", { buffer = 0 })
vim.notify("LSP autostart re-triggered for this buffer")
end, { desc = "Start LSP on the current buffer" })
-- ── :LspRestart ──────────────────────────────────────────────────────
-- Saves config and buffers for each client, stops it, and after a delay
-- re-starts it re-attaching the same buffers.
-- Works regardless of how the client was started (lspconfig, vim.lsp.enable, etc.)
vim.api.nvim_create_user_command("LspRestart", function(opts)
local clients = get_target_clients(opts.fargs)
if vim.tbl_isempty(clients) then
vim.notify("No clients found to restart", vim.log.levels.WARN)
return
end
local saved = {}
for _, client in ipairs(clients) do
table.insert(saved, {
name = client.name,
config = client.config,
bufs = vim.lsp.get_buffers_by_client_id(client.id),
})
client:stop(opts.bang)
end
vim.defer_fn(function()
for _, item in ipairs(saved) do
for _, buf in ipairs(item.bufs) do
if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_is_loaded(buf) then
-- vim.lsp.start reuses the client if one already exists with the same config
vim.lsp.start(item.config, { bufnr = buf })
end
end
vim.notify("Restarted: " .. item.name)
end
end, 500)
end, {
nargs = "*",
bang = true,
complete = complete_client_names,
desc = "Restart LSP clients",
})
-- ── :LspCapabilities ─────────────────────────────────────────────────
-- Useful to know if the server supports formatting, inlayHints, etc.
vim.api.nvim_create_user_command("LspCapabilities", function(opts)
local clients = get_target_clients(opts.fargs)
if vim.tbl_isempty(clients) then
vim.notify("No LSP clients in this buffer", vim.log.levels.WARN)
return
end
for _, client in ipairs(clients) do
-- Opens in a scratch buffer so you can search with /
local buf = vim.api.nvim_create_buf(false, true)
local lines = vim.split(vim.inspect(client.server_capabilities), "\n")
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.api.nvim_buf_set_name(buf, "capabilities://" .. client.name)
vim.bo[buf].filetype = "lua"
vim.cmd.tabnew()
vim.api.nvim_win_set_buf(0, buf)
end
end, {
nargs = "*",
complete = complete_client_names,
desc = "View LSP server capabilities",
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment