A performant lsp progress status for Neovim.
Click here to see how to configure
require("lsp-progress").setup()
Click here to see how to configure
require("lsp-progress").setup({
client_format = function(client_name, spinner, series_messages)
if #series_messages == 0 then
return nil
end
return {
name = client_name,
body = spinner .. " " .. table.concat(series_messages, ", "),
}
end,
format = function(client_messages)
--- @param name string
--- @param msg string?
--- @return string
local function stringify(name, msg)
return msg and string.format("%s %s", name, msg) or name
end
local sign = "" -- nf-fa-gear \uf013
local lsp_clients = vim.lsp.get_active_clients()
local messages_map = {}
for _, climsg in ipairs(client_messages) do
messages_map[climsg.name] = climsg.body
end
if #lsp_clients > 0 then
table.sort(lsp_clients, function(a, b)
return a.name < b.name
end)
local builder = {}
for _, cli in ipairs(lsp_clients) do
if
type(cli) == "table"
and type(cli.name) == "string"
and string.len(cli.name) > 0
then
if messages_map[cli.name] then
table.insert(builder, stringify(cli.name, messages_map[cli.name]))
else
table.insert(builder, stringify(cli.name))
end
end
end
if #builder > 0 then
return sign .. " " .. table.concat(builder, ", ")
end
end
return ""
end,
})
Click here to see how to configure
require("lsp-progress").setup({
decay = 1200,
series_format = function(title, message, percentage, done)
local builder = {}
local has_title = false
local has_message = false
if type(title) == "string" and string.len(title) > 0 then
table.insert(builder, title)
has_title = true
end
if type(message) == "string" and string.len(message) > 0 then
table.insert(builder, message)
has_message = true
end
if percentage and (has_title or has_message) then
table.insert(builder, string.format("(%.0f%%)", percentage))
end
return { msg = table.concat(builder, " "), done = done }
end,
client_format = function(client_name, spinner, series_messages)
if #series_messages == 0 then
return nil
end
local builder = {}
local done = true
for _, series in ipairs(series_messages) do
if not series.done then
done = false
end
table.insert(builder, series.msg)
end
if done then
spinner = "✓" -- replace your check mark
end
return "["
.. client_name
.. "] "
.. spinner
.. " "
.. table.concat(builder, ", ")
end,
})
I use a 2-layer map to cache all lsp progress messages, thus split the O(N * M) time complexity calculation into almost O(1) on every LSP progress update.
N is active lsp clients count, M is token count of each lsp client.
For more details, please see Design & Technologies.
- Neovim ≥ 0.6.
- Nerd fonts for icons.
With packer.nvim
-- lua
return require('packer').startup(function(use)
use {
'linrongbin16/lsp-progress.nvim',
config = function()
require('lsp-progress').setup()
end
}
end)
With lazy.nvim
-- lua
require("lazy").setup({
{
'linrongbin16/lsp-progress.nvim',
config = function()
require('lsp-progress').setup()
end
}
})
With vim-plug
" vim
call plug#begin()
Plug 'linrongbin16/lsp-progress.nvim'
call plug#end()
lua require('lsp-progress').setup()
-
LspProgressStatusUpdated
: user event to notify new status, and trigger statusline refresh. -
require('lsp-progress').progress(opts)
: get lsp progress status, parameteropts
is an optional lua table:require('lsp-progress').progress({ format = ..., max_size = ..., })
The fields are the same value passing to
setup
(see Configuration) for more dynamic abilities.
Important
Don't directly put require('lsp-progress').progress
as lualine component or heirline's component provider, wrap it with a function to avoid the lazy dependency issue, see #131.
require("lualine").setup({
sections = {
-- Other Status Line components
lualine_a = { ... },
lualine_b = { ... },
lualine_c = {
function()
-- invoke `progress` here.
return require('lsp-progress').progress()
end,
},
...
}
})
-- listen lsp-progress event and refresh lualine
vim.api.nvim_create_augroup("lualine_augroup", { clear = true })
vim.api.nvim_create_autocmd("User", {
group = "lualine_augroup",
pattern = "LspProgressStatusUpdated",
callback = require("lualine").refresh,
})
local LspProgress = {
provider = function()
return require('lsp-progress').progress()
end,
update = {
'User',
pattern = 'LspProgressStatusUpdated',
callback = vim.schedule_wrap(function()
vim.cmd('redrawstatus')
end),
}
}
local StatusLine = {
-- Other StatusLine components
{ ... },
-- Lsp progress status component here
LspProgress,
}
require('heirline').setup({
statusline = StatusLine
})
To configure options, please use:
require('lsp-progress').setup(opts)
The opts
is an optional lua table that overwrite the default options.
For complete options and defaults, please check defaults.lua.
For more advanced configurations, please see Advanced Configuration.
- lsp-status.nvim: Utility functions for getting diagnostic status and progress messages from LSP servers, for use in the Neovim statusline.
- fidget.nvim: Standalone UI for nvim-lsp progress.
Please open issue/PR for anything about lsp-progress.nvim.
Like lsp-progress.nvim? Consider