diff options
Diffstat (limited to 'lua/core/statusbar')
-rw-r--r-- | lua/core/statusbar/components.lua | 325 |
1 files changed, 0 insertions, 325 deletions
diff --git a/lua/core/statusbar/components.lua b/lua/core/statusbar/components.lua deleted file mode 100644 index 0233e1b..0000000 --- a/lua/core/statusbar/components.lua +++ /dev/null @@ -1,325 +0,0 @@ -if not pcall(require, "el") then return end - -local job = require "plenary.job" -local el_sub = require "el.subscribe" - -local M = {} - -function M.extract_hl(spec) - if not spec or vim.tbl_isempty(spec) then return end - local hl_name, hl_opts = { "El" }, {} - for attr, val in pairs(spec) do - if type(val) == "table" then - table.insert(hl_name, attr) - assert(vim.tbl_count(val) == 1) - local hl, what = next(val) - local hlID = vim.fn.hlID(hl) - if hlID > 0 then - table.insert(hl_name, hl) - local col = vim.fn.synIDattr(hlID, what) - if col and #col > 0 then - table.insert(hl_name, what) - hl_opts[attr] = col - end - end - else - -- bold, underline, etc - hl_opts[attr] = val - end - end - hl_name = table.concat(hl_name, "_") - -- if highlight exists, verify it has - -- the correct colorscheme highlights - local newID = vim.fn.hlID(hl_name) - if newID > 0 then - for what, expected in pairs(hl_opts) do - local res = vim.fn.synIDattr(newID, what) - if type(expected) == "boolean" then - -- synIDattr returns '1' for boolean - res = res and res == "1" and true - end - if res ~= expected then - -- need to regen the highlight - -- print("color mismatch", hl_name, what, "e:", expected, "c:", res) - newID = 0 - end - end - end - if newID == 0 then - vim.api.nvim_set_hl(0, hl_name, hl_opts) - end - return hl_name -end - -local function set_hl(hls, s) - if not hls or not s then return s end - hls = type(hls) == "string" and { hls } or hls - for _, hl in ipairs(hls) do - if vim.fn.hlID(hl) > 0 then - return ("%%#%s#%s%%0*"):format(hl, s) - end - end - return s -end - -local function wrap_fnc(opts, fn) - return function(window, buffer) - -- buf_autocmd doesn't send win - if not window and buffer then - window = { win_id = vim.fn.bufwinid(buffer.bufnr) } - end - if opts.hide_inactive and window and - window.win_id ~= vim.api.nvim_get_current_win() then - return "" - end - return fn(window, buffer) - end -end - -function M.mode(opts) - opts = opts or {} - return wrap_fnc(opts, function(_, _) - local fmt = opts.fmt or "%s%s" - local mode = vim.api.nvim_get_mode().mode - local mode_data = opts.modes and opts.modes[mode] - local hls = mode_data and mode_data[3] - local icon = opts.hl_icon_only and set_hl(hls, opts.icon) or opts.icon - mode = mode_data and mode_data[1]:upper() or mode - mode = (fmt):format(icon or "", mode) - return not opts.hl_icon_only and set_hl(hls, mode) or mode - end) -end - -function M.git_branch(opts) - opts = opts or {} - return el_sub.buf_autocmd("el_git_branch", "BufEnter", - wrap_fnc(opts, function(_, buffer) - -- Try fugitive first as it's most reliable - local branch = vim.g.loaded_fugitive == 1 and - vim.fn.FugitiveHead() or nil - -- buffer can be null and code will crash with: - -- E5108: Error executing lua ... 'attempt to index a nil value' - if not buffer or not (buffer.bufnr > 0) then - return - end - -- fugitive is empty or not loaded, try gitsigns - if not branch or #branch == 0 then - local ok, res = pcall(vim.api.nvim_buf_get_var, - buffer.bufnr, "gitsigns_head") - if ok then branch = res end - end - -- last resort run git command - if not branch then - local j = job:new { - command = "git", - args = { "branch", "--show-current" }, - cwd = vim.fn.fnamemodify(buffer.name, ":h"), - } - - local ok, result = pcall(function() - return vim.trim(j:sync()[1]) - end) - if ok then - branch = result - end - end - - if branch and #branch > 0 then - local fmt = opts.fmt or "%s %s" - local icon = opts.icon or "" - return set_hl(opts.hl, (fmt):format(icon, branch)) - end - end)) -end - -local function git_changes_formatter(opts) - local specs = { - insert = { - regex = "(%d+) insertions?", - icon = opts.icon_insert or "+", - hl = opts.hl_insert, - }, - change = { - regex = "(%d+) files? changed", - icon = opts.icon_change or "~", - hl = opts.hl_change, - }, - delete = { - regex = "(%d+) deletions?", - icon = opts.icon_delete or "-", - hl = opts.hl_delete, - }, - } - return function(_, _, s) - local result = {} - for k, v in pairs(specs) do - local count = nil - if type(s) == "string" then - -- 'git diff --shortstat' output - -- from 'git_changes_all' - count = tonumber(string.match(s, v.regex)) - else - -- map from 'git_changes_buf' - count = s[k] - end - if count and count > 0 then - table.insert(result, set_hl(v.hl, ("%s%d"):format(v.icon, count))) - end - end - return table.concat(result, " ") - end -end - --- requires gitsigns -function M.git_changes_buf(opts) - opts = opts or {} - local formatter = opts.formatter or git_changes_formatter(opts) - return wrap_fnc(opts, function(window, buffer) - local stats = {} - if buffer and buffer.bufnr > 0 then - local ok, res = pcall(vim.api.nvim_buf_get_var, - buffer.bufnr, "vgit_status") - if ok then stats = res end - end - if buffer and buffer.bufnr > 0 then - local ok, res = pcall(vim.api.nvim_buf_get_var, - buffer.bufnr, "gitsigns_status_dict") - if ok then stats = res end - end - local counts = { - insert = stats.added > 0 and stats.added or nil, - change = stats.changed > 0 and stats.changed or nil, - delete = stats.removed > 0 and stats.removed or nil, - } - if not vim.tbl_isempty(counts) then - local fmt = opts.fmt or "%s" - local out = formatter(window, buffer, counts) - return out and fmt:format(out) or nil - else - -- el functions that return a - -- string must not return nil - return "" - end - end) -end - -function M.git_changes_all(opts) - opts = opts or {} - local formatter = opts.formatter or git_changes_formatter(opts) - return el_sub.buf_autocmd("el_git_changes", "BufWritePost", - wrap_fnc(opts, function(window, buffer) - if not buffer or - not (buffer.bufnr > 0) or - vim.bo[buffer.bufnr].bufhidden ~= "" or - vim.bo[buffer.bufnr].buftype == "nofile" or - vim.fn.filereadable(buffer.name) ~= 1 then - return - end - - local j = job:new { - command = "git", - args = { "diff", "--shortstat" }, - -- makes no sense to run for one file as - -- 'file(s) changed' will always be 1 - -- args = { "diff", "--shortstat", buffer.name }, - cwd = vim.fn.fnamemodify(buffer.name, ":h"), - } - - local ok, git_changes = pcall(function() - return formatter(window, buffer, vim.trim(j:sync()[1])) - end) - - if ok then - local fmt = opts.fmt or "%s" - return git_changes and fmt:format(git_changes) or nil - end - end)) -end - -function M.lsp_srvname(opts) - local fmt = opts.fmt or "%s" - local icon = opts.icon or "" - local names = "" - vim.lsp.for_each_buffer_client(0, function(client) - if names ~= "" then names = names..", " end - names = names..client.name - end) - return icon..fmt:format(names) -end - -local function diag_formatter(opts) - return function(_, buffer, counts) - local items = {} - local icons = { - ["errors"] = { opts.icon_err or "x", opts.hl_err or "DiagnosticError"}, - ["warnings"] = { opts.icon_warn or "!", opts.hl_warn or "DiagnosticWarn"}, - ["infos"] = { opts.icon_info or "i", opts.hl_info or "DiagnosticInfo"}, - ["hints"] = { opts.icon_hint or "h", opts.hl_hint or "DiagnosticHint"}, - } - for _, k in ipairs({ "errors", "warnings", "infos", "hints" }) do - if counts[k] > 0 then - table.insert(items, - set_hl(icons[k][2], ("%s:%s"):format(icons[k][1], counts[k]))) - end - end - local fmt = opts.fmt or "%s" - if vim.tbl_isempty(items) then - return "" - else - return fmt:format(table.concat(items, " ")) - end - end -end - -local function get_buffer_counts(diagnostic, _, buffer) - local counts = { 0, 0, 0, 0 } - local diags = diagnostic.get(buffer.bufnr) - if diags and not vim.tbl_isempty(diags) then - for _, d in ipairs(diags) do - if tonumber(d.severity) then - counts[d.severity] = counts[d.severity] + 1 - end - end - end - return { - errors = counts[1], - warnings = counts[2], - infos = counts[3], - hints = counts[4], - } -end - -function M.diagnostics(opts) - opts = opts or {} - local formatter = opts.formatter or diag_formatter(opts) - return el_sub.buf_autocmd("el_buf_diagnostic", "LspAttach,DiagnosticChanged", - wrap_fnc(opts, function(window, buffer) - return formatter(window, buffer, get_buffer_counts(vim.diagnostic, window, buffer)) - end)) -end - -function M.line(opts) - opts = opts or {} - local fmt = opts.fmt or "%s" - return wrap_fnc(opts, function(_, _) - local al = vim.api.nvim_buf_line_count(0) - local cl = vim.api.nvim_win_get_cursor(0)[1] - return (fmt):format(cl.."/"..al.." "..math.floor((cl / al) * 100).."%%") - end) -end - -function M.fn_tail(opts) - opts = opts or {} - local fmt = opts.fmt or "%s" - local hl_exec = opts.hl_exec or "Character" - - local fn = vim.fn.expand("%:t") - if vim.fn.getftype(fn) == "file" then - if string.match(vim.fn.getfperm(fn), 'x', 3) then - return (fmt):format(set_hl(hl_exec, fn)) - end - end - return (fmt):format(fn) -end - -return M |