Added optimizationsto statusline
This commit is contained in:
@@ -38,7 +38,6 @@ local function setup_statusline_highlights()
|
|||||||
derive_hl('StatusDiagWarn', { base = 'StatusLine', fg = 'DiagnosticWarn' })
|
derive_hl('StatusDiagWarn', { base = 'StatusLine', fg = 'DiagnosticWarn' })
|
||||||
derive_hl('StatusDiagHint', { base = 'StatusLine', fg = 'DiagnosticHint' })
|
derive_hl('StatusDiagHint', { base = 'StatusLine', fg = 'DiagnosticHint' })
|
||||||
derive_hl('StatusCursor', { base = 'StatusLine', fg = 'Normal' })
|
derive_hl('StatusCursor', { base = 'StatusLine', fg = 'Normal' })
|
||||||
-- derive_mode_hl('StatusPercent', 'Constant')
|
|
||||||
end
|
end
|
||||||
vim.api.nvim_create_autocmd('ColorScheme', {
|
vim.api.nvim_create_autocmd('ColorScheme', {
|
||||||
callback = setup_statusline_highlights,
|
callback = setup_statusline_highlights,
|
||||||
@@ -68,6 +67,9 @@ local mode_hl_map = {
|
|||||||
|
|
||||||
--- Git branch (async, cached per buffer, refreshed every 5s)
|
--- Git branch (async, cached per buffer, refreshed every 5s)
|
||||||
local function update_git_branch()
|
local function update_git_branch()
|
||||||
|
if vim.bo.buftype ~= '' then
|
||||||
|
return
|
||||||
|
end
|
||||||
vim.system(
|
vim.system(
|
||||||
{ 'git', 'branch', '--show-current' },
|
{ 'git', 'branch', '--show-current' },
|
||||||
{ text = true },
|
{ text = true },
|
||||||
@@ -90,6 +92,39 @@ vim.api.nvim_create_autocmd({ 'BufEnter', 'FocusGained' }, {
|
|||||||
local progress = {}
|
local progress = {}
|
||||||
local spinner_frames =
|
local spinner_frames =
|
||||||
{ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' }
|
{ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' }
|
||||||
|
|
||||||
|
local frame = 0
|
||||||
|
--- Clean stale progress messages periodically
|
||||||
|
local progress_timer = vim.uv.new_timer()
|
||||||
|
local function start_progress_timer()
|
||||||
|
if not progress_timer:is_active() then
|
||||||
|
progress_timer:start(0, 200, function()
|
||||||
|
local now = vim.loop.now()
|
||||||
|
for k, v in pairs(progress) do
|
||||||
|
local ttl = v.done and 2000 or 10000
|
||||||
|
if now - v.t > ttl then
|
||||||
|
progress[k] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if next(progress) then
|
||||||
|
frame = (frame % #spinner_frames) + 1
|
||||||
|
-- vim.cmd('redrawstatus')
|
||||||
|
vim.schedule(function()
|
||||||
|
vim.cmd('redrawstatus')
|
||||||
|
end)
|
||||||
|
-- else
|
||||||
|
else
|
||||||
|
progress_timer:stop()
|
||||||
|
vim.schedule(function()
|
||||||
|
vim.cmd('redrawstatus')
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
-- progress_timer:stop()
|
||||||
|
-- end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
vim.api.nvim_create_autocmd('LspProgress', {
|
vim.api.nvim_create_autocmd('LspProgress', {
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
local d = ev.data
|
local d = ev.data
|
||||||
@@ -107,6 +142,7 @@ vim.api.nvim_create_autocmd('LspProgress', {
|
|||||||
msg = (value.message or 'working...'):gsub('%%', '%%%%'),
|
msg = (value.message or 'working...'):gsub('%%', '%%%%'),
|
||||||
t = vim.loop.now(),
|
t = vim.loop.now(),
|
||||||
}
|
}
|
||||||
|
start_progress_timer()
|
||||||
elseif value.kind == 'report' then
|
elseif value.kind == 'report' then
|
||||||
local msg_parts = {}
|
local msg_parts = {}
|
||||||
if value.message then
|
if value.message then
|
||||||
@@ -127,123 +163,147 @@ vim.api.nvim_create_autocmd('LspProgress', {
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
local frame = 0
|
-- local frame = 0
|
||||||
--- Clean stale progress messages periodically
|
-- --- Clean stale progress messages periodically
|
||||||
vim.uv.new_timer():start(
|
-- vim.uv.new_timer():start(
|
||||||
0,
|
-- 0,
|
||||||
200,
|
-- 200,
|
||||||
vim.schedule_wrap(function()
|
-- vim.schedule_wrap(function()
|
||||||
local now = vim.loop.now()
|
-- if next(progress) == nil then
|
||||||
for k, v in pairs(progress) do
|
-- return progress_timer:stop()
|
||||||
local ttl = v.done and 2000 or 10000
|
-- -- end
|
||||||
if now - v.t > ttl then
|
-- -- else -- no progress
|
||||||
progress[k] = nil
|
-- -- progress_timer:stop()
|
||||||
end
|
-- end
|
||||||
end
|
-- local now = vim.loop.now()
|
||||||
if next(progress) then
|
-- for k, v in pairs(progress) do
|
||||||
frame = (frame % #spinner_frames) + 1
|
-- local ttl = v.done and 2000 or 10000
|
||||||
end
|
-- if now - v.t > ttl then
|
||||||
vim.cmd('redrawstatus')
|
-- progress[k] = nil
|
||||||
end)
|
-- end
|
||||||
)
|
-- end
|
||||||
|
-- if next(progress) then
|
||||||
|
-- frame = (frame % #spinner_frames) + 1
|
||||||
|
-- end
|
||||||
|
-- vim.cmd('redrawstatus')
|
||||||
|
-- end)
|
||||||
|
-- )
|
||||||
--- Build the LSP section of the statusline
|
--- Build the LSP section of the statusline
|
||||||
|
vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, {
|
||||||
|
callback = function(args)
|
||||||
|
-- vim.schedule(function()
|
||||||
|
local names = {}
|
||||||
|
for _, c in ipairs(vim.lsp.get_clients({ bufnr = args.buf })) do
|
||||||
|
table.insert(names, c.name)
|
||||||
|
end
|
||||||
|
vim.b[args.buf].lsp_names = #names > 0
|
||||||
|
and (' ● ' .. table.concat(names, ', ') .. ' ')
|
||||||
|
or ''
|
||||||
|
-- end)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- local function lsp_section()
|
||||||
|
-- -- Only check for progress (dynamic)
|
||||||
|
-- local latest = nil
|
||||||
|
-- for _, p in pairs(progress) do
|
||||||
|
-- -- Simplified check: show latest active or recently done
|
||||||
|
-- if not latest or p.t > latest.t then
|
||||||
|
-- latest = p
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- if latest and (not latest.done or (vim.loop.now() - latest.t < 2000)) then
|
||||||
|
-- return '%#StatusLspSpinner# ○ ' .. latest.msg .. ' %*'
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- -- Use the cached names from the autocmd
|
||||||
|
-- return '%#StatusLsp#' .. (vim.b.lsp_names or '') .. '%*'
|
||||||
|
-- end
|
||||||
local function lsp_section()
|
local function lsp_section()
|
||||||
local bufnr = vim.api.nvim_get_current_buf()
|
-- Only check progress for this buffer's clients
|
||||||
local clients = vim.lsp.get_clients({ bufnr = bufnr })
|
|
||||||
if #clients == 0 then
|
|
||||||
return ''
|
|
||||||
end
|
|
||||||
-- Show progress spinner if any active for visible clients
|
|
||||||
local client_ids = {}
|
local client_ids = {}
|
||||||
for _, c in ipairs(clients) do
|
for _, c in
|
||||||
|
ipairs(vim.lsp.get_clients({ bufnr = vim.api.nvim_get_current_buf() }))
|
||||||
|
do
|
||||||
client_ids[c.id] = true
|
client_ids[c.id] = true
|
||||||
end
|
end
|
||||||
|
-- Filter progress by current buffer's clients
|
||||||
local latest = nil
|
local latest = nil
|
||||||
for key, p in pairs(progress) do
|
for key, p in pairs(progress) do
|
||||||
local cid = tonumber(key:match('^(%d+):'))
|
local cid = tonumber(key:match('^(%d+):'))
|
||||||
if cid and client_ids[cid] and not p.done then
|
if cid and client_ids[cid] then
|
||||||
if not latest or p.t > latest.t then
|
if not latest or p.t > latest.t then
|
||||||
latest = p
|
latest = p
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if latest then
|
if latest and (not latest.done or (vim.loop.now() - latest.t < 2000)) then
|
||||||
return '%#StatusLspSpinner# ○ ' .. latest.msg .. ' %*'
|
return '%#StatusLspSpinner# ○ ' .. latest.msg .. ' %*'
|
||||||
end
|
end
|
||||||
-- Fallback: most recent done entry (lasts 2s for smooth transition)
|
-- Use the cached names from the autocmd
|
||||||
for key, p in pairs(progress) do
|
return '%#StatusLsp#' .. (vim.b.lsp_names or '') .. '%*'
|
||||||
local cid = tonumber(key:match('^(%d+):'))
|
end
|
||||||
if cid and client_ids[cid] and p.done then
|
--- Diagnostics summary.
|
||||||
if not latest or p.t > latest.t then
|
local diag_cache = {}
|
||||||
latest = p
|
local function update_diag_cache(ev)
|
||||||
end
|
local bufnr = ev.buf
|
||||||
end
|
local counts = vim.diagnostic.count(bufnr)
|
||||||
|
local parts = {}
|
||||||
|
if counts[1] and counts[1] > 0 then
|
||||||
|
table.insert(parts, '%#StatusDiagError# E' .. counts[1] .. ' %*')
|
||||||
end
|
end
|
||||||
if latest then
|
if counts[2] and counts[2] > 0 then
|
||||||
return '%#StatusLspSpinner# ○ ' .. latest.msg .. ' %*'
|
table.insert(parts, '%#StatusDiagWarn# W' .. counts[2] .. ' %*')
|
||||||
end
|
end
|
||||||
-- Idle: show client names
|
if counts[4] and counts[4] > 0 then
|
||||||
local names = {}
|
table.insert(parts, '%#StatusDiagHint# H' .. counts[4] .. ' %*')
|
||||||
for _, c in ipairs(clients) do
|
|
||||||
table.insert(names, c.name)
|
|
||||||
end
|
end
|
||||||
return '%#StatusLsp# ● ' .. table.concat(names, ', ') .. ' %*'
|
diag_cache[bufnr] = table.concat(parts)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Diagnostics summary.
|
vim.api.nvim_create_autocmd(
|
||||||
local function diag_section()
|
'DiagnosticChanged',
|
||||||
local diag = vim.diagnostic.get(vim.api.nvim_get_current_buf())
|
{ callback = update_diag_cache }
|
||||||
local parts = {}
|
)
|
||||||
local counts = { errors = 0, warnings = 0, hints = 0 }
|
|
||||||
for _, d in ipairs(diag) do
|
|
||||||
if d.severity == vim.diagnostic.severity.ERROR then
|
|
||||||
counts.errors = counts.errors + 1
|
|
||||||
elseif d.severity == vim.diagnostic.severity.WARN then
|
|
||||||
counts.warnings = counts.warnings + 1
|
|
||||||
elseif d.severity == vim.diagnostic.severity.HINT then
|
|
||||||
counts.hints = counts.hints + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if counts.errors > 0 then
|
|
||||||
table.insert(parts, '%#StatusDiagError# E' .. counts.errors .. ' %*')
|
|
||||||
end
|
|
||||||
if counts.warnings > 0 then
|
|
||||||
table.insert(parts, '%#StatusDiagWarn# W' .. counts.warnings .. ' %*')
|
|
||||||
end
|
|
||||||
if counts.hints > 0 then
|
|
||||||
table.insert(parts, '%#StatusDiagHint# H' .. counts.hints .. ' %*')
|
|
||||||
end
|
|
||||||
return table.concat(parts)
|
|
||||||
end
|
|
||||||
--- Main statusline renderer.
|
--- Main statusline renderer.
|
||||||
function _G.__statusline()
|
function _G.__statusline()
|
||||||
local m = vim.fn.mode()
|
local m = vim.fn.mode()
|
||||||
local mode_hl = mode_hl_map[m] or 'StatusModeNormal'
|
local mode_hl = mode_hl_map[m] or 'StatusModeNormal'
|
||||||
local mode_txt = mode_map[m] or ' ?? '
|
|
||||||
local parts = {}
|
|
||||||
-- Mode
|
|
||||||
parts[#parts + 1] = '%#' .. mode_hl .. '#' .. mode_txt .. '%*'
|
|
||||||
-- Git
|
|
||||||
local git = vim.b.git_branch or ''
|
local git = vim.b.git_branch or ''
|
||||||
if git ~= '' then
|
local cur_buf = vim.api.nvim_get_current_buf()
|
||||||
parts[#parts + 1] = '%#StatusGit# ' .. git .. ' %*'
|
|
||||||
end
|
local parts = {
|
||||||
-- LSP
|
'%#' .. mode_hl .. '#' .. (mode_map[m] or ' ?? ') .. '%*',
|
||||||
parts[#parts + 1] = lsp_section()
|
git ~= '' and ('%#StatusGit# ' .. git .. ' %*') or '',
|
||||||
-- Right align
|
lsp_section(),
|
||||||
parts[#parts + 1] = '%='
|
'%=',
|
||||||
-- Diagnostics
|
-- diag_cache[cur_buf] or '', -- Per-buffer cache lookup
|
||||||
parts[#parts + 1] = diag_section()
|
diag_cache[cur_buf] or (function()
|
||||||
-- Cursor position
|
local parts = {}
|
||||||
parts[#parts + 1] = '%#StatusCursor# %l:%-2c %*'
|
local counts = vim.diagnostic.count(cur_buf)
|
||||||
-- Percentage
|
if counts[1] and counts[1] > 0 then
|
||||||
parts[#parts + 1] = '%#' .. mode_hl .. '# %p%% %*'
|
table.insert(
|
||||||
|
parts,
|
||||||
|
'%#StatusDiagError# E' .. counts[1] .. ' %*'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
if counts[2] and counts[2] > 0 then
|
||||||
|
table.insert(parts, '%#StatusDiagWarn# W' .. counts[2] .. ' %*')
|
||||||
|
end
|
||||||
|
if counts[4] and counts[4] > 0 then
|
||||||
|
table.insert(parts, '%#StatusDiagHint# H' .. counts[4] .. ' %*')
|
||||||
|
end
|
||||||
|
return table.concat(parts)
|
||||||
|
end)(),
|
||||||
|
'%#StatusCursor# %l:%-2c %*',
|
||||||
|
'%#' .. mode_hl .. '# %p%% %*',
|
||||||
|
}
|
||||||
return table.concat(parts)
|
return table.concat(parts)
|
||||||
end
|
end
|
||||||
vim.o.statusline = '%!v:lua.__statusline()'
|
vim.o.statusline = '%!v:lua.__statusline()'
|
||||||
|
|
||||||
local helpers = require('incline.helpers')
|
|
||||||
local devicons = require('nvim-web-devicons')
|
|
||||||
require('incline').setup({
|
require('incline').setup({
|
||||||
window = {
|
window = {
|
||||||
padding = 0,
|
padding = 0,
|
||||||
@@ -255,7 +315,8 @@ require('incline').setup({
|
|||||||
if filename == '' then
|
if filename == '' then
|
||||||
filename = '[No Name]'
|
filename = '[No Name]'
|
||||||
end
|
end
|
||||||
local ft_icon, ft_color = devicons.get_icon_color(filename)
|
local ft_icon, ft_color =
|
||||||
|
require('nvim-web-devicons').get_icon_color(filename)
|
||||||
local modified = vim.bo[props.buf].modified
|
local modified = vim.bo[props.buf].modified
|
||||||
return {
|
return {
|
||||||
ft_icon and {
|
ft_icon and {
|
||||||
@@ -263,7 +324,7 @@ require('incline').setup({
|
|||||||
ft_icon,
|
ft_icon,
|
||||||
' ',
|
' ',
|
||||||
guibg = ft_color,
|
guibg = ft_color,
|
||||||
guifg = helpers.contrast_color(ft_color),
|
guifg = require('incline.helpers').contrast_color(ft_color),
|
||||||
} or '',
|
} or '',
|
||||||
' ',
|
' ',
|
||||||
{ filename, gui = modified and 'bold,italic' or 'bold' },
|
{ filename, gui = modified and 'bold,italic' or 'bold' },
|
||||||
|
|||||||
Reference in New Issue
Block a user