function _G.statusline() local bufnr = vim.fn.bufnr() or 0 local hi = statusline_color(vim.fn.mode()) local sl = hi -- sl = sl .. statusline_append([[ ⢷]], 'StatusLineIcon', hi) sl = sl .. [[%-h%-w%-q%-f %-m %-r]] -- sl = sl .. statusline_append(statusline_ts(), 'StatusLineTreesitter', hi) sl = sl .. [[ %= ]] -- spacer sl = sl .. statusline_append(statusline_lsp_diagnostics(bufnr, hi), 'StatusLineDiagnostics', hi) sl = sl .. statusline_append(statusline_lspstatus(), 'StatusLineLsp', hi) sl = sl .. statusline_append(statusline_dap(), 'StatusLineDap', hi) -- sl = sl .. [[ %= ]] -- spacer sl = sl .. statusline_append(statusline_notify(hi), 'StatusLineNotify', hi) sl = sl .. statusline_append(statusline_spinner(bufnr), 'StatusLineJobs', hi) sl = sl .. [[%-l:%-v --%p%%-- %-Y]] return sl end function _G.statusline_color(mode) local hi = '%*' if mode == 'i' then -- hi = '%#StatusLineInsert#' elseif mode == 'c' then -- hi = '%#StatusLineCommand#' elseif mode == 'v' or mode == 'V' or mode == '' then hi = '%#StatusLineVisual#' elseif mode == 'R' or mode == 'Rv' then hi = '%#StatusLineReplace#' end -- return '%{g:actual_curwin==win_getid()?'.. hi ..':%#StatusLineNC#}' return hi end -- does item highlighting and conditionnal spacing function _G.statusline_append(element, hi, default_hi, opts) if not element or element == '' then return '' end opts = opts or { append_space = true } if hi ~= nil then hi = '%#' .. hi .. '#' end if not (default_hi == '%*') then hi = default_hi end local el = hi .. element .. default_hi if opts.append_space then el = el .. ' ' end return el end function _G.statusline_combine_hi(outer_name, inner_name) local outer = vim.api.nvim_get_hl_by_id(vim.api.nvim_get_hl_id_by_name(outer_name), true) local inner = vim.api.nvim_get_hl_by_id(vim.api.nvim_get_hl_id_by_name(inner_name), true) local hi = 'auto' .. outer_name .. inner_name if pcall(vim.api.nvim_get_hl_by_name, hi, true) then return hi end local gui gui = inner.bold and 'bold' gui = inner.italic and 'italic' gui = inner.underline and 'underline' vim.api.nvim_set_hl(0, hi, { bg = outer.background, fg = inner.foreground, gui = gui }) return hi end function _G.statusline_lsp_diagnostics(bufnr, default_hi) local error_num = vim.diagnostic.get(bufnr, { severity = vim.diagnostic.severity.ERROR }) local warn_num = vim.diagnostic.get(bufnr, { severity = vim.diagnostic.severity.WARN }) local s = '' if #error_num > 0 then local errs = vim.fn.sign_getdefined('DiagnosticSignError')[1].text .. #error_num s = s .. statusline_append( errs, statusline_combine_hi('StatusLineDiagnostics', 'DiagnosticError'), default_hi ) end if #warn_num > 0 then local warns = vim.fn.sign_getdefined('DiagnosticSignWarn')[1].text .. #warn_num s = s .. statusline_append( warns, statusline_combine_hi('StatusLineDiagnostics', 'DiagnosticWarn'), default_hi ) end return vim.trim(s) end function _G.statusline_ts() local navic = package.loaded['nvim-navic'] if not navic then return '' end local data = navic.get_data() if not data then return '' end local s = {} for i = 1, #data do table.insert( s, string.format( '%%#CmpItemKind%s#%s%%* %%#StatusLine#%s%%*', data[i].type, data[i].icon, data[i].name ) ) end return table.concat(s, ' > ') end function _G.statusline_lspstatus() local lst = package.loaded['lsp-status'] if not lst then return '' end return vim.trim(lst.status()) end function _G.statusline_spinner(bufnr) local sp = package.loaded.spinner if not sp then return '' end return sp.status(bufnr) end function _G.statusline_dap() local dap = package.loaded.dap if not dap then return '' end local s = dap.status() if s == '' then return s end return '[DAP: ' .. s .. ']' end function _G.statusline_notify(default_hi) if not _G.statusline_notifications or #_G.statusline_notifications == 0 then return '' end local n = _G.statusline_notifications[1] local timeout = (n.options and n.options.timeout) or 2000 -- pop message after and move to archive vim.defer_fn(function() local n_ = table.remove(_G.statusline_notifications, 1) table.insert(_G.statusline_notifications_archive, n_) -- make sure archive is never longer than 20 notifications if #_G.statusline_notifications_archive > 20 then table.remove(_G.statusline_notifications_archive, 1) end end, timeout) local s = '' if n.hi then s = s .. statusline_append( n.lvl_string .. ' ', statusline_combine_hi('StatusLineNotify', n.hi), default_hi, { append_space = false } ) end s = s .. statusline_append(vim.inspect(n.message), 'StatusLineNotify', default_hi) return vim.trim(s) end vim.opt.statusline = '%{%v:lua.statusline()%}' -- WINBAR -- -- vim.opt.winbar = [[%h%w%q%f %-m %-r %= %#WinBarCwd#%{%getcwd()%}%*]] -- keep it simple -- function _G.winbar() -- return [[%<%F %-m %-r]] -- end -- vim.opt.winbar = '%{%v:lua.winbar()%}'