CHORE: Fixing some minor bugs

This commit is contained in:
2026-10-03 01:53:11 -04:00
parent f74d475dfb
commit 75e4e77dba
+131 -38
View File
@@ -74,10 +74,10 @@ local mode_hl_map = {
i = 'StatusModeInsert', i = 'StatusModeInsert',
v = 'StatusModeVisual', v = 'StatusModeVisual',
V = 'StatusModeVisual', V = 'StatusModeVisual',
['^V'] = 'StatusModeVisual', ['\22'] = 'StatusModeVisual',
s = 'StatusModeVisual', s = 'StatusModeVisual',
S = 'StatusModeVisual', S = 'StatusModeVisual',
['^S'] = 'StatusModeVisual', ['\19'] = 'StatusModeVisual',
R = 'StatusModeReplace', R = 'StatusModeReplace',
c = 'StatusModeCommand', c = 'StatusModeCommand',
r = 'StatusModeCommand', r = 'StatusModeCommand',
@@ -85,6 +85,13 @@ local mode_hl_map = {
t = 'StatusModeTerminal', t = 'StatusModeTerminal',
} }
local mode_statusline = {}
for k, v in pairs(mode_map) do
local hl = mode_hl_map[k] or 'StatusModeNormal'
mode_statusline[k] = '%#' .. hl .. '#' .. v .. '%*'
end
mode_statusline['default'] = '%#StatusModeNormal# ?? %*'
local function refresh_status(buf) local function refresh_status(buf)
local b = vim.b[buf] local b = vim.b[buf]
local left, right = {}, {} local left, right = {}, {}
@@ -116,8 +123,14 @@ local function refresh_status(buf)
.. ' %*' .. ' %*'
end end
b.status_left = #left > 0 and table.concat(left) or '' local l = #left > 0 and table.concat(left) or ''
b.status_right = #right > 0 and table.concat(right) or '' local r = #right > 0 and table.concat(right) or ''
if b.status_left ~= l then
b.status_left = l
end
if b.status_right ~= r then
b.status_right = r
end
end end
local lsp_icon = { local lsp_icon = {
@@ -144,29 +157,47 @@ local function refresh_lsp(buf)
local names = {} local names = {}
for _, client in ipairs(clients) do for _, client in ipairs(clients) do
names[#names + 1] = client.name names[#names + 1] = client.name
local prog = active_progress[client.id] local p = active_progress[client.id]
if prog == 'working' then if p then
state = 'working' if p.is_starting then
elseif prog == 'starting' and state ~= 'working' then if state ~= 'working' then
state = 'starting' state = 'starting'
end end
elseif next(p.tokens) then
state = 'working'
end
end
vim.b[buf].lsp_name = table.concat(names, '/') vim.b[buf].lsp_name = table.concat(names, '/')
end end
end end
if vim.b[buf].lsp_state == state then
return
end
vim.b[buf].lsp_state = state
vim.b[buf].lsp_icon = lsp_icon[state] vim.b[buf].lsp_icon = lsp_icon[state]
vim.b[buf].lsp_hl = lsp_hl[state] vim.b[buf].lsp_hl = lsp_hl[state]
refresh_status(buf) refresh_status(buf)
vim.cmd.redrawstatus()
end end
vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, { vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, {
callback = function(ev) callback = function(ev)
if ev.event == 'LspAttach' then
local cid = ev.data.client_id local cid = ev.data.client_id
if not active_progress[cid] then if ev.event == 'LspAttach' then
active_progress[cid] = 'starting' local p = active_progress[cid] or { tokens = {} }
active_progress[cid] = p
if not p.is_starting and not next(p.tokens) then
p.is_starting = true
p.timer_id = (p.timer_id or 0) + 1
local current_id = p.timer_id
vim.defer_fn(function() vim.defer_fn(function()
if active_progress[cid] == 'starting' then local curr = active_progress[cid]
active_progress[cid] = nil if
curr
and curr.is_starting
and curr.timer_id == current_id
then
curr.is_starting = nil
if vim.api.nvim_buf_is_valid(ev.buf) then if vim.api.nvim_buf_is_valid(ev.buf) then
refresh_lsp(ev.buf) refresh_lsp(ev.buf)
end end
@@ -174,7 +205,7 @@ vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, {
end, 500) -- 500ms grace period to wait for LspProgress end, 500) -- 500ms grace period to wait for LspProgress
end end
elseif ev.event == 'LspDetach' then elseif ev.event == 'LspDetach' then
active_progress[ev.data.client_id] = nil active_progress[cid] = nil
end end
refresh_lsp(ev.buf) refresh_lsp(ev.buf)
end, end,
@@ -182,13 +213,27 @@ vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, {
vim.api.nvim_create_autocmd('LspProgress', { vim.api.nvim_create_autocmd('LspProgress', {
callback = function(ev) callback = function(ev)
local kind = ev.data.params.value and ev.data.params.value.kind local cid = ev.data.client_id
if kind == 'begin' or kind == 'report' then local p = active_progress[cid] or { tokens = {} }
active_progress[ev.data.client_id] = 'working' active_progress[cid] = p
elseif kind == 'end' then
active_progress[ev.data.client_id] = nil if p.is_starting then
else p.is_starting = nil
return p.timer_id = (p.timer_id or 0) + 1 -- Invalidate pending start timer safely
end
local val = type(ev.data.params.value) == 'table'
and ev.data.params.value
or {}
local kind = val.kind or ev.match
local token = ev.data.params.token or 'fallback'
if kind == 'begin' or (kind == 'report' and val.percentage ~= 100) then
p.tokens[token] = true
elseif
kind == 'end' or (kind == 'report' and val.percentage == 100)
then
p.tokens[token] = nil
end end
local client = vim.lsp.get_client_by_id(ev.data.client_id) local client = vim.lsp.get_client_by_id(ev.data.client_id)
if client then if client then
@@ -200,6 +245,18 @@ vim.api.nvim_create_autocmd('LspProgress', {
}) })
local BRANCH_ICON = '' local BRANCH_ICON = ''
local branch_jobs = {}
local diff_jobs = {}
local git_root_cache = {}
local function get_git_root(buf, file)
local dir = vim.fs.dirname(file)
if git_root_cache[dir] ~= nil then
return git_root_cache[dir]
end
local root = vim.fs.root(buf, '.git') or dir
git_root_cache[dir] = root
return root
end
local function refresh_branch(buf) local function refresh_branch(buf)
local file = vim.api.nvim_buf_get_name(buf) local file = vim.api.nvim_buf_get_name(buf)
@@ -207,12 +264,17 @@ local function refresh_branch(buf)
vim.b[buf].git_branch = '' vim.b[buf].git_branch = ''
return return
end end
local cwd = vim.fs.root(buf, '.git') or vim.fs.dirname(file) local cwd = get_git_root(buf, file)
vim.system( if branch_jobs[buf] then
branch_jobs[buf]:kill(9)
end
branch_jobs[buf] = vim.system(
{ 'git', 'branch', '--show-current' }, { 'git', 'branch', '--show-current' },
{ text = true, cwd = cwd }, { text = true, cwd = cwd },
vim.schedule_wrap(function(out) vim.schedule_wrap(function(out)
branch_jobs[buf] = nil
if not vim.api.nvim_buf_is_valid(buf) then if not vim.api.nvim_buf_is_valid(buf) then
return return
end end
@@ -220,24 +282,39 @@ local function refresh_branch(buf)
vim.b[buf].git_branch = branch ~= '' and (BRANCH_ICON .. branch) vim.b[buf].git_branch = branch ~= '' and (BRANCH_ICON .. branch)
or '' or ''
refresh_status(buf) refresh_status(buf)
vim.cmd.redrawstatus()
end) end)
) )
end end
local function refresh_diff(buf) local function refresh_diff(buf, force)
local file = vim.api.nvim_buf_get_name(buf) local file = vim.api.nvim_buf_get_name(buf)
if file == '' or vim.bo[buf].buftype ~= '' then if file == '' or vim.bo[buf].buftype ~= '' then
vim.b[buf].git_diff = nil vim.b[buf].git_diff = nil
return return
end end
local cwd = vim.fs.root(buf, '.git') or vim.fs.dirname(file) if
vim.system( not force
and vim.b[buf].git_diff_fetched
and not vim.bo[buf].modified
then
return
end
local cwd = get_git_root(buf, file)
if diff_jobs[buf] then
diff_jobs[buf]:kill(9)
end
diff_jobs[buf] = vim.system(
{ 'git', 'diff', '--numstat', 'HEAD', '--', file }, { 'git', 'diff', '--numstat', 'HEAD', '--', file },
{ text = true, cwd = cwd }, { text = true, cwd = cwd },
vim.schedule_wrap(function(out) vim.schedule_wrap(function(out)
diff_jobs[buf] = nil
if not vim.api.nvim_buf_is_valid(buf) then if not vim.api.nvim_buf_is_valid(buf) then
return return
end end
vim.b[buf].git_diff_fetched = true
if out.code ~= 0 or out.stdout == '' then if out.code ~= 0 or out.stdout == '' then
vim.b[buf].git_diff = nil vim.b[buf].git_diff = nil
else else
@@ -252,6 +329,7 @@ local function refresh_diff(buf)
end end
end end
refresh_status(buf) refresh_status(buf)
vim.cmd.redrawstatus()
end) end)
) )
end end
@@ -271,11 +349,13 @@ local function refresh_diag(buf)
end end
vim.b[buf].diag_str = #parts > 0 and table.concat(parts) or '' vim.b[buf].diag_str = #parts > 0 and table.concat(parts) or ''
refresh_status(buf) refresh_status(buf)
vim.cmd.redrawstatus()
end end
vim.api.nvim_create_autocmd('DiagnosticChanged', { vim.api.nvim_create_autocmd('DiagnosticChanged', {
callback = function(ev) callback = function(ev)
refresh_diag(ev.buf) refresh_diag(ev.buf)
vim.cmd.redrawstatus()
end, end,
}) })
@@ -283,7 +363,7 @@ vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, {
callback = function(ev) callback = function(ev)
if vim.bo[ev.buf].buftype == '' then if vim.bo[ev.buf].buftype == '' then
refresh_branch(ev.buf) refresh_branch(ev.buf)
refresh_diff(ev.buf) refresh_diff(ev.buf, false)
end end
refresh_lsp(ev.buf) refresh_lsp(ev.buf)
refresh_diag(ev.buf) refresh_diag(ev.buf)
@@ -299,7 +379,7 @@ vim.api.nvim_create_autocmd('FocusGained', {
}) })
vim.api.nvim_create_autocmd('BufWritePost', { vim.api.nvim_create_autocmd('BufWritePost', {
callback = function(ev) callback = function(ev)
refresh_diff(ev.buf) refresh_diff(ev.buf, true)
end, end,
}) })
@@ -320,18 +400,31 @@ vim.api.nvim_create_autocmd('RecordingLeave', {
}) })
function _G.__statusline() function _G.__statusline()
local m = vim.fn.mode() local win_id = vim.g.statusline_winid or vim.api.nvim_get_current_win()
local is_active = win_id == vim.api.nvim_get_current_win()
local buf = vim.api.nvim_win_get_buf(win_id)
local b = vim.b[buf]
if not is_active then
return '%#StatusLineNC# '
.. (b.status_left or '')
.. '%='
.. (b.status_right or '')
.. ' %#StatusLineNC# %l:%-2c '
end
local m = vim.api.nvim_get_mode().mode
local key = (m == '\22' or m == '\19') and m or m:sub(1, 1) local key = (m == '\22' or m == '\19') and m or m:sub(1, 1)
local hl = mode_hl_map[key] or 'StatusModeNormal' local hl = mode_hl_map[key] or 'StatusModeNormal'
local b = vim.b
return table.concat({ return (mode_statusline[key] or mode_statusline['default'])
'%#' .. hl .. '#' .. (mode_map[key] or ' ?? ') .. '%*', .. (b.status_left or '')
b.status_left or '', .. '%='
'%=', .. (b.status_right or '')
b.status_right or '', .. '%#StatusCursor# %l:%-2c '
'%#StatusCursor# %l:%c ', .. '%#'
'%#' .. hl .. '# %p%% %*', .. hl
}) .. '# %p%% %*'
end end
vim.o.statusline = '%!v:lua.__statusline()' vim.o.statusline = '%!v:lua.__statusline()'