summary refs log tree commit diff
path: root/.vim/lua/statusline.lua
diff options
context:
space:
mode:
authorRobert Günzler <r@gnzler.io>2022-04-15 14:54:52 +0200
committerRobert Günzler <r@gnzler.io>2022-04-15 14:54:52 +0200
commitcfd78f5133b15dfb7b90d15d35d8b3739cebb12b (patch)
tree3b507a417f904dc057e48e3d0910063186966d44 /.vim/lua/statusline.lua
parent06fbd867be412c4eff480f70c9f9902635d4d726 (diff)
vim: move statusline into separate file
Diffstat (limited to '')
-rw-r--r--.vim/lua/statusline.lua224
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()")'