|
| 1 | +---@class StatusLine |
| 2 | +---@field statusline_icon_hl fun(self: StatusLine, icon_hl: string, default_hl_token: string): string |
| 3 | +local StatusLine = {} |
| 4 | + |
| 5 | +function StatusLine:statusline_icon_hl(icon_hl, default_hl_token) |
| 6 | + local base_hl = default_hl_token:match("%%#(.-)#") or default_hl_token |
| 7 | + local group = ("Nikero_%s_%s"):format(base_hl, icon_hl):gsub("[^%w_]", "_") |
| 8 | + local icon = vim.api.nvim_get_hl(0, { name = group, link = false }) |
| 9 | + |
| 10 | + if next(icon) ~= nil then return group end |
| 11 | + |
| 12 | + local base = vim.api.nvim_get_hl(0, { name = base_hl, link = false }) |
| 13 | + local new_icon = vim.api.nvim_get_hl(0, { name = icon_hl, link = false }) |
| 14 | + |
| 15 | + vim.api.nvim_set_hl(0, group, { fg = new_icon.fg, bg = base.bg }) |
| 16 | + |
| 17 | + return group |
| 18 | +end |
| 19 | + |
| 20 | +function StatusLine:harpoon_item(default_hl, active_index) |
| 21 | + return function(index, item) |
| 22 | + local file_path = vim.fn.fnamemodify(item.value, ":p") |
| 23 | + local icon, base_icon_hl = require("mini.icons").get("file", file_path) |
| 24 | + |
| 25 | + local is_active = index == active_index |
| 26 | + local base_hl = default_hl |
| 27 | + if is_active then base_hl = "%#OverlayActive#" end |
| 28 | + |
| 29 | + local icon_hl = self:statusline_icon_hl(base_icon_hl, base_hl) |
| 30 | + local icon_str = self:wrap(icon_hl, icon) .. base_hl |
| 31 | + |
| 32 | + local value = string.format("%s %d", icon_str, index) |
| 33 | + |
| 34 | + if is_active then |
| 35 | + local side_hl = self:statusline_icon_hl("OverlayActiveInverted", default_hl) |
| 36 | + value = self:wrap(side_hl, "") .. value .. self:wrap(side_hl, "") .. default_hl |
| 37 | + else |
| 38 | + value = string.format(" %s ", value) |
| 39 | + end |
| 40 | + |
| 41 | + return value |
| 42 | + end |
| 43 | +end |
| 44 | + |
| 45 | +local MAX_DISPLAYED_WIDGETS = 3 |
| 46 | + |
| 47 | +function StatusLine:harpoon_widget(default_hl) |
| 48 | + local current_file = vim.fn.expand("%:p") |
| 49 | + local items = require("harpoon"):list().items |
| 50 | + |
| 51 | + local active_index = vim.iter(ipairs(items)):find( |
| 52 | + function(_, item) return vim.fn.fnamemodify(item.value, ":p") == current_file end |
| 53 | + ) |
| 54 | + |
| 55 | + local start_index = 1 |
| 56 | + if |
| 57 | + #items > MAX_DISPLAYED_WIDGETS |
| 58 | + and active_index ~= nil |
| 59 | + and active_index >= MAX_DISPLAYED_WIDGETS - 1 |
| 60 | + then |
| 61 | + start_index = math.max(math.min(active_index - 1, #items - MAX_DISPLAYED_WIDGETS + 1), 0) |
| 62 | + end |
| 63 | + |
| 64 | + local widgets = vim |
| 65 | + .iter(ipairs(items)) |
| 66 | + :skip(start_index - 1) |
| 67 | + :take(MAX_DISPLAYED_WIDGETS) |
| 68 | + :map(self:harpoon_item(default_hl, active_index)) |
| 69 | + :join("") |
| 70 | + |
| 71 | + if start_index ~= 1 then widgets = string.gsub(widgets, "^%s", "<") end |
| 72 | + if #items > MAX_DISPLAYED_WIDGETS and start_index ~= #items - MAX_DISPLAYED_WIDGETS + 1 then |
| 73 | + widgets = string.gsub(widgets, "%s$", ">") |
| 74 | + end |
| 75 | + |
| 76 | + return widgets |
| 77 | +end |
| 78 | + |
| 79 | +function StatusLine:wrap(hl, text) return "%#" .. hl .. "#" .. text end |
| 80 | + |
| 81 | +return StatusLine |
0 commit comments