REFACTOR: Opencode heavily optimized statusline
This commit is contained in:
@@ -1,203 +1,186 @@
|
|||||||
local has_devicons, devicons = pcall(require, 'nvim-web-devicons')
|
local ok, D = pcall(require, 'nvim-web-devicons')
|
||||||
local uv, api, b = vim.uv or vim.loop, vim.api, vim.b
|
local a, u, S = vim.api, vim.uv or vim.loop, vim.diagnostic.severity
|
||||||
local SEV = vim.diagnostic.severity
|
local C = a.nvim_get_current_buf
|
||||||
|
local R = function()
|
||||||
local function setup_highlights()
|
vim.cmd.redrawstatus()
|
||||||
local bg = api.nvim_get_hl(0, { name = 'StatusLine' }).bg or 'none'
|
|
||||||
|
|
||||||
local function set(name, link, bold)
|
|
||||||
local hl = api.nvim_get_hl(0, { name = link, link = false })
|
|
||||||
api.nvim_set_hl(0, name, { fg = hl.fg, bg = bg, bold = bold or false })
|
|
||||||
end
|
|
||||||
|
|
||||||
set('StatusLineFilename', 'Normal', true)
|
|
||||||
set('StatusLineMod', 'WarningMsg', true)
|
|
||||||
set('StatusLineRO', 'ErrorMsg', true)
|
|
||||||
set('StatusDiagError', 'DiagnosticError', true)
|
|
||||||
set('StatusDiagWarn', 'DiagnosticWarn', false)
|
|
||||||
set('StatusDiagHint', 'DiagnosticHint', false)
|
|
||||||
set('StatusLspSpinner', 'DiagnosticWarn', true)
|
|
||||||
set('StatusLspLoading', 'DiagnosticInfo', false)
|
|
||||||
set('StatusLspReady', 'Comment', false)
|
|
||||||
end
|
end
|
||||||
|
local M = '%#StatusLineMod#%m%*%#StatusLineRO#%r%* %='
|
||||||
api.nvim_create_autocmd({ 'ColorScheme', 'FocusGained', 'VimEnter' }, {
|
local FR = { '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏' }
|
||||||
callback = function()
|
local N, SPIN, LOAD = #FR, '%#StatusLspSpinner#', '%* %#StatusLspLoading#'
|
||||||
setup_highlights()
|
local c, T, JOB, TMR, IDX = {}, {}, nil, nil, 1
|
||||||
vim.cmd('redrawstatus')
|
local function HI()
|
||||||
end,
|
local bg = a.nvim_get_hl(0, { name = 'StatusLine' }).bg or 'none'
|
||||||
})
|
for _, t in ipairs({
|
||||||
setup_highlights()
|
{ 'StatusLineFilename', 'Normal', true },
|
||||||
|
{ 'StatusLineMod', 'WarningMsg', true },
|
||||||
local function update_file_info(buf)
|
{ 'StatusLineRO', 'ErrorMsg', true },
|
||||||
local path = api.nvim_buf_get_name(buf)
|
{ 'StatusDiagError', 'DiagnosticError', true },
|
||||||
if path == '' then
|
{ 'StatusDiagWarn', 'DiagnosticWarn', false },
|
||||||
b[buf].stl_file_info = ' %#StatusLineFilename#[No Name]%*'
|
{ 'StatusDiagHint', 'DiagnosticHint', false },
|
||||||
return
|
{ 'StatusLspSpinner', 'DiagnosticWarn', true },
|
||||||
|
{ 'StatusLspLoading', 'DiagnosticInfo', false },
|
||||||
|
{ 'StatusLspReady', 'Comment', false },
|
||||||
|
}) do
|
||||||
|
local h = a.nvim_get_hl(0, { name = t[2], link = false })
|
||||||
|
a.nvim_set_hl(0, t[1], { fg = h.fg, bg = bg, bold = t[3] })
|
||||||
end
|
end
|
||||||
|
|
||||||
local fname = path:match('([^/\\]+)$') or path
|
|
||||||
local icon = ''
|
|
||||||
if has_devicons then
|
|
||||||
local ic, hl = devicons.get_icon(
|
|
||||||
fname,
|
|
||||||
path:match('%.([^./\\]+)$'),
|
|
||||||
{ default = true }
|
|
||||||
)
|
|
||||||
if ic then
|
|
||||||
icon = '%#' .. hl .. '#' .. ic .. ' %*'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
b[buf].stl_file_info = ' '
|
|
||||||
.. icon
|
|
||||||
.. '%#StatusLineFilename#'
|
|
||||||
.. fname
|
|
||||||
.. '%*'
|
|
||||||
end
|
end
|
||||||
|
local function snap(bb)
|
||||||
local function update_lsp_clients(buf)
|
local p = a.nvim_buf_get_name(bb)
|
||||||
local clients = vim.lsp.get_clients({ bufnr = buf })
|
local nm = ' %#StatusLineFilename#'
|
||||||
if #clients == 0 then
|
if p == '' then
|
||||||
b[buf].stl_lsp_ready = ''
|
nm = nm .. '[No Name]%*'
|
||||||
return
|
else
|
||||||
|
local f = p:match('([^/\\]+)$') or p
|
||||||
|
if ok then
|
||||||
|
local i, hl = D.get_icon(f, p:match('%.([^./\\]+)$'), { default = true })
|
||||||
|
if i then
|
||||||
|
nm = nm .. '%#' .. hl .. '#' .. i .. ' %*'
|
||||||
end
|
end
|
||||||
|
|
||||||
local names = {}
|
|
||||||
for i = 1, #clients do
|
|
||||||
names[i] = clients[i].name
|
|
||||||
end
|
end
|
||||||
b[buf].stl_lsp_ready = '%#StatusLspReady# '
|
nm = nm .. f .. '%*'
|
||||||
.. table.concat(names, '/')
|
end
|
||||||
.. '%* '
|
local x = vim.diagnostic.count(bb)
|
||||||
|
local e, w, h = x[S.ERROR] or 0, x[S.WARN] or 0, x[S.HINT] or 0
|
||||||
|
local dg = ''
|
||||||
|
if e + w + h > 0 then
|
||||||
|
dg = (e > 0 and ('%#StatusDiagError#E' .. e .. '%* ') or '')
|
||||||
|
.. (w > 0 and ('%#StatusDiagWarn#W' .. w .. '%* ') or '')
|
||||||
|
.. (h > 0 and ('%#StatusDiagHint#H' .. h .. '%* ') or '')
|
||||||
|
end
|
||||||
|
local rd, cs = '', vim.lsp.get_clients({ bufnr = bb })
|
||||||
|
if #cs > 0 then
|
||||||
|
local nm2 = {}
|
||||||
|
for i = 1, #cs do
|
||||||
|
nm2[i] = cs[i].name
|
||||||
|
end
|
||||||
|
rd = '%#StatusLspReady# ' .. table.concat(nm2, '/') .. '%* '
|
||||||
|
end
|
||||||
|
return nm .. M .. dg, rd
|
||||||
end
|
end
|
||||||
|
local function touch(bb, redraw)
|
||||||
local active_tokens = {}
|
local v = c[bb]
|
||||||
local spinner_frames =
|
if v then
|
||||||
{ '⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏' }
|
v.d = true
|
||||||
local current_job, spinner_timer = nil, nil
|
end
|
||||||
|
if redraw then
|
||||||
local function sync_spinner()
|
R()
|
||||||
current_job = nil
|
end
|
||||||
for _, tokens in pairs(active_tokens) do
|
end
|
||||||
for _, msg in pairs(tokens) do
|
local function SYNC()
|
||||||
current_job = msg
|
JOB = nil
|
||||||
|
for _, t in pairs(T) do
|
||||||
|
for _, m in pairs(t) do
|
||||||
|
JOB = m
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
if current_job then
|
if JOB then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if JOB and not TMR then
|
||||||
if current_job and not spinner_timer then
|
IDX = math.floor(u.now() / 100) % N + 1
|
||||||
spinner_timer = uv.new_timer()
|
TMR = u.new_timer()
|
||||||
spinner_timer:start(
|
TMR:start(
|
||||||
0,
|
0,
|
||||||
100,
|
100,
|
||||||
vim.schedule_wrap(function()
|
vim.schedule_wrap(function()
|
||||||
if current_job then
|
if JOB then
|
||||||
vim.cmd('redrawstatus')
|
IDX = IDX % N + 1
|
||||||
elseif spinner_timer then
|
R()
|
||||||
spinner_timer:stop()
|
elseif TMR then
|
||||||
spinner_timer:close()
|
TMR:stop()
|
||||||
spinner_timer = nil
|
TMR:close()
|
||||||
|
TMR = nil
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
)
|
)
|
||||||
elseif not current_job and spinner_timer then
|
elseif not JOB and TMR then
|
||||||
spinner_timer:stop()
|
TMR:stop()
|
||||||
spinner_timer:close()
|
TMR:close()
|
||||||
spinner_timer = nil
|
TMR = nil
|
||||||
vim.cmd('redrawstatus')
|
R()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local G = a.nvim_create_augroup('STL5', { clear = true })
|
||||||
local group = api.nvim_create_augroup('MinimalStatusline', { clear = true })
|
for _, s in ipairs({
|
||||||
|
{
|
||||||
api.nvim_create_autocmd({ 'BufEnter', 'BufFilePost' }, {
|
{ 'BufEnter', 'BufFilePost' },
|
||||||
group = group,
|
function(e)
|
||||||
callback = function(ev)
|
touch(e.buf, true)
|
||||||
update_file_info(ev.buf)
|
|
||||||
update_lsp_clients(ev.buf)
|
|
||||||
end,
|
end,
|
||||||
})
|
},
|
||||||
|
{
|
||||||
api.nvim_create_autocmd('DiagnosticChanged', {
|
'DiagnosticChanged',
|
||||||
group = group,
|
function(e)
|
||||||
callback = function(ev)
|
touch(e.buf, e.buf == C())
|
||||||
if ev.buf == api.nvim_get_current_buf() then
|
end,
|
||||||
vim.cmd('redrawstatus')
|
},
|
||||||
|
{
|
||||||
|
{ 'LspAttach', 'LspDetach' },
|
||||||
|
function(e)
|
||||||
|
if e.event == 'LspDetach' then
|
||||||
|
T[e.data.client_id] = nil
|
||||||
|
SYNC()
|
||||||
end
|
end
|
||||||
|
touch(e.buf, true)
|
||||||
end,
|
end,
|
||||||
})
|
},
|
||||||
|
{
|
||||||
api.nvim_create_autocmd({ 'LspAttach', 'LspDetach' }, {
|
'LspProgress',
|
||||||
group = group,
|
function(e)
|
||||||
callback = function(ev)
|
local v = e.data.params.value
|
||||||
if ev.event == 'LspDetach' then
|
if type(v) ~= 'table' then
|
||||||
active_tokens[ev.data.client_id] = nil
|
|
||||||
sync_spinner()
|
|
||||||
end
|
|
||||||
update_lsp_clients(ev.buf)
|
|
||||||
vim.cmd('redrawstatus')
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
api.nvim_create_autocmd('LspProgress', {
|
|
||||||
group = group,
|
|
||||||
callback = function(ev)
|
|
||||||
local val = ev.data.params.value
|
|
||||||
if type(val) ~= 'table' then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local id, tk = e.data.client_id, e.data.params.token or 'default'
|
||||||
local client_id = ev.data.client_id
|
T[id] = T[id] or {}
|
||||||
local token = ev.data.params.token or 'default'
|
if v.kind == 'end' or (v.kind == 'report' and v.percentage == 100) then
|
||||||
active_tokens[client_id] = active_tokens[client_id] or {}
|
T[id][tk] = nil
|
||||||
|
|
||||||
if
|
|
||||||
val.kind == 'end'
|
|
||||||
or (val.kind == 'report' and val.percentage == 100)
|
|
||||||
then
|
|
||||||
active_tokens[client_id][token] = nil
|
|
||||||
else
|
else
|
||||||
local msg = (val.title and val.title ~= '' and val.title)
|
local m = (v.title and v.title ~= '' and v.title) or v.message or 'Loading...'
|
||||||
or val.message
|
if v.title and v.message and v.message ~= '' then
|
||||||
or 'Loading...'
|
m = v.title .. ' ' .. v.message
|
||||||
if val.title and val.message and val.message ~= '' then
|
|
||||||
msg = val.title .. ' ' .. val.message
|
|
||||||
end
|
end
|
||||||
active_tokens[client_id][token] = msg
|
T[id][tk] = m
|
||||||
end
|
end
|
||||||
|
SYNC()
|
||||||
sync_spinner()
|
|
||||||
end,
|
end,
|
||||||
})
|
},
|
||||||
|
{
|
||||||
function MinimalStatusline()
|
'BufUnload',
|
||||||
local cur_buf = api.nvim_get_current_buf()
|
function(e)
|
||||||
local vars = b[cur_buf]
|
c[e.buf] = nil
|
||||||
|
end,
|
||||||
local c = vim.diagnostic.count(cur_buf)
|
},
|
||||||
local e, w, h = c[SEV.ERROR] or 0, c[SEV.WARN] or 0, c[SEV.HINT] or 0
|
{
|
||||||
local diags = ''
|
'ColorScheme',
|
||||||
if e > 0 or w > 0 or h > 0 then
|
function()
|
||||||
diags = (e > 0 and ('%#StatusDiagError#E' .. e .. '%* ') or '')
|
HI()
|
||||||
.. (w > 0 and ('%#StatusDiagWarn#W' .. w .. '%* ') or '')
|
R()
|
||||||
.. (h > 0 and ('%#StatusDiagHint#H' .. h .. '%*') or '')
|
end,
|
||||||
end
|
},
|
||||||
|
{ 'FocusGained', R },
|
||||||
local right = current_job
|
}) do
|
||||||
and ('%#StatusLspSpinner#' .. spinner_frames[(math.floor(
|
a.nvim_create_autocmd(s[1], { group = G, callback = s[2] })
|
||||||
uv.now() / 100
|
|
||||||
) % 10) + 1] .. '%* %#StatusLspLoading#' .. current_job .. '%* ')
|
|
||||||
or (vars.stl_lsp_ready or '')
|
|
||||||
|
|
||||||
return (vars.stl_file_info or '')
|
|
||||||
.. '%#StatusLineMod#%m%*%#StatusLineRO#%r%* %='
|
|
||||||
.. diags
|
|
||||||
.. '%='
|
|
||||||
.. right
|
|
||||||
end
|
end
|
||||||
|
HI()
|
||||||
vim.opt.laststatus = 3
|
local function Status()
|
||||||
vim.opt.statusline = '%!v:lua.MinimalStatusline()'
|
local bb = C()
|
||||||
|
local v = c[bb]
|
||||||
|
if not v or v.d then
|
||||||
|
if not v then
|
||||||
|
v = {}
|
||||||
|
c[bb] = v
|
||||||
|
end
|
||||||
|
v.h, v.r = snap(bb)
|
||||||
|
v.stl = v.h .. v.r
|
||||||
|
v.d = nil
|
||||||
|
end
|
||||||
|
if JOB then
|
||||||
|
return v.h .. SPIN .. FR[IDX] .. LOAD .. JOB .. '%* '
|
||||||
|
end
|
||||||
|
return v.stl
|
||||||
|
end
|
||||||
|
_G.Status = Status
|
||||||
|
vim.opt.statusline = '%!v:lua.Status()'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
column_width = 80
|
column_width = 120
|
||||||
line_endings = "Unix"
|
line_endings = "Unix"
|
||||||
indent_type = "Tabs"
|
indent_type = "Tabs"
|
||||||
indent_width = 4
|
indent_width = 2
|
||||||
quote_style = "AutoPreferSingle"
|
quote_style = "AutoPreferSingle"
|
||||||
|
|||||||
Reference in New Issue
Block a user