CHORE: Fixing some minor bugs
This commit is contained in:
@@ -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
|
||||
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)
|
||||
if ev.event == 'LspAttach' then
|
||||
local cid = ev.data.client_id
|
||||
if not active_progress[cid] then
|
||||
active_progress[cid] = 'starting'
|
||||
if ev.event == 'LspAttach' then
|
||||
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()'
|
||||
|
||||
Reference in New Issue
Block a user