diff options
| author | Robert Günzler <r@gnzler.io> | 2022-04-15 14:54:52 +0200 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2022-04-15 14:54:52 +0200 |
| commit | cfd78f5133b15dfb7b90d15d35d8b3739cebb12b (patch) | |
| tree | 3b507a417f904dc057e48e3d0910063186966d44 /.vim/lua | |
| parent | 06fbd867be412c4eff480f70c9f9902635d4d726 (diff) | |
vim: move statusline into separate file
Diffstat (limited to '.vim/lua')
| -rw-r--r-- | .vim/lua/statusline.lua | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/.vim/lua/statusline.lua b/.vim/lua/statusline.lua new file mode 100644 index 0000000..48a134d --- /dev/null +++ b/.vim/lua/statusline.lua @@ -0,0 +1,224 @@ + +require('spinner').setup { + spinner = {'⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'}, + interval = 120, -- spinner frame rate in ms +} + +function _G.statusline() + local bufnr = vim.fn.bufnr() or 0 + local hi = statusline_color(vim.fn.mode()) + + local sl = '' + -- left + sl = sl .. hi + -- sl = sl .. statusline_append([[ ⢷]], '%#StatusLineIcon#', hi) + sl = sl .. statusline_append([[%<%F %-m %-r]], hi, hi) + + -- right + sl = sl .. [[ %= ]] -- spacer + + sl = sl .. statusline_append(statusline_dap(), '%#StatusLineDap#', hi) + sl = sl .. statusline_append(statusline_notify(hi), '%#StatusLineNotify#', hi) + + local lsp_status = require('lsp-status').status() + sl = sl .. statusline_append(vim.trim(lsp_status), '%#StatusLineLsp#', hi) + + local lsp_spinner = require('spinner').status(bufnr) + sl = sl .. statusline_append(lsp_spinner, '%#StatusLineJobs#', hi) + + local lsp_diagnostics = statusline_lsp_diagnostics(bufnr, hi) + sl = sl .. statusline_append(lsp_diagnostics, '%#StatusLineDiagnostics#', hi) + + local lsp_lightbulb = require('nvim-lightbulb').get_status_text() + sl = sl .. statusline_append(lsp_lightbulb, '%#StatusLineLightbulb#', hi) + + sl = sl .. statusline_append([[ %l:%v %y]], hi, hi) + 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 + +-- statusline_append +-- 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 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_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_combine_hi(outer_name, inner_name) + local outer = vim.api.nvim_get_hl_by_name(outer_name, true) + local inner = vim.api.nvim_get_hl_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_dap() + local s = require('dap').status() + if s == '' then return s end + return '[DAP: ' .. s .. ']' +end + +-- notifications cache +_G.statusline_notifications = {} +_G.statusline_notifications_archive = {} + +function _G.statusline_notify(default_hi) + if #_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 <timeout> 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(n.message, '%#StatusLineNotify#', default_hi) + return vim.trim(s) +end + +-- out vim.notify implementation +local notify = function(m, l, o) + local lvl_string = l + local hi = nil + if l and type(l) == 'number' then + if l == vim.log.levels.TRACE then + hi = 'deEmph' + elseif l == vim.log.levels.DEBUG then + hi = 'DiagnosticHint' + elseif l == vim.log.levels.INFO then + hi = 'DiagnosticInfo' + elseif l == vim.log.levels.WARN then + hi = 'DiagnosticWarn' + elseif l == vim.log.levels.ERROR then + hi = 'DiagnosticError' + end + lvl_string = vim.lsp.log_levels[l] + end + local display = m + if lvl_string then display = lvl_string .. ' ' .. display end + table.insert(_G.statusline_notifications, { + message = m, + level = l, + options = o, + lvl_string = lvl_string, + hi = hi, + display = display, + }) + + if _G.statusline_enable_notifysend then + local args = {} + if lvl_string then + if lvl_string == 'ERROR' then + table.insert(args, '--category=error') + end + if lvl_string == 'WARN' then + table.insert(args, '--category=warning') + end + end + table.insert(args, 'nvim') + table.insert(args, display) + require('job').jobstart { command = 'notify-send', args = args } + end +end + +-- overwrite vim.notify +vim.notify = function( m, l, o) + if vim.in_fast_event() then + vim.schedule(function() + notify(m, l, o) + end) + else + return notify(m, l, o) + end +end + +vim.keymap.set('n', '<leader>N', function() + local pickers = require('telescope.pickers') + local finders = require('telescope.finders') + local conf = require('telescope.config').values + local actions = require('telescope.actions') + -- local action_state = require('telescope.actions.state') + local previewers = require('telescope.previewers') + + local opts = {} + pickers.new(opts, { + prompt_title = "Notifications", + finder = finders.new_dynamic { + fn = function() + return _G.statusline_notifications_archive + end, + entry_maker = function(n) + return { + value = n, + display = n.display, + ordinal = n.message, + } + end, + }, + sorter = conf.generic_sorter(opts), + attach_mappings = function(prompt_bufnr, _) + actions.select_default:replace(function() + actions.close(prompt_bufnr) + -- noop + -- local sel = action_state.get_selected_entry() + -- vim.notify(sel.value.message, sel.value.level, sel.value.options) + end) + return true + end, + previewer = previewers.new_buffer_previewer { + define_preview = function(self, entry) + vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, vim.split(vim.inspect(entry.value), '\n')) + end, + }, + }):find() +end) + +vim.opt.statusline = '%!luaeval("statusline()")' |