2023-12-31 00:10:56 +02:00

156 lines
6.7 KiB
Lua

--- ### AstroNvim Status Initializers
--
-- Statusline related init functions for building dynamic statusline components
--
-- This module can be loaded with `local init = require "astronvim.utils.status.init"`
--
-- @module astronvim.utils.status.init
-- @copyright 2023
-- @license GNU General Public License v3.0
local M = {}
local env = require "astronvim.utils.status.env"
local provider = require "astronvim.utils.status.provider"
local status_utils = require "astronvim.utils.status.utils"
local utils = require "astronvim.utils"
local extend_tbl = utils.extend_tbl
--- An `init` function to build a set of children components for LSP breadcrumbs
---@param opts? table # options for configuring the breadcrumbs (default: `{ max_depth = 5, separator = "  ", icon = { enabled = true, hl = false }, padding = { left = 0, right = 0 } }`)
---@return function # The Heirline init function
-- @usage local heirline_component = { init = require("astronvim.utils.status").init.breadcrumbs { padding = { left = 1 } } }
function M.breadcrumbs(opts)
opts = extend_tbl({
max_depth = 5,
separator = env.separators.breadcrumbs or "",
icon = { enabled = true, hl = env.icon_highlights.breadcrumbs },
padding = { left = 0, right = 0 },
}, opts)
return function(self)
local data = require("aerial").get_location(true) or {}
local children = {}
-- add prefix if needed, use the separator if true, or use the provided character
if opts.prefix and not vim.tbl_isempty(data) then
table.insert(children, { provider = opts.prefix == true and opts.separator or opts.prefix })
end
local start_idx = 0
if opts.max_depth and opts.max_depth > 0 then
start_idx = #data - opts.max_depth
if start_idx > 0 then
table.insert(children, { provider = require("astronvim.utils").get_icon "Ellipsis" .. opts.separator })
end
end
-- create a child for each level
for i, d in ipairs(data) do
if i > start_idx then
local child = {
{ provider = string.gsub(d.name, "%%", "%%%%"):gsub("%s*->%s*", "") }, -- add symbol name
on_click = { -- add on click function
minwid = status_utils.encode_pos(d.lnum, d.col, self.winnr),
callback = function(_, minwid)
local lnum, col, winnr = status_utils.decode_pos(minwid)
vim.api.nvim_win_set_cursor(vim.fn.win_getid(winnr), { lnum, col })
end,
name = "heirline_breadcrumbs",
},
}
if opts.icon.enabled then -- add icon and highlight if enabled
local hl = opts.icon.hl
if type(hl) == "function" then hl = hl(self) end
local hlgroup = string.format("Aerial%sIcon", d.kind)
table.insert(child, 1, {
provider = string.format("%s ", d.icon),
hl = (hl and vim.fn.hlexists(hlgroup) == 1) and hlgroup or nil,
})
end
if #data > 1 and i < #data then table.insert(child, { provider = opts.separator }) end -- add a separator only if needed
table.insert(children, child)
end
end
if opts.padding.left > 0 then -- add left padding
table.insert(children, 1, { provider = status_utils.pad_string(" ", { left = opts.padding.left - 1 }) })
end
if opts.padding.right > 0 then -- add right padding
table.insert(children, { provider = status_utils.pad_string(" ", { right = opts.padding.right - 1 }) })
end
-- instantiate the new child
self[1] = self:new(children, 1)
end
end
--- An `init` function to build a set of children components for a separated path to file
---@param opts? table options for configuring the breadcrumbs (default: `{ max_depth = 3, path_func = provider.unique_path(), separator = "  ", suffix = true, padding = { left = 0, right = 0 } }`)
---@return function # The Heirline init function
-- @usage local heirline_component = { init = require("astronvim.utils.status").init.separated_path { padding = { left = 1 } } }
function M.separated_path(opts)
opts = extend_tbl({
max_depth = 3,
path_func = provider.unique_path(),
separator = env.separators.path or "",
suffix = true,
padding = { left = 0, right = 0 },
}, opts)
if opts.suffix == true then opts.suffix = opts.separator end
return function(self)
local path = opts.path_func(self)
if path == "." then path = "" end -- if there is no path, just replace with empty string
local data = vim.fn.split(path, "/")
local children = {}
-- add prefix if needed, use the separator if true, or use the provided character
if opts.prefix and not vim.tbl_isempty(data) then
table.insert(children, { provider = opts.prefix == true and opts.separator or opts.prefix })
end
local start_idx = 0
if opts.max_depth and opts.max_depth > 0 then
start_idx = #data - opts.max_depth
if start_idx > 0 then
table.insert(children, { provider = require("astronvim.utils").get_icon "Ellipsis" .. opts.separator })
end
end
-- create a child for each level
for i, d in ipairs(data) do
if i > start_idx then
local child = { { provider = d } }
local separator = i < #data and opts.separtor or opts.suffix
if separator then table.insert(child, { provider = separator }) end
table.insert(children, child)
end
end
if opts.padding.left > 0 then -- add left padding
table.insert(children, 1, { provider = status_utils.pad_string(" ", { left = opts.padding.left - 1 }) })
end
if opts.padding.right > 0 then -- add right padding
table.insert(children, { provider = status_utils.pad_string(" ", { right = opts.padding.right - 1 }) })
end
-- instantiate the new child
self[1] = self:new(children, 1)
end
end
--- An `init` function to build multiple update events which is not supported yet by Heirline's update field
---@param opts any[] an array like table of autocmd events as either just a string or a table with custom patterns and callbacks.
---@return function # The Heirline init function
-- @usage local heirline_component = { init = require("astronvim.utils.status").init.update_events { "BufEnter", { "User", pattern = "LspProgressUpdate" } } }
function M.update_events(opts)
return function(self)
if not rawget(self, "once") then
local clear_cache = function() self._win_cache = nil end
for _, event in ipairs(opts) do
local event_opts = { callback = clear_cache }
if type(event) == "table" then
event_opts.pattern = event.pattern
event_opts.callback = event.callback or clear_cache
event.pattern = nil
event.callback = nil
end
vim.api.nvim_create_autocmd(event, event_opts)
end
self.once = true
end
end
end
return M