From 75e4e77dbac618b6922354aa0efadfbd6e015dd1 Mon Sep 17 00:00:00 2001 From: Andrew Haynes Date: Sat, 3 Oct 2026 01:53:11 -0400 Subject: [PATCH] CHORE: Fixing some minor bugs --- nvim/.config/nvim/lua/DarthMooMancer/ui.lua | 171 +++++++++++++++----- 1 file changed, 132 insertions(+), 39 deletions(-) diff --git a/nvim/.config/nvim/lua/DarthMooMancer/ui.lua b/nvim/.config/nvim/lua/DarthMooMancer/ui.lua index 06186d2..fd0c5dc 100644 --- a/nvim/.config/nvim/lua/DarthMooMancer/ui.lua +++ b/nvim/.config/nvim/lua/DarthMooMancer/ui.lua @@ -74,10 +74,10 @@ local mode_hl_map = { i = 'StatusModeInsert', v = 'StatusModeVisual', V = 'StatusModeVisual', - ['^V'] = 'StatusModeVisual', + ['\22'] = 'StatusModeVisual', s = 'StatusModeVisual', S = 'StatusModeVisual', - ['^S'] = 'StatusModeVisual', + ['\19'] = 'StatusModeVisual', R = 'StatusModeReplace', c = 'StatusModeCommand', r = 'StatusModeCommand', @@ -85,6 +85,13 @@ local mode_hl_map = { 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 b = vim.b[buf] local left, right = {}, {} @@ -116,8 +123,14 @@ local function refresh_status(buf) .. ' %*' end - b.status_left = #left > 0 and table.concat(left) or '' - b.status_right = #right > 0 and table.concat(right) or '' + local l = #left > 0 and table.concat(left) 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 local lsp_icon = { @@ -144,29 +157,47 @@ local function refresh_lsp(buf) local names = {} for _, client in ipairs(clients) do names[#names + 1] = client.name - local prog = active_progress[client.id] - if prog == 'working' then - state = 'working' - elseif prog == 'starting' and state ~= 'working' then - state = 'starting' + local p = active_progress[client.id] + if p then + if p.is_starting then + if state ~= 'working' then + state = 'starting' + end + elseif next(p.tokens) then + state = 'working' + end end vim.b[buf].lsp_name = table.concat(names, '/') 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_hl = lsp_hl[state] refresh_status(buf) + vim.cmd.redrawstatus() end vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, { callback = function(ev) + local cid = ev.data.client_id if ev.event == 'LspAttach' then - local cid = ev.data.client_id - if not active_progress[cid] 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() - if active_progress[cid] == 'starting' then - active_progress[cid] = nil + local curr = active_progress[cid] + 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 refresh_lsp(ev.buf) end @@ -174,7 +205,7 @@ vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, { end, 500) -- 500ms grace period to wait for LspProgress end elseif ev.event == 'LspDetach' then - active_progress[ev.data.client_id] = nil + active_progress[cid] = nil end refresh_lsp(ev.buf) end, @@ -182,13 +213,27 @@ vim.api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, { vim.api.nvim_create_autocmd('LspProgress', { callback = function(ev) - local kind = ev.data.params.value and ev.data.params.value.kind - if kind == 'begin' or kind == 'report' then - active_progress[ev.data.client_id] = 'working' - elseif kind == 'end' then - active_progress[ev.data.client_id] = nil - else - return + local cid = ev.data.client_id + local p = active_progress[cid] or { tokens = {} } + active_progress[cid] = p + + if p.is_starting then + p.is_starting = nil + 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 local client = vim.lsp.get_client_by_id(ev.data.client_id) if client then @@ -200,6 +245,18 @@ vim.api.nvim_create_autocmd('LspProgress', { }) 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 file = vim.api.nvim_buf_get_name(buf) @@ -207,12 +264,17 @@ local function refresh_branch(buf) vim.b[buf].git_branch = '' return 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' }, { text = true, cwd = cwd }, vim.schedule_wrap(function(out) + branch_jobs[buf] = nil if not vim.api.nvim_buf_is_valid(buf) then return end @@ -220,24 +282,39 @@ local function refresh_branch(buf) vim.b[buf].git_branch = branch ~= '' and (BRANCH_ICON .. branch) or '' refresh_status(buf) + vim.cmd.redrawstatus() end) ) end -local function refresh_diff(buf) +local function refresh_diff(buf, force) local file = vim.api.nvim_buf_get_name(buf) if file == '' or vim.bo[buf].buftype ~= '' then vim.b[buf].git_diff = nil return end - local cwd = vim.fs.root(buf, '.git') or vim.fs.dirname(file) - vim.system( + if + 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 }, { text = true, cwd = cwd }, vim.schedule_wrap(function(out) + diff_jobs[buf] = nil if not vim.api.nvim_buf_is_valid(buf) then return end + vim.b[buf].git_diff_fetched = true if out.code ~= 0 or out.stdout == '' then vim.b[buf].git_diff = nil else @@ -252,6 +329,7 @@ local function refresh_diff(buf) end end refresh_status(buf) + vim.cmd.redrawstatus() end) ) end @@ -271,11 +349,13 @@ local function refresh_diag(buf) end vim.b[buf].diag_str = #parts > 0 and table.concat(parts) or '' refresh_status(buf) + vim.cmd.redrawstatus() end vim.api.nvim_create_autocmd('DiagnosticChanged', { callback = function(ev) refresh_diag(ev.buf) + vim.cmd.redrawstatus() end, }) @@ -283,7 +363,7 @@ vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, { callback = function(ev) if vim.bo[ev.buf].buftype == '' then refresh_branch(ev.buf) - refresh_diff(ev.buf) + refresh_diff(ev.buf, false) end refresh_lsp(ev.buf) refresh_diag(ev.buf) @@ -299,7 +379,7 @@ vim.api.nvim_create_autocmd('FocusGained', { }) vim.api.nvim_create_autocmd('BufWritePost', { callback = function(ev) - refresh_diff(ev.buf) + refresh_diff(ev.buf, true) end, }) @@ -320,18 +400,31 @@ vim.api.nvim_create_autocmd('RecordingLeave', { }) 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 hl = mode_hl_map[key] or 'StatusModeNormal' - local b = vim.b - return table.concat({ - '%#' .. hl .. '#' .. (mode_map[key] or ' ?? ') .. '%*', - b.status_left or '', - '%=', - b.status_right or '', - '%#StatusCursor# %l:%c ', - '%#' .. hl .. '# %p%% %*', - }) + + return (mode_statusline[key] or mode_statusline['default']) + .. (b.status_left or '') + .. '%=' + .. (b.status_right or '') + .. '%#StatusCursor# %l:%-2c ' + .. '%#' + .. hl + .. '# %p%% %*' end vim.o.statusline = '%!v:lua.__statusline()'