vimtricks.wiki Concise Vim tricks, one at a time.

How do I display the current LSP server progress messages in the Neovim statusline?

Answer

vim.lsp.status()

Explanation

vim.lsp.status() returns the most recent LSP progress message as a plain string — things like "Loading workspace..." or "Indexing: 42%" sent by servers via the $/progress JSON-RPC notification. Including it in a custom statusline gives you real-time feedback on what the language server is doing, without needing fidget.nvim or any other plugin.

How it works

  • Returns an empty string '' when no progress is active, so it disappears cleanly from the statusline when the server is idle
  • Neovim updates the internal progress state asynchronously as progress messages arrive
  • The function itself is synchronous — it just reads the cached last message, so it is safe to call inside a statusline expression

Example

-- Use via the Vimscript bridge in a string statusline:
vim.o.statusline = '%f %=%{v:lua.vim.lsp.status()} %l:%c'

-- Or inside a Lua statusline builder:
local function lsp_progress()
  local msg = vim.lsp.status()
  return msg ~= '' and (' ' .. msg) or ''
end

-- Trigger a redraw when progress changes so the statusline stays current:
vim.api.nvim_create_autocmd('User', {
  pattern = 'LspProgressUpdate',
  callback = function() vim.cmd.redrawstatus() end,
})

Tips

  • Without the LspProgressUpdate autocmd the statusline only refreshes on cursor movement — adding the autocmd makes progress messages appear and disappear promptly
  • vim.lsp.status() aggregates progress from all attached clients; if you need per-client messages, iterate over vim.lsp.get_clients({ bufnr = 0 }) and read their progress tables
  • fidget.nvim provides a richer floating notification UI if you want animated spinners and history, but vim.lsp.status() covers the common case with zero dependencies

Next

What is the difference between the inner word (iw) and inner WORD (iW) text objects in Vim?