From b99af28d132e41702794ec6ba5b37466fa17bc75 Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Sat, 3 Jan 2026 21:50:08 -0600 Subject: [PATCH 1/4] fix: better syntax, improved LuaLS type annotations Signed-off-by: Guennadi Maximov C --- lua/volt/color.lua | 159 ++++++++++++++++++----------------- lua/volt/draw.lua | 1 + lua/volt/events.lua | 17 ++-- lua/volt/highlights.lua | 9 +- lua/volt/init.lua | 30 ++++--- lua/volt/ui/components.lua | 19 +++-- lua/volt/ui/graphs/bar.lua | 2 +- lua/volt/ui/graphs/dot.lua | 2 +- lua/volt/ui/graphs/utils.lua | 7 +- lua/volt/ui/grid_col.lua | 4 +- lua/volt/ui/slider.lua | 4 +- lua/volt/ui/table.lua | 14 +-- lua/volt/utils.lua | 25 ++++-- 13 files changed, 168 insertions(+), 125 deletions(-) diff --git a/lua/volt/color.lua b/lua/volt/color.lua index 3015a6d..7f03b6f 100644 --- a/lua/volt/color.lua +++ b/lua/volt/color.lua @@ -26,14 +26,14 @@ local M = {} -- Convert a hex color value to RGB --- @param hex: The hex color value --- @return r: Red (0-255) --- @return g: Green (0-255) --- @return b: Blue (0-255) -M.hex2rgb = function(hex) +--- @param hex string: The hex color value +--- @return integer|nil r: Red (0-255) +--- @return integer|nil g: Green (0-255) +--- @return integer|nil b: Blue (0-255) +function M.hex2rgb(hex) local hash = string.sub(hex, 1, 1) == "#" if string.len(hex) ~= (7 - (hash and 0 or 1)) then - return nil + return end local r = tonumber(hex:sub(2 - (hash and 0 or 1), 3 - (hash and 0 or 1)), 16) @@ -43,27 +43,31 @@ M.hex2rgb = function(hex) end -- Convert a hex color value to RGB ratio --- @param hex: The hex color value --- @return r: Red (0-100) --- @return g: Green (0-100) --- @return b: Blue (0-100) -M.hex2rgb_ratio = function(hex) +--- @param hex string: The hex color value +--- @return integer r: Red (0-100) +--- @return integer g: Green (0-100) +--- @return integer b: Blue (0-100) +function M.hex2rgb_ratio(hex) local r, g, b = M.hex2rgb(hex) return math.floor(r / 255 * 100), math.floor(g / 255 * 100), math.floor(b / 255 * 100) end -- Convert an RGB color value to hex --- @param r: Red (0-255) --- @param g: Green (0-255) --- @param b: Blue (0-255) --- @return The hexadecimal string representation of the color -M.rgb2hex = function(r, g, b) +--- @param r number: Red (0-255) +--- @param g number: Green (0-255) +--- @param b number: Blue (0-255) +--- @return string hex: The hexadecimal string representation of the color +function M.rgb2hex(r, g, b) return string.format("#%02x%02x%02x", math.floor(r), math.floor(g), math.floor(b)) end -- Helper function to convert a HSL color value to RGB -- Not to be used directly, use M.hsl2rgb instead -M.hsl2rgb_helper = function(p, q, a) +--- @param p number +--- @param q number +--- @param a number +--- @return number +function M.hsl2rgb_helper(p, q, a) if a < 0 then a = a + 6 end @@ -72,48 +76,50 @@ M.hsl2rgb_helper = function(p, q, a) end if a < 1 then return (q - p) * a + p - elseif a < 3 then + end + if a < 3 then return q - elseif a < 4 then + end + if a < 4 then return (q - p) * (4 - a) + p - else - return p end + + return p end -- Convert a HSL color value to RGB --- @param h: Hue (0-360) --- @param s: Saturation (0-1) --- @param l: Lightness (0-1) --- @return r: Red (0-255) --- @return g: Green (0-255) --- @return b: Blue (0-255) -M.hsl2rgb = function(h, s, l) +--- @param h number: Hue (0-360) +--- @param s number: Saturation (0-1) +--- @param l number: Lightness (0-1) +--- @return integer r: Red (0-255) +--- @return integer g: Green (0-255) +--- @return integer b: Blue (0-255) +function M.hsl2rgb(h, s, l) local t1, t2, r, g, b - h = h / 60 if l <= 0.5 then t2 = l * (s + 1) else t2 = l + s - (l * s) end + h = h / 60 t1 = l * 2 - t2 r = M.hsl2rgb_helper(t1, t2, h + 2) * 255 g = M.hsl2rgb_helper(t1, t2, h) * 255 b = M.hsl2rgb_helper(t1, t2, h - 2) * 255 - return r, g, b + return math.floor(r), math.floor(g), math.floor(b) end -- Convert an RGB color value to HSL --- @param r Red (0-255) --- @param g Green (0-255) --- @param b Blue (0-255) --- @return h Hue (0-360) --- @return s Saturation (0-1) --- @return l Lightness (0-1) -M.rgb2hsl = function(r, g, b) +--- @param r number: Red (0-255) +--- @param g number: Green (0-255) +--- @param b number: Blue (0-255) +--- @return number h: Hue (0-360) +--- @return number s: Saturation (0-1) +--- @return number l: Lightness (0-1) +function M.rgb2hsl(r, g, b) local min, max, l, s, maxcolor, h r, g, b = r / 255, g / 255, b / 255 @@ -155,31 +161,30 @@ M.rgb2hsl = function(r, g, b) end -- Convert a hex color value to HSL --- @param hex: The hex color value --- @param h: Hue (0-360) --- @param s: Saturation (0-1) --- @param l: Lightness (0-1) -M.hex2hsl = function(hex) +--- @param hex string: The hex color value +--- @return number h: Hue (0-360) +--- @return number s: Saturation (0-1) +--- @return number l: Lightness (0-1) +function M.hex2hsl(hex) local r, g, b = M.hex2rgb(hex) return M.rgb2hsl(r, g, b) end -- Convert a HSL color value to hex --- @param h: Hue (0-360) --- @param s: Saturation (0-1) --- @param l: Lightness (0-1) --- @returns hex color value -M.hsl2hex = function(h, s, l) +--- @param h number: Hue (0-360) +--- @param s number: Saturation (0-1) +--- @param l number: Lightness (0-1) +--- @return string hex: The hex color value +function M.hsl2hex(h, s, l) local r, g, b = M.hsl2rgb(h, s, l) return M.rgb2hex(r, g, b) end -- Change the hue of a color by a given amount --- @param hex The hex color value --- @param amount The amount to change the hue. --- Negative values decrease the hue, positive values increase it. --- @return The hex color value -M.change_hex_hue = function(hex, percent) +--- @param hex string: The hex color value +--- @param percent integer: The amount to change the hue +--- @return string hex: The hex color value +function M.change_hex_hue(hex, percent) local h, s, l = M.hex2hsl(hex) -- Convert percentage to a degree shift local shift = (percent / 100) * 360 @@ -191,11 +196,10 @@ M.change_hex_hue = function(hex, percent) end -- Desaturate or saturate a color by a given percentage --- @param hex The hex color value --- @param percent The percentage to desaturate or saturate the color. --- Negative values desaturate the color, positive values saturate it --- @return The hex color value -M.change_hex_saturation = function(hex, percent) +--- @param hex string: The hex color value +--- @param percent number: The percentage to desaturate or saturate the color. +--- @return string hex: The hex color value +function M.change_hex_saturation(hex, percent) local h, s, l = M.hex2hsl(hex) s = s + (percent / 100) if s > 1 then @@ -208,11 +212,10 @@ M.change_hex_saturation = function(hex, percent) end -- Lighten or darken a color by a given percentage --- @param hex The hex color value --- @param percent The percentage to lighten or darken the color. --- Negative values darken the color, positive values lighten it --- @return The hex color value -M.change_hex_lightness = function(hex, percent) +--- @param hex string: The hex color value +--- @param percent number: The percentage to lighten or darken the color. +--- @return string hex: The hex color value +function M.change_hex_lightness(hex, percent) local h, s, l = M.hex2hsl(hex) l = l + (percent / 100) if l > 1 then @@ -225,11 +228,11 @@ M.change_hex_lightness = function(hex, percent) end -- Compute a gradient between two colors --- @param hex1 The first hex color value --- @param hex2 The second hex color value --- @param steps The number of steps to compute --- @return A table of hex color values -M.compute_gradient = function(hex1, hex2, steps) +--- @param hex1 string: The first hex color value +--- @param hex2 string: The second hex color value +--- @param steps integer: The number of steps to compute +--- @return string[] gradient: A table of hex color values +function M.compute_gradient(hex1, hex2, steps) local h1, s1, l1 = M.hex2hsl(hex1) local h2, s2, l2 = M.hex2hsl(hex2) local h, s, l @@ -249,10 +252,10 @@ M.compute_gradient = function(hex1, hex2, steps) end -- Generate complementary colors --- @param hex The hex color value (string) --- @param count The number of complementary colors to generate --- @return A table containing the complementary colors in hex format -M.hex2complementary = function(hex, count) +--- @param hex string: The hex color value (string) +--- @param count integer: The number of complementary colors to generate +--- @return string[] complementary_colors: A table containing the complementary colors in hex format +function M.hex2complementary(hex, count) local h, s, l = M.hex2hsl(hex) local complementary_colors = {} @@ -271,12 +274,11 @@ M.hex2complementary = function(hex, count) end -- Mix two colors with a given percentage. --- @param first The primary hex color. --- @param second The hex color you want to mix into the first color. --- @param strength The percentage of second color in the output. --- This needs to be a number between 0 - 100. --- @return The mixed color as a hex value -M.mix = function(first, second, strength) +--- @param first string: The primary hex color. +--- @param second string: The hex color you want to mix into the first color. +--- @param strength number: The percentage of second color in the output (0-100). +--- @return string mixed: The mixed color as a hex value +function M.mix(first, second, strength) if strength == nil then strength = 0.5 end @@ -291,7 +293,8 @@ M.mix = function(first, second, strength) if s == 0 then return first - elseif s == 1 then + end + if s == 1 then return second end diff --git a/lua/volt/draw.lua b/lua/volt/draw.lua index 6f4fc94..f36460d 100644 --- a/lua/volt/draw.lua +++ b/lua/volt/draw.lua @@ -2,6 +2,7 @@ local api = vim.api local set_extmark = api.nvim_buf_set_extmark local state = require "volt.state" +--- @param buf integer return function(buf, section) local v = state[buf] local section_lines = section.lines(buf) diff --git a/lua/volt/events.lua b/lua/volt/events.lua index be035c1..725d5c4 100644 --- a/lua/volt/events.lua +++ b/lua/volt/events.lua @@ -7,7 +7,7 @@ local MouseMove = vim.keycode "" local LeftMouse = vim.keycode "" local map = vim.keymap.set -local get_item_from_col = function(tb, n) +local function get_item_from_col(tb, n) for _, val in ipairs(tb) do if val.col_start <= n and val.col_end >= n then return val @@ -15,9 +15,12 @@ local get_item_from_col = function(tb, n) end end -local run_func = function(foo) +--- @param foo function|string +local function run_func(foo) + ---@cast foo function if type(foo) == "function" then foo() + ---@cast foo string elseif type(foo) == "string" then vim.cmd(foo) end @@ -56,6 +59,9 @@ local function set_cursormoved_autocmd(buf) }) end +--- @param buf integer +--- @param row integer +--- @param col integer local function handle_hover(buf_state, buf, row, col) -- clear old hovers! if buf_state.hovered_extmarks then @@ -81,7 +87,8 @@ local function handle_hover(buf_state, buf, row, col) end end -local buf_mappings = function(buf) +--- @param buf integer +local function buf_mappings(buf) set_cursormoved_autocmd(buf) map("n", "", function() @@ -101,7 +108,7 @@ local M = {} M.bufs = {} -M.add = function(val) +function M.add(val) if type(val) == "table" then for _, buf in ipairs(val) do table.insert(M.bufs, buf) @@ -113,7 +120,7 @@ M.add = function(val) end end -M.enable = function() +function M.enable() vim.g.extmarks_events = true vim.o.mousemev = true diff --git a/lua/volt/highlights.lua b/lua/volt/highlights.lua index a6f75e0..370b83a 100644 --- a/lua/volt/highlights.lua +++ b/lua/volt/highlights.lua @@ -2,9 +2,11 @@ local api = vim.api local lighten = require("volt.color").change_hex_lightness local bg = vim.o.bg +---@type table local highlights = {} -local hexadecimal_to_hex = function(hex) +--- @param hex? integer +local function hexadecimal_to_hex(hex) return "#" .. ("%06x"):format((hex == nil and 0 or hex)) end @@ -29,7 +31,9 @@ if vim.g.base46_cache then CommentFg = { fg = colors.light_grey }, } else + ---@type string|integer|nil local normal_bg = api.nvim_get_hl(0, { name = "Normal" }).bg + ---@type string|integer|nil local comment_fg = api.nvim_get_hl(0, { name = "comment" }).fg normal_bg = hexadecimal_to_hex(normal_bg) @@ -39,7 +43,8 @@ else local lighter_bg = lighten(normal_bg, 5) local black3_bg = lighten(normal_bg, 10) - local get_hl = function(name) + --- @param name string + local function get_hl(name) local data = api.nvim_get_hl(0, { name = name }) return hexadecimal_to_hex(data.fg) end diff --git a/lua/volt/init.lua b/lua/volt/init.lua index 2f75ea6..2f1e146 100644 --- a/lua/volt/init.lua +++ b/lua/volt/init.lua @@ -5,7 +5,9 @@ local draw = require "volt.draw" local state = require "volt.state" local utils = require "volt.utils" -local get_section = function(tb, name) +--- @param tb table +--- @param name string +local function get_section(tb, name) for _, value in ipairs(tb) do if value.name == name then return value @@ -13,7 +15,7 @@ local get_section = function(tb, name) end end -M.gen_data = function(data) +function M.gen_data(data) for _, info in ipairs(data) do state[info.buf] = {} @@ -39,7 +41,9 @@ M.gen_data = function(data) end end -M.redraw = function(buf, names) +--- @param buf integer +--- @param names "all"|string|string[] +function M.redraw(buf, names) local v = state[buf] if names == "all" then @@ -49,17 +53,21 @@ M.redraw = function(buf, names) return end + ---@cast names string if type(names) == "string" then draw(buf, get_section(v.layout, names)) return end + ---@cast names string[] for _, name in ipairs(names) do draw(buf, get_section(v.layout, name)) end end -M.set_empty_lines = function(buf, n, w) +--- @param buf integer +--- @param w integer +function M.set_empty_lines(buf, n, w) local empty_lines = {} for _ = 1, n, 1 do @@ -69,7 +77,7 @@ M.set_empty_lines = function(buf, n, w) api.nvim_buf_set_lines(buf, 0, -1, true, empty_lines) end -M.mappings = function(val) +function M.mappings(val) for _, buf in ipairs(val.bufs) do -- cycle bufs map("n", "", function() @@ -100,7 +108,8 @@ M.mappings = function(val) end end -M.run = function(buf, opts) +--- @param buf integer +function M.run(buf, opts) vim.bo[buf].filetype = "VoltWindow" if opts.custom_empty_lines then @@ -120,15 +129,16 @@ M.run = function(buf, opts) end end -M.toggle_func = function(open_func, ui_state) +function M.toggle_func(open_func, ui_state) if ui_state then open_func() - else - api.nvim_feedkeys("q", "x", false) + return end + + api.nvim_feedkeys("q", "x", false) end -M.close = function(buf) +function M.close(buf) if not buf then api.nvim_feedkeys("q", "x", false) return diff --git a/lua/volt/ui/components.lua b/lua/volt/ui/components.lua index 8f0bcca..a6ed846 100644 --- a/lua/volt/ui/components.lua +++ b/lua/volt/ui/components.lua @@ -11,7 +11,7 @@ local M = {} --- @param o CheckboxOptions The options for the checkbox. --- @return string[] A table containing the checkbox representation. -M.checkbox = function(o) +function M.checkbox(o) return { (o.active and (o.check or "") or (o.uncheck or "")) .. " " .. o.txt, o.active and (o.hlon or "String") or (o.hloff or "ExInactive"), @@ -27,7 +27,7 @@ end --- @param o ProgressOptions The options for the progress bar. --- @return table[] A table containing two elements: the active and inactive parts of the progress bar. -M.progressbar = function(o) +function M.progressbar(o) local opts = { icon = { on = "-", off = "-" }, hl = { on = "exred", off = "linenr" }, @@ -44,11 +44,14 @@ M.progressbar = function(o) } end -M.separator = function(char, w, hl) +--- @param char string +--- @param w integer +--- @param hl string|nil +function M.separator(char, w, hl) return { { string.rep(char or "─", w), hl or "linenr" } } end -M.grid_row = function(tb) +function M.grid_row(tb) local result = {} for _, lines in ipairs(tb) do for _, line in ipairs(lines) do @@ -59,7 +62,7 @@ M.grid_row = function(tb) return result end -M.line_w = function(line) +function M.line_w(line) local w = 0 for _, cell in ipairs(line) do @@ -71,7 +74,8 @@ M.line_w = function(line) return w end -M.border = function(lines, hl) +--- @param hl string|nil +function M.border(lines, hl) hl = hl or "linenr" local maxw = 0 @@ -101,7 +105,8 @@ M.border = function(lines, hl) table.insert(lines, { { "└" .. horiz_chars .. "┘", hl } }) end -M.hpad = function(line, w) +--- @param w integer +function M.hpad(line, w) local pad_w = w - M.line_w(line) for i, v in ipairs(line) do diff --git a/lua/volt/ui/graphs/bar.lua b/lua/volt/ui/graphs/bar.lua index 45fca95..3e5c417 100644 --- a/lua/volt/ui/graphs/bar.lua +++ b/lua/volt/ui/graphs/bar.lua @@ -1,6 +1,6 @@ local utils = require "volt.ui.graphs.utils" -local gen_graph = function(lines, val, opts) +local function gen_graph(lines, val, opts) local barchar = string.rep(opts.icon or "█", opts.w) local emptychar = string.rep(" ", opts.w) local gap = string.rep(" ", opts.gap) diff --git a/lua/volt/ui/graphs/dot.lua b/lua/volt/ui/graphs/dot.lua index d4d43e2..89a100e 100644 --- a/lua/volt/ui/graphs/dot.lua +++ b/lua/volt/ui/graphs/dot.lua @@ -6,7 +6,7 @@ local default_opts = { sidelabels = true, } -local gen_graph = function(lines, val, baropts) +local function gen_graph(lines, val, baropts) local icons = baropts.icons val = vim.tbl_map(function(x) diff --git a/lua/volt/ui/graphs/utils.lua b/lua/volt/ui/graphs/utils.lua index bbe5918..87c7e6d 100644 --- a/lua/volt/ui/graphs/utils.lua +++ b/lua/volt/ui/graphs/utils.lua @@ -1,6 +1,7 @@ local M = {} -M.gen_labels = function(format) +--- @param format nil|fun(n: integer): string +function M.gen_labels(format) local result = {} local max_strw = 0 @@ -13,7 +14,7 @@ M.gen_labels = function(format) num = tostring(i * 10) end - if #num > max_strw then + if num:len() > max_strw then max_strw = #num end @@ -27,7 +28,7 @@ M.gen_labels = function(format) return { labels = result, maxw = max_strw + 1 } end -M.footer_label = function(virt_txt, total_w, l_pad) +function M.footer_label(virt_txt, total_w, l_pad) local strw = vim.api.nvim_strwidth(virt_txt[1]) / 2 local pad = (total_w / 2 + l_pad) - strw return { { string.rep(" ", pad) }, virt_txt } diff --git a/lua/volt/ui/grid_col.lua b/lua/volt/ui/grid_col.lua index b3e02ea..f9832ae 100644 --- a/lua/volt/ui/grid_col.lua +++ b/lua/volt/ui/grid_col.lua @@ -1,6 +1,6 @@ local linew = require("volt.ui.components").line_w -local add_empty_space = function(lines, w, pad) +local function add_empty_space(lines, w, pad) for _, line in ipairs(lines) do table.insert(line, { string.rep(" ", w - linew(line) + pad) }) end @@ -8,7 +8,7 @@ local add_empty_space = function(lines, w, pad) return lines end -local append_tb = function(t1, t2) +local function append_tb(t1, t2) for _, v in ipairs(t2) do table.insert(t1, v) end diff --git a/lua/volt/ui/slider.lua b/lua/volt/ui/slider.lua index 3377108..97c9c8a 100644 --- a/lua/volt/ui/slider.lua +++ b/lua/volt/ui/slider.lua @@ -1,7 +1,7 @@ local api = vim.api local M = {} -M.val = function(w, left_txt, xpad, opts) +function M.val(w, left_txt, xpad, opts) opts = opts or {} local txt_len = vim.fn.strwidth(left_txt or "") w = w - txt_len - (opts.ratio and 5 or 0) @@ -15,7 +15,7 @@ M.val = function(w, left_txt, xpad, opts) return math.ceil((col / w) * 100) end -M.config = function(o) +function M.config(o) local line = {} local left_txt_len = vim.fn.strwidth(o.txt or "") diff --git a/lua/volt/ui/table.lua b/lua/volt/ui/table.lua index 5e1c0c1..02e5639 100644 --- a/lua/volt/ui/table.lua +++ b/lua/volt/ui/table.lua @@ -1,6 +1,6 @@ local virt_linew = require("volt.ui.components").line_w -local get_column_widths = function(tb, w) +local function get_column_widths(tb, w) local fit_w = type(w) == "string" local maxrow = #tb[1] local sum = 0 @@ -50,19 +50,23 @@ local border_chars = { corners_right = { top = "┐", bot = "┘", none = "┤" }, } -local table_border = function(points, row_type) +--- @param points integer[] +--- @param row_type string|nil +local function table_border(points, row_type) + row_type = row_type or "none" + local str = "" local tblen = #points for i, n in ipairs(points) do - local t_char = border_chars.mid[row_type or "none"] + local t_char = border_chars.mid[row_type] t_char = i == tblen and "" or t_char str = str .. string.rep("─", n + 1) .. t_char end - local l_char = border_chars.corners_left[row_type or "none"] - local r_char = border_chars.corners_right[row_type or "none"] + local l_char = border_chars.corners_left[row_type] + local r_char = border_chars.corners_right[row_type] return { { l_char .. str .. r_char, "linenr" } } end diff --git a/lua/volt/utils.lua b/lua/volt/utils.lua index 3c8f6fe..9521b36 100644 --- a/lua/volt/utils.lua +++ b/lua/volt/utils.lua @@ -4,7 +4,13 @@ local state = require "volt.state" local buf_i = 1 -M.cycle_bufs = function(bufs) +--- @param hex integer|nil +local function hexadecimal_to_hex(hex) + return "#" .. ("%06x"):format(hex == nil and 0 or hex) +end + +--- @param bufs integer[] +function M.cycle_bufs(bufs) buf_i = buf_i == #bufs and 1 or buf_i + 1 local new_buf = bufs[buf_i] @@ -13,7 +19,9 @@ M.cycle_bufs = function(bufs) api.nvim_set_current_win(a) end -M.cycle_clickables = function(buf, step) +--- @param buf integer +--- @param step number +function M.cycle_clickables(buf, step) local bufstate = state[buf] local lines = {} @@ -37,7 +45,7 @@ M.cycle_clickables = function(buf, step) end end -M.close = function(val) +function M.close(val) local event_bufs = require("volt.events").bufs for _, buf in ipairs(val.bufs) do @@ -67,13 +75,12 @@ M.close = function(val) vim.g.nvmark_hovered = nil end -M.get_hl = function(name) - local hexadecimal_to_hex = function(hex) - return "#" .. ("%06x"):format(hex == nil and 0 or hex) - end - - local hl = api.nvim_get_hl(0, { name = name }) +--- @param name string +--- @return vim.api.keyset.highlight result +function M.get_hl(name) + ---@type vim.api.keyset.highlight local result = {} + local hl = api.nvim_get_hl(0, { name = name }) if hl.fg ~= nil then result.fg = hexadecimal_to_hex(hl.fg) From a9e20cc961c68c8e92eadee3cf1fe14f1f4db7ff Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Thu, 12 Feb 2026 20:25:08 -0600 Subject: [PATCH 2/4] fix: more LuaLS annotations Signed-off-by: Guennadi Maximov C --- lua/volt/init.lua | 12 ++++++++++++ lua/volt/ui/components.lua | 14 +++++++++++--- lua/volt/ui/grid_col.lua | 10 ++++++++-- lua/volt/ui/table.lua | 11 +++++++++-- lua/volt/ui/tabs.lua | 6 +++++- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/lua/volt/init.lua b/lua/volt/init.lua index 2f1e146..9ecd5b6 100644 --- a/lua/volt/init.lua +++ b/lua/volt/init.lua @@ -1,3 +1,14 @@ +--- @class VoltData.Layout +--- @field name string +--- @field lines fun(buf?: integer): (string[][][]|string[][]) +--- @field row? integer + +--- @class VoltData +--- @field buf integer +--- @field xpad integer +--- @field ns integer +--- @field layout VoltData.Layout[] + local M = {} local api = vim.api local map = vim.keymap.set @@ -15,6 +26,7 @@ local function get_section(tb, name) end end +--- @param data VoltData[] function M.gen_data(data) for _, info in ipairs(data) do state[info.buf] = {} diff --git a/lua/volt/ui/components.lua b/lua/volt/ui/components.lua index a6ed846..2ebd284 100644 --- a/lua/volt/ui/components.lua +++ b/lua/volt/ui/components.lua @@ -26,7 +26,7 @@ end --- @field hl? table active/inactive highlights, ex: { on = "", off = ""} --- @param o ProgressOptions The options for the progress bar. ---- @return table[] A table containing two elements: the active and inactive parts of the progress bar. +--- @return string[][] bar A table containing two elements: the active and inactive parts of the progress bar. function M.progressbar(o) local opts = { icon = { on = "-", off = "-" }, @@ -47,12 +47,15 @@ end --- @param char string --- @param w integer --- @param hl string|nil +--- @return string[][] separator function M.separator(char, w, hl) return { { string.rep(char or "─", w), hl or "linenr" } } end +--- @param tb (string[][][]|string[][])[] +--- @return string[][][]|string[][] row function M.grid_row(tb) - local result = {} + local result = {} ---@type string[][][]|string[][] for _, lines in ipairs(tb) do for _, line in ipairs(lines) do table.insert(result, line) @@ -62,6 +65,8 @@ function M.grid_row(tb) return result end +--- @param line string[][] +--- @return integer w function M.line_w(line) local w = 0 @@ -74,12 +79,13 @@ function M.line_w(line) return w end +--- @param lines string[][][] --- @param hl string|nil function M.border(lines, hl) hl = hl or "linenr" local maxw = 0 - local line_widths = {} + local line_widths = {} ---@type integer[] for _, line in ipairs(lines) do local linew = M.line_w(line) @@ -105,7 +111,9 @@ function M.border(lines, hl) table.insert(lines, { { "└" .. horiz_chars .. "┘", hl } }) end +--- @param line string[][] --- @param w integer +--- @return string[][] line function M.hpad(line, w) local pad_w = w - M.line_w(line) diff --git a/lua/volt/ui/grid_col.lua b/lua/volt/ui/grid_col.lua index f9832ae..88efa90 100644 --- a/lua/volt/ui/grid_col.lua +++ b/lua/volt/ui/grid_col.lua @@ -1,5 +1,8 @@ local linew = require("volt.ui.components").line_w +--- @param lines string[][][]|string[][] +--- @param w integer +--- @param pad integer local function add_empty_space(lines, w, pad) for _, line in ipairs(lines) do table.insert(line, { string.rep(" ", w - linew(line) + pad) }) @@ -8,15 +11,18 @@ local function add_empty_space(lines, w, pad) return lines end +--- @param t1 any[] +--- @param t2 any[] local function append_tb(t1, t2) for _, v in ipairs(t2) do table.insert(t1, v) end end +--- @param columns { lines: string[][][]|string[][], w: integer, pad?: integer }[] return function(columns) - local ui_sections = {} - local empty_space = {} + local ui_sections = {} ---@type (string[][][]|string[][])[] + local empty_space = {} ---@type string[][] local h = 0 for _, column in ipairs(columns) do diff --git a/lua/volt/ui/table.lua b/lua/volt/ui/table.lua index 02e5639..8256796 100644 --- a/lua/volt/ui/table.lua +++ b/lua/volt/ui/table.lua @@ -1,5 +1,7 @@ local virt_linew = require("volt.ui.components").line_w +--- @param tb string[][][]|string[][] +--- @param w string|integer local function get_column_widths(tb, w) local fit_w = type(w) == "string" local maxrow = #tb[1] @@ -71,10 +73,15 @@ local function table_border(points, row_type) return { { l_char .. str .. r_char, "linenr" } } end +--- @param tbl string[][][]|string[][] +--- @param w string|integer +--- @param header_hl? string +--- @param title? string +--- @return string[][][]|string[][] lines return function(tbl, w, header_hl, title) local col_widths = get_column_widths(tbl, w) - local lines = {} + local lines = {} ---@type string[][][]|string[][] local tb_border_up = table_border(col_widths, "top") local tb_border_middle = table_border(col_widths) local tb_border_down = table_border(col_widths, "bot") @@ -83,7 +90,7 @@ return function(tbl, w, header_hl, title) local end_i = #tbl for line_i, row in ipairs(tbl) do - local line = {} + local line = {} ---@type string[][] for i, v in ipairs(row) do local maxlen = col_widths[i] diff --git a/lua/volt/ui/tabs.lua b/lua/volt/ui/tabs.lua index 824bfa0..fb30b76 100644 --- a/lua/volt/ui/tabs.lua +++ b/lua/volt/ui/tabs.lua @@ -1,3 +1,7 @@ +--- @param data string[] +--- @param w integer +--- @param opts { active: string, hlon?: string, hloff?: string } +--- @return string[][][]|string[][] lines return function(data, w, opts) local total_str_w = -1 -- cuz last tab doesnt need gap @@ -8,7 +12,7 @@ return function(data, w, opts) end end - local lines = { {}, {}, {} } + local lines = { {}, {}, {} } ---@type string[][][]|string[][] local datalen = #data for i, v in ipairs(data) do From 2cad3c13d85b4997a2269b9866ebe95ee3287fcb Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Sat, 4 Apr 2026 20:12:09 -0600 Subject: [PATCH 3/4] feat: more LuaLS annotations Signed-off-by: Guennadi Maximov C --- lua/volt/draw.lua | 1 + lua/volt/events.lua | 4 ++++ lua/volt/init.lua | 7 +++++-- lua/volt/state.lua | 12 +++++++++++- lua/volt/ui/graphs/bar.lua | 9 +++++---- lua/volt/ui/grid_col.lua | 9 +++++---- lua/volt/ui/table.lua | 6 +++--- 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/lua/volt/draw.lua b/lua/volt/draw.lua index f36460d..1ee4145 100644 --- a/lua/volt/draw.lua +++ b/lua/volt/draw.lua @@ -3,6 +3,7 @@ local set_extmark = api.nvim_buf_set_extmark local state = require "volt.state" --- @param buf integer +--- @param section VoltData.Layout return function(buf, section) local v = state[buf] local section_lines = section.lines(buf) diff --git a/lua/volt/events.lua b/lua/volt/events.lua index 725d5c4..5bbb311 100644 --- a/lua/volt/events.lua +++ b/lua/volt/events.lua @@ -26,6 +26,10 @@ local function run_func(foo) end end +---@param buf integer +---@param row integer +---@param col integer +---@param win integer local function handle_click(buf, by, row, col, win) local v = nvmark_state[buf] diff --git a/lua/volt/init.lua b/lua/volt/init.lua index 9ecd5b6..c164e59 100644 --- a/lua/volt/init.lua +++ b/lua/volt/init.lua @@ -2,6 +2,7 @@ --- @field name string --- @field lines fun(buf?: integer): (string[][][]|string[][]) --- @field row? integer +--- @field col_start? integer --- @class VoltData --- @field buf integer @@ -9,6 +10,7 @@ --- @field ns integer --- @field layout VoltData.Layout[] +---@class Volt local M = {} local api = vim.api local map = vim.keymap.set @@ -16,8 +18,9 @@ local draw = require "volt.draw" local state = require "volt.state" local utils = require "volt.utils" ---- @param tb table +--- @param tb VoltData.Layout[] --- @param name string +--- @return VoltData.Layout | nil local function get_section(tb, name) for _, value in ipairs(tb) do if value.name == name then @@ -65,8 +68,8 @@ function M.redraw(buf, names) return end - ---@cast names string if type(names) == "string" then + ---@cast names string draw(buf, get_section(v.layout, names)) return end diff --git a/lua/volt/state.lua b/lua/volt/state.lua index a564707..04a499d 100644 --- a/lua/volt/state.lua +++ b/lua/volt/state.lua @@ -1 +1,11 @@ -return {} +---@class Volt.State +---@field clickables? table +---@field hoverables? table +---@field xpad? integer +---@field ns? integer +---@field buf? integer +---@field layout? VoltData.Layout +---@field h? integer +---@field hovered_extmarks? string[] + +return {} ---@type Volt.State[] diff --git a/lua/volt/ui/graphs/bar.lua b/lua/volt/ui/graphs/bar.lua index 3e5c417..1e94653 100644 --- a/lua/volt/ui/graphs/bar.lua +++ b/lua/volt/ui/graphs/bar.lua @@ -29,19 +29,20 @@ local function gen_graph(lines, val, opts) end end +---@return string[][][] lines return function(data) - local lines = {} + local lines = {} ---@type string[][][] local total_w = #data.val * (data.baropts.w + data.baropts.gap) + 1 - local bottom_line = { "└" .. string.rep("─", total_w), "linenr" } + local bottom_line = { "└" .. ("─"):rep(total_w), "linenr" } local sidelabels_data = utils.gen_labels(data.format_labels) local sidelabels = sidelabels_data.labels - local l_pad = { string.rep(" ", sidelabels_data.maxw) } + local l_pad = { (" "):rep(sidelabels_data.maxw) } for i = 10, 1, -1 do - local line = {} + local line = {} ---@type string[][] table.insert(line, { sidelabels[i], "commentfg" }) table.insert(line, { " │ ", "linenr" }) table.insert(lines, line) diff --git a/lua/volt/ui/grid_col.lua b/lua/volt/ui/grid_col.lua index 88efa90..304b95c 100644 --- a/lua/volt/ui/grid_col.lua +++ b/lua/volt/ui/grid_col.lua @@ -19,16 +19,17 @@ local function append_tb(t1, t2) end end ---- @param columns { lines: string[][][]|string[][], w: integer, pad?: integer }[] +--- @param columns { lines: string[][][], w: integer, pad?: integer }[] +--- @return string[][][] result return function(columns) - local ui_sections = {} ---@type (string[][][]|string[][])[] + local ui_sections = {} ---@type string[][][]|string[][] local empty_space = {} ---@type string[][] local h = 0 for _, column in ipairs(columns) do local pad = column.pad or 0 table.insert(ui_sections, add_empty_space(column.lines, column.w, pad)) - table.insert(empty_space, { { string.rep(" ", column.w + pad) } }) + table.insert(empty_space, { { (" "):rep(column.w + pad) } }) local col_h = #column.lines if h < col_h then @@ -36,7 +37,7 @@ return function(columns) end end - local result = {} + local result = {} ---@type string[][][] for i = 1, h do if not result[i] then diff --git a/lua/volt/ui/table.lua b/lua/volt/ui/table.lua index 8256796..17280ba 100644 --- a/lua/volt/ui/table.lua +++ b/lua/volt/ui/table.lua @@ -1,6 +1,6 @@ local virt_linew = require("volt.ui.components").line_w ---- @param tb string[][][]|string[][] +--- @param tb string[][][][]|string[][][]|string[][] --- @param w string|integer local function get_column_widths(tb, w) local fit_w = type(w) == "string" @@ -73,10 +73,10 @@ local function table_border(points, row_type) return { { l_char .. str .. r_char, "linenr" } } end ---- @param tbl string[][][]|string[][] +--- @param tbl string[][][][]|string[][][]|string[][] --- @param w string|integer --- @param header_hl? string ---- @param title? string +--- @param title? string[]|string --- @return string[][][]|string[][] lines return function(tbl, w, header_hl, title) local col_widths = get_column_widths(tbl, w) From b93c29b9f0b33eeac42a5db7337113fd48cc1448 Mon Sep 17 00:00:00 2001 From: Guennadi Maximov C Date: Fri, 17 Jul 2026 08:54:27 -0600 Subject: [PATCH 4/4] fix: maintenance Signed-off-by: Guennadi Maximov C --- .stylua.toml | 3 +- lua/volt/color.lua | 100 +++++++++-------------------------- lua/volt/draw.lua | 9 +--- lua/volt/events.lua | 72 ++++++++++++------------- lua/volt/highlights.lua | 38 ++++++------- lua/volt/init.lua | 100 ++++++++++++++++------------------- lua/volt/state.lua | 10 ++-- lua/volt/ui/components.lua | 44 +++++++-------- lua/volt/ui/graphs/bar.lua | 13 +++-- lua/volt/ui/graphs/dot.lua | 18 +++---- lua/volt/ui/graphs/init.lua | 4 +- lua/volt/ui/graphs/utils.lua | 30 +++++------ lua/volt/ui/grid_col.lua | 15 +++--- lua/volt/ui/init.lua | 18 +++---- lua/volt/ui/slider.lua | 37 ++++--------- lua/volt/ui/table.lua | 34 ++++-------- lua/volt/ui/tabs.lua | 6 +-- lua/volt/utils.lua | 47 +++++++--------- 18 files changed, 228 insertions(+), 370 deletions(-) diff --git a/.stylua.toml b/.stylua.toml index ecb6dca..c401612 100644 --- a/.stylua.toml +++ b/.stylua.toml @@ -3,4 +3,5 @@ line_endings = "Unix" indent_type = "Spaces" indent_width = 2 quote_style = "AutoPreferDouble" -call_parentheses = "None" +call_parentheses = "Always" +syntax = "LuaJIT" diff --git a/lua/volt/color.lua b/lua/volt/color.lua index 7f03b6f..57ffab9 100644 --- a/lua/volt/color.lua +++ b/lua/volt/color.lua @@ -23,16 +23,17 @@ -- All credits to https://github.com/LeonHeidelbach for making this! -- 90% of functions are written by him +---@class volt.Color local M = {} -- Convert a hex color value to RGB --- @param hex string: The hex color value ---- @return integer|nil r: Red (0-255) ---- @return integer|nil g: Green (0-255) ---- @return integer|nil b: Blue (0-255) +--- @return integer|nil|? r: Red (0-255) +--- @return integer|nil|? g: Green (0-255) +--- @return integer|nil|? b: Blue (0-255) function M.hex2rgb(hex) - local hash = string.sub(hex, 1, 1) == "#" - if string.len(hex) ~= (7 - (hash and 0 or 1)) then + local hash = hex:sub(1, 1) == "#" + if hex:len() ~= (7 - (hash and 0 or 1)) then return end @@ -58,7 +59,7 @@ end --- @param b number: Blue (0-255) --- @return string hex: The hexadecimal string representation of the color function M.rgb2hex(r, g, b) - return string.format("#%02x%02x%02x", math.floor(r), math.floor(g), math.floor(b)) + return ("#%02x%02x%02x"):format(math.floor(r), math.floor(g), math.floor(b)) end -- Helper function to convert a HSL color value to RGB @@ -83,7 +84,6 @@ function M.hsl2rgb_helper(p, q, a) if a < 4 then return (q - p) * (4 - a) + p end - return p end @@ -96,7 +96,6 @@ end --- @return integer b: Blue (0-255) function M.hsl2rgb(h, s, l) local t1, t2, r, g, b - if l <= 0.5 then t2 = l * (s + 1) else @@ -120,43 +119,25 @@ end --- @return number s: Saturation (0-1) --- @return number l: Lightness (0-1) function M.rgb2hsl(r, g, b) - local min, max, l, s, maxcolor, h r, g, b = r / 255, g / 255, b / 255 - min = math.min(r, g, b) - max = math.max(r, g, b) - maxcolor = 1 + (max == b and 2 or (max == g and 1 or 0)) + local min = math.min(r, g, b) + local max = math.max(r, g, b) + local maxcolor = 1 + (max == b and 2 or (max == g and 1 or 0)) - if maxcolor == 1 then - h = (g - b) / (max - min) - elseif maxcolor == 2 then - h = 2 + (b - r) / (max - min) - elseif maxcolor == 3 then - h = 4 + (r - g) / (max - min) - end + local h = maxcolor == 1 and ((g - b) / (max - min)) + or (maxcolor == 2 and (2 + (b - r) / (max - min)) or (maxcolor == 3 and (4 + (r - g) / (max - min)) or nil)) if not rawequal(type(h), "number") then h = 0 end - h = h * 60 - if h < 0 then h = h + 360 end - l = (min + max) / 2 - - if min == max then - s = 0 - else - if l < 0.5 then - s = (max - min) / (max + min) - else - s = (max - min) / (2 - max - min) - end - end - + local l = (min + max) / 2 + local s = min == max and 0 or (l < 0.5 and ((max - min) / (max + min)) or ((max - min) / (2 - max - min))) return h, s, l end @@ -187,8 +168,7 @@ end function M.change_hex_hue(hex, percent) local h, s, l = M.hex2hsl(hex) -- Convert percentage to a degree shift - local shift = (percent / 100) * 360 - h = (h + shift) % 360 + h = (h + (percent / 100) * 360) % 360 if h < 0 then h = h + 360 end @@ -202,12 +182,7 @@ end function M.change_hex_saturation(hex, percent) local h, s, l = M.hex2hsl(hex) s = s + (percent / 100) - if s > 1 then - s = 1 - end - if s < 0 then - s = 0 - end + s = s > 1 and 1 or (s < 0 and 0 or s) return M.hsl2hex(h, s, l) end @@ -218,12 +193,7 @@ end function M.change_hex_lightness(hex, percent) local h, s, l = M.hex2hsl(hex) l = l + (percent / 100) - if l > 1 then - l = 1 - end - if l < 0 then - l = 0 - end + l = l > 1 and 1 or (l < 0 and 0 or l) return M.hsl2hex(h, s, l) end @@ -235,12 +205,11 @@ end function M.compute_gradient(hex1, hex2, steps) local h1, s1, l1 = M.hex2hsl(hex1) local h2, s2, l2 = M.hex2hsl(hex2) - local h, s, l + local h, s, l ---@type number, number, number local h_step = (h2 - h1) / (steps - 1) local s_step = (s2 - s1) / (steps - 1) local l_step = (l2 - l1) / (steps - 1) - local gradient = {} - + local gradient = {} ---@type string[] for i = 0, steps - 1 do h = h1 + (h_step * i) s = s1 + (s_step * i) @@ -257,17 +226,11 @@ end --- @return string[] complementary_colors: A table containing the complementary colors in hex format function M.hex2complementary(hex, count) local h, s, l = M.hex2hsl(hex) - local complementary_colors = {} - - -- Calculate the hue for the complementary color (180 degrees shift) + local complementary_colors = {} ---@type string[] local complementary_hue = (h + 180) % 360 - - -- Create a gradient of colors by slightly varying the complementary hue local hue_step = 360 / count for i = 0, count - 1 do - local new_hue = (complementary_hue + (hue_step * i)) % 360 - local complementary_hex = M.hsl2hex(new_hue, s, l) - table.insert(complementary_colors, complementary_hex) + table.insert(complementary_colors, M.hsl2hex((complementary_hue + (hue_step * i)) % 360, s, l)) end return complementary_colors @@ -276,33 +239,20 @@ end -- Mix two colors with a given percentage. --- @param first string: The primary hex color. --- @param second string: The hex color you want to mix into the first color. ---- @param strength number: The percentage of second color in the output (0-100). +--- @param strength? number: The percentage of second color in the output (0-100). --- @return string mixed: The mixed color as a hex value function M.mix(first, second, strength) - if strength == nil then - strength = 0.5 - end - - local s = strength / 100 + local s = (strength or 0.5) / 100 local r1, g1, b1 = M.hex2rgb(first) local r2, g2, b2 = M.hex2rgb(second) - - if r1 == nil or r2 == nil then - return first - end - - if s == 0 then + if not (r1 and r2) or s == 0 then return first end if s == 1 then return second end - local r3 = r1 * (1 - s) + r2 * s - local g3 = g1 * (1 - s) + g2 * s - local b3 = b1 * (1 - s) + b2 * s - - return M.rgb2hex(r3, g3, b3) + return M.rgb2hex(r1 * (1 - s) + r2 * s, g1 * (1 - s) + g2 * s, b1 * (1 - s) + b2 * s) end return M diff --git a/lua/volt/draw.lua b/lua/volt/draw.lua index 1ee4145..cabe9d3 100644 --- a/lua/volt/draw.lua +++ b/lua/volt/draw.lua @@ -1,11 +1,7 @@ -local api = vim.api -local set_extmark = api.nvim_buf_set_extmark -local state = require "volt.state" - --- @param buf integer --- @param section VoltData.Layout return function(buf, section) - local v = state[buf] + local v = require("volt.state")[buf] local section_lines = section.lines(buf) local xpad = section.col_start or v.xpad or 0 @@ -22,7 +18,6 @@ return function(buf, section) if mark[3] then local virt = { col_start = col - strlen, col_end = col, actions = mark[3] } - if strlen == 1 and #mark[1] == 1 then virt.col_end = virt.col_start end @@ -48,6 +43,6 @@ return function(buf, section) for line, marks in ipairs(section_lines) do local row = line + section.row local opts = { virt_text_win_col = xpad, virt_text = marks, id = row } - set_extmark(buf, v.ns, row - 1, 0, opts) + vim.api.nvim_buf_set_extmark(buf, v.ns, row - 1, 0, opts) end end diff --git a/lua/volt/events.lua b/lua/volt/events.lua index 5bbb311..9b1ffbf 100644 --- a/lua/volt/events.lua +++ b/lua/volt/events.lua @@ -1,12 +1,8 @@ -local api = vim.api -local nvmark_state = require "volt.state" -local redraw = require("volt").redraw -local cycle_clickables = require("volt.utils").cycle_clickables - -local MouseMove = vim.keycode "" -local LeftMouse = vim.keycode "" -local map = vim.keymap.set +local nvmark_state = require("volt.state") +local MouseMove = vim.keycode("") +local LeftMouse = vim.keycode("") +---@param n integer local function get_item_from_col(tb, n) for _, val in ipairs(tb) do if val.col_start <= n and val.col_end >= n then @@ -17,45 +13,43 @@ end --- @param foo function|string local function run_func(foo) - ---@cast foo function if type(foo) == "function" then foo() - ---@cast foo string elseif type(foo) == "string" then vim.cmd(foo) end end ---@param buf integer ----@param row integer ----@param col integer ----@param win integer +---@param by? string +---@param row? integer +---@param col? integer +---@param win? integer local function handle_click(buf, by, row, col, win) - local v = nvmark_state[buf] - if not row then - local cursor_pos = api.nvim_win_get_cursor(0) + local cursor_pos = vim.api.nvim_win_get_cursor(0) row, col = cursor_pos[1], cursor_pos[2] end + local v = nvmark_state[buf] if v.clickables[row] then local virt = get_item_from_col(v.clickables[row], col) - if virt and (by ~= "keyb" or virt.ui_type == "slider") then local actions = virt.actions run_func(type(actions) == "table" and actions.click or actions) end - if win and api.nvim_win_is_valid(win) then + if win and vim.api.nvim_win_is_valid(win) then vim.schedule(function() - api.nvim_win_set_cursor(win, { 1, 1 }) + vim.api.nvim_win_set_cursor(win, { 1, 1 }) end) end end end +---@param buf integer local function set_cursormoved_autocmd(buf) - api.nvim_create_autocmd("CursorMoved", { + vim.api.nvim_create_autocmd("CursorMoved", { buffer = buf, callback = function() handle_click(buf, "keyb") @@ -63,6 +57,7 @@ local function set_cursormoved_autocmd(buf) }) end +--- @param buf_state Volt.State --- @param buf integer --- @param row integer --- @param col integer @@ -70,23 +65,20 @@ local function handle_hover(buf_state, buf, row, col) -- clear old hovers! if buf_state.hovered_extmarks then vim.g.nvmark_hovered = nil - redraw(buf, buf_state.hovered_extmarks) + require("volt").redraw(buf, buf_state.hovered_extmarks) buf_state.hovered_extmarks = nil end if buf_state.hoverables[row] then local virt = get_item_from_col(buf_state.hoverables[row], col) - if virt and virt.hover then - local hover = virt.hover - - if hover.callback then - hover.callback() + if virt.hover.callback then + virt.hover.callback() end - vim.g.nvmark_hovered = hover.id or nil - redraw(buf, hover.redraw) - buf_state.hovered_extmarks = hover.redraw + vim.g.nvmark_hovered = virt.hover.id or nil + require("volt").redraw(buf, virt.hover.redraw) + buf_state.hovered_extmarks = virt.hover.redraw end end end @@ -95,33 +87,37 @@ end local function buf_mappings(buf) set_cursormoved_autocmd(buf) - map("n", "", function() + vim.keymap.set("n", "", function() handle_click(buf) end, { buffer = buf }) - map("n", "", function() - cycle_clickables(buf, 1) + vim.keymap.set("n", "", function() + require("volt.utils").cycle_clickables(buf, 1) end, { buffer = buf }) - map("n", "", function() - cycle_clickables(buf, -1) + vim.keymap.set("n", "", function() + require("volt.utils").cycle_clickables(buf, -1) end, { buffer = buf }) end +---@class volt.Events +---@field bufs integer[] local M = {} M.bufs = {} +---@param val integer[]|integer function M.add(val) if type(val) == "table" then for _, buf in ipairs(val) do table.insert(M.bufs, buf) buf_mappings(buf) end - else - table.insert(M.bufs, val) - buf_mappings(val) + return end + + table.insert(M.bufs, val) + buf_mappings(val) end function M.enable() @@ -131,7 +127,7 @@ function M.enable() vim.on_key(function(key) local mousepos = vim.fn.getmousepos() local cur_win = mousepos.winid - local cur_buf = api.nvim_win_get_buf(cur_win) + local cur_buf = vim.api.nvim_win_get_buf(cur_win) if vim.tbl_contains(M.bufs, cur_buf) then local row, col = mousepos.line, mousepos.column - 1 diff --git a/lua/volt/highlights.lua b/lua/volt/highlights.lua index 370b83a..06f5770 100644 --- a/lua/volt/highlights.lua +++ b/lua/volt/highlights.lua @@ -1,15 +1,18 @@ -local api = vim.api local lighten = require("volt.color").change_hex_lightness -local bg = vim.o.bg ----@type table -local highlights = {} +local highlights = {} ---@type table --- @param hex? integer local function hexadecimal_to_hex(hex) return "#" .. ("%06x"):format((hex == nil and 0 or hex)) end +--- @param name string +--- @return string hl +local function get_hl(name) + return hexadecimal_to_hex(vim.api.nvim_get_hl(0, { name = name }).fg) +end + if vim.g.base46_cache then local colors = dofile(vim.g.base46_cache .. "colors") @@ -27,28 +30,17 @@ if vim.g.base46_cache then ExBlack3Bg = { bg = colors.one_bg2 }, ExBlack3Border = { bg = colors.one_bg2, fg = colors.one_bg2 }, - ExLightGrey = { fg = lighten(colors.grey, bg == "dark" and 35 or -35) }, + ExLightGrey = { fg = lighten(colors.grey, vim.o.bg == "dark" and 35 or -35) }, CommentFg = { fg = colors.light_grey }, } else - ---@type string|integer|nil - local normal_bg = api.nvim_get_hl(0, { name = "Normal" }).bg - ---@type string|integer|nil - local comment_fg = api.nvim_get_hl(0, { name = "comment" }).fg - - normal_bg = hexadecimal_to_hex(normal_bg) - comment_fg = hexadecimal_to_hex(comment_fg) + local normal_bg = hexadecimal_to_hex(vim.api.nvim_get_hl(0, { name = "Normal" }).bg) + local comment_fg = hexadecimal_to_hex(vim.api.nvim_get_hl(0, { name = "comment" }).fg) local darker_bg = lighten(normal_bg, -3) local lighter_bg = lighten(normal_bg, 5) local black3_bg = lighten(normal_bg, 10) - --- @param name string - local function get_hl(name) - local data = api.nvim_get_hl(0, { name = name }) - return hexadecimal_to_hex(data.fg) - end - highlights = { ExDarkBg = { bg = darker_bg }, ExDarkBorder = { bg = darker_bg, fg = darker_bg }, @@ -56,14 +48,14 @@ else ExBlack2Bg = { bg = lighter_bg }, ExBlack2Border = { bg = lighter_bg, fg = lighter_bg }, - ExRed = { fg = get_hl "removed" }, - ExYellow = { fg = get_hl "changed" }, - ExBlue = { fg = get_hl "Function" }, - ExGreen = { fg = get_hl "added" }, + ExRed = { fg = get_hl("removed") }, + ExYellow = { fg = get_hl("changed") }, + ExBlue = { fg = get_hl("Function") }, + ExGreen = { fg = get_hl("added") }, ExBlack3Bg = { bg = black3_bg }, CommentFg = { fg = comment_fg }, ExBlack3Border = { bg = black3_bg, fg = black3_bg }, - ExLightGrey = { fg = lighten(comment_fg, bg == "dark" and 20 or -20) }, + ExLightGrey = { fg = lighten(comment_fg, vim.o.bg == "dark" and 20 or -20) }, } end diff --git a/lua/volt/init.lua b/lua/volt/init.lua index c164e59..7900596 100644 --- a/lua/volt/init.lua +++ b/lua/volt/init.lua @@ -1,26 +1,24 @@ --- @class VoltData.Layout ---- @field name string +--- @field col_start? integer --- @field lines fun(buf?: integer): (string[][][]|string[][]) +--- @field name string --- @field row? integer ---- @field col_start? integer --- @class VoltData --- @field buf integer ---- @field xpad integer ---- @field ns integer --- @field layout VoltData.Layout[] +--- @field ns integer +--- @field xpad integer ---@class Volt local M = {} -local api = vim.api -local map = vim.keymap.set -local draw = require "volt.draw" -local state = require "volt.state" -local utils = require "volt.utils" +local draw = require("volt.draw") +local state = require("volt.state") +local utils = require("volt.utils") --- @param tb VoltData.Layout[] --- @param name string ---- @return VoltData.Layout | nil +--- @return VoltData.Layout|nil|? local function get_section(tb, name) for _, value in ipairs(tb) do if value.name == name then @@ -45,7 +43,6 @@ function M.gen_data(data) v.buf = buf local row = 0 - for _, value in ipairs(v.layout) do local lines = value.lines(buf) value.row = row @@ -57,111 +54,104 @@ function M.gen_data(data) end --- @param buf integer ---- @param names "all"|string|string[] +--- @param names string[]|string|"all" function M.redraw(buf, names) local v = state[buf] - if names == "all" then for _, section in ipairs(v.layout) do draw(buf, section) end - return - end - - if type(names) == "string" then - ---@cast names string + elseif type(names) == "string" then draw(buf, get_section(v.layout, names)) - return - end - - ---@cast names string[] - for _, name in ipairs(names) do - draw(buf, get_section(v.layout, name)) + else + for _, name in ipairs(names) do + draw(buf, get_section(v.layout, name)) + end end end --- @param buf integer +--- @param n integer --- @param w integer function M.set_empty_lines(buf, n, w) - local empty_lines = {} - + local empty_lines = {} ---@type string[] for _ = 1, n, 1 do - table.insert(empty_lines, string.rep(" ", w)) + table.insert(empty_lines, (" "):rep(w)) end - api.nvim_buf_set_lines(buf, 0, -1, true, empty_lines) + vim.api.nvim_buf_set_lines(buf, 0, -1, true, empty_lines) end function M.mappings(val) for _, buf in ipairs(val.bufs) do -- cycle bufs - map("n", "", function() + vim.keymap.set("n", "", function() utils.cycle_bufs(val.bufs) end, { buffer = buf }) -- close - map("n", "q", function() + vim.keymap.set("n", "q", function() utils.close(val) end, { buffer = buf }) - map("n", "", function() + vim.keymap.set("n", "", function() utils.close(val) end, { buffer = buf }) - if val.winclosed_event then - vim.api.nvim_create_autocmd("WinClosed", { - buffer = buf, - callback = function() + if not val.winclosed_event then + return + end + vim.api.nvim_create_autocmd("WinClosed", { + buffer = buf, + callback = function() + if state[buf] then vim.schedule(function() - if state[buf] then - utils.close(val) - end + utils.close(val) end) - end, - }) - end + end + end, + }) end end --- @param buf integer function M.run(buf, opts) - vim.bo[buf].filetype = "VoltWindow" - + vim.api.nvim_set_option_value("filetype", "VoltWindow", { buf = buf }) if opts.custom_empty_lines then opts.custom_empty_lines() else M.set_empty_lines(buf, opts.h, opts.w) end - require "volt.highlights" + require("volt.highlights") M.redraw(buf, "all") - api.nvim_set_option_value("modifiable", false, { buf = buf }) + vim.api.nvim_set_option_value("modifiable", false, { buf = buf }) if not vim.g.extmarks_events then require("volt.events").enable() end end +---@param open_func function function M.toggle_func(open_func, ui_state) - if ui_state then + if ui_state and open_func then open_func() - return + else + vim.api.nvim_feedkeys("q", "x", false) end - - api.nvim_feedkeys("q", "x", false) end +---@param buf? integer function M.close(buf) if not buf then - api.nvim_feedkeys("q", "x", false) - return + vim.api.nvim_feedkeys("q", "x", false) + else + vim.api.nvim_buf_call(buf, function() + vim.api.nvim_feedkeys("q", "x", false) + end) end - - api.nvim_buf_call(buf, function() - api.nvim_feedkeys("q", "x", false) - end) end return M diff --git a/lua/volt/state.lua b/lua/volt/state.lua index 04a499d..a481483 100644 --- a/lua/volt/state.lua +++ b/lua/volt/state.lua @@ -1,11 +1,11 @@ ---@class Volt.State ----@field clickables? table ----@field hoverables? table ----@field xpad? integer ----@field ns? integer ---@field buf? integer ----@field layout? VoltData.Layout +---@field clickables? table ---@field h? integer +---@field hoverables? table ---@field hovered_extmarks? string[] +---@field layout? VoltData.Layout +---@field ns? integer +---@field xpad? integer return {} ---@type Volt.State[] diff --git a/lua/volt/ui/components.lua b/lua/volt/ui/components.lua index 2ebd284..e7ee5d6 100644 --- a/lua/volt/ui/components.lua +++ b/lua/volt/ui/components.lua @@ -1,13 +1,13 @@ local M = {} --- @class CheckboxOptions +--- @field actions table|nil|? Actions associated with the checkbox (optional). --- @field active boolean Indicates if the checkbox is active. +--- @field check string|nil|? Replace the default check icon with a custom one. +--- @field hloff? string|nil|? Highlight for the inactive state (optional). +--- @field hlon? string|nil|? Highlight for the active state (optional). --- @field txt string The text to display next to the checkbox. ---- @field check string|nil Replace the default check icon with a custom one. ---- @field uncheck string|nil Replace the deafult unchecked icon with a custom one. ---- @field hlon? string|nil Highlight for the active state (optional). ---- @field hloff? string|nil Highlight for the inactive state (optional). ---- @field actions table|nil Actions associated with the checkbox (optional). +--- @field uncheck string|nil|? Replace the deafult unchecked icon with a custom one. --- @param o CheckboxOptions The options for the checkbox. --- @return string[] A table containing the checkbox representation. @@ -20,10 +20,10 @@ function M.checkbox(o) end --- @class ProgressOptions ---- @field w number The total width of the progress bar. ---- @field val number The current value of the progress (0 to 100). ---- @field icon? table active/inactive icon styles, ex: { on = "", off = ""} ---- @field hl? table active/inactive highlights, ex: { on = "", off = ""} +--- @field hl? { on?: string, off?: string } active/inactive highlights, ex: { on = "", off = ""} +--- @field icon? { on?: string, off?: string } active/inactive icon styles, ex: { on = "", off = ""} +--- @field val integer The current value of the progress (0 to 100). +--- @field w integer The total width of the progress bar. --- @param o ProgressOptions The options for the progress bar. --- @return string[][] bar A table containing two elements: the active and inactive parts of the progress bar. @@ -39,8 +39,8 @@ function M.progressbar(o) local inactivelen = o.w - activelen return { - { string.rep(o.icon.on, activelen), o.hl.on }, - { string.rep(o.icon.off, inactivelen), o.hl.off }, + { o.icon.on:rep(activelen), o.hl.on }, + { o.icon.off:rep(inactivelen), o.hl.off }, } end @@ -49,7 +49,7 @@ end --- @param hl string|nil --- @return string[][] separator function M.separator(char, w, hl) - return { { string.rep(char or "─", w), hl or "linenr" } } + return { { (char or "─"):rep(w), hl or "linenr" } } end --- @param tb (string[][][]|string[][])[] @@ -61,7 +61,6 @@ function M.grid_row(tb) table.insert(result, line) end end - return result end @@ -69,18 +68,16 @@ end --- @return integer w function M.line_w(line) local w = 0 - for _, cell in ipairs(line) do if cell[1] ~= "_pad_" then w = w + vim.api.nvim_strwidth(cell[1]) end end - return w end --- @param lines string[][][] ---- @param hl string|nil +--- @param hl? string function M.border(lines, hl) hl = hl or "linenr" @@ -99,30 +96,27 @@ function M.border(lines, hl) for i, _ in ipairs(lines) do table.insert(lines[i], 1, { "│ ", hl }) - local rpad = string.rep(" ", maxw - line_widths[i]) - table.insert(lines[i], { rpad .. " │", hl }) + table.insert(lines[i], { (" "):rep(maxw - line_widths[i]) .. " │", hl }) end maxw = maxw + 2 - local horiz_chars = string.rep("─", maxw) - + local horiz_chars = ("─"):rep(maxw) table.insert(lines, 1, { { "┌" .. horiz_chars .. "┐", hl } }) table.insert(lines, { { "└" .. horiz_chars .. "┘", hl } }) end ---- @param line string[][] +---@generic T: table +--- @param line T --- @param w integer ---- @return string[][] line +--- @return T line function M.hpad(line, w) local pad_w = w - M.line_w(line) - for i, v in ipairs(line) do if v[1] == "_pad_" then - line[i][1] = string.rep(" ", pad_w) + line[i][1] = (" "):rep(pad_w) end end - return line end diff --git a/lua/volt/ui/graphs/bar.lua b/lua/volt/ui/graphs/bar.lua index 1e94653..038dfff 100644 --- a/lua/volt/ui/graphs/bar.lua +++ b/lua/volt/ui/graphs/bar.lua @@ -1,12 +1,9 @@ -local utils = require "volt.ui.graphs.utils" - local function gen_graph(lines, val, opts) - local barchar = string.rep(opts.icon or "█", opts.w) - local emptychar = string.rep(" ", opts.w) - local gap = string.rep(" ", opts.gap) + local barchar = (opts.icon or "█"):rep(opts.w) + local emptychar = (" "):rep(opts.w) + local gap = (" "):rep(opts.gap) local dual_hl = opts.dual_hl local format_hl = opts.format_hl - val = vim.tbl_map(function(x) return (math.floor(x / 10) * 10) / 10 end, val) @@ -29,10 +26,12 @@ local function gen_graph(lines, val, opts) end end +---@param data table ---@return string[][][] lines return function(data) - local lines = {} ---@type string[][][] + local utils = require("volt.ui.graphs.utils") + local lines = {} ---@type string[][][] local total_w = #data.val * (data.baropts.w + data.baropts.gap) + 1 local bottom_line = { "└" .. ("─"):rep(total_w), "linenr" } diff --git a/lua/volt/ui/graphs/dot.lua b/lua/volt/ui/graphs/dot.lua index 89a100e..a6bcf88 100644 --- a/lua/volt/ui/graphs/dot.lua +++ b/lua/volt/ui/graphs/dot.lua @@ -1,38 +1,32 @@ -local utils = require "volt.ui.graphs.utils" - local default_opts = { icons = { on = " 󰄰", off = " ·" }, hl = { on = "exblue", off = "commentfg" }, sidelabels = true, } +---@param lines string[][] +---@param val integer[] local function gen_graph(lines, val, baropts) - local icons = baropts.icons - val = vim.tbl_map(function(x) return (math.floor(x / 10) * 10) / 10 end, val) local arrlen = #val - + local icons = baropts.icons for row_i, v in ipairs(val) do for i = 10, 1, -1 do local icon = v == i and icons.on or icons.off - if v == i and baropts.format_icon then icon = baropts.format_icon(v * 10) end local new_i = (11 - i) <= 0 and 11 or (11 - i) - local hl = v == i and baropts.hl.on or baropts.hl.off - if v == i and baropts.format_hl then hl = baropts.format_hl(v * 10) end table.insert(lines[new_i], { icon, hl }) - if row_i ~= arrlen then table.insert(lines[new_i], { " " }) end @@ -45,11 +39,11 @@ return function(data) local lines = {} local total_w = #data.val * 3 - local bottom_line = { "└" .. string.rep("─", total_w), "linenr" } + local bottom_line = { "└" .. ("─"):rep(total_w), "linenr" } + local utils = require("volt.ui.graphs.utils") local sidelabels_data = utils.gen_labels(data.format_labels) local sidelabels = sidelabels_data.labels - if data.baropts.sidelabels then for i = 10, 1, -1 do local line = {} @@ -58,7 +52,7 @@ return function(data) table.insert(lines, line) end - table.insert(lines, { { string.rep(" ", sidelabels_data.maxw) }, bottom_line }) + table.insert(lines, { { (" "):rep(sidelabels_data.maxw) }, bottom_line }) else for _ = 1, 10, 1 do table.insert(lines, {}) diff --git a/lua/volt/ui/graphs/init.lua b/lua/volt/ui/graphs/init.lua index f76756a..e25769e 100644 --- a/lua/volt/ui/graphs/init.lua +++ b/lua/volt/ui/graphs/init.lua @@ -1,4 +1,4 @@ return { - dot = require "volt.ui.graphs.dot", - bar = require "volt.ui.graphs.bar", + dot = require("volt.ui.graphs.dot"), + bar = require("volt.ui.graphs.bar"), } diff --git a/lua/volt/ui/graphs/utils.lua b/lua/volt/ui/graphs/utils.lua index 87c7e6d..63ec8e6 100644 --- a/lua/volt/ui/graphs/utils.lua +++ b/lua/volt/ui/graphs/utils.lua @@ -1,37 +1,31 @@ +---@class volt.UI.Graphs.Utils local M = {} ---- @param format nil|fun(n: integer): string +--- @param format fun(n: integer): fmt: string +--- @return { labels: string[], maxw: integer } function M.gen_labels(format) - local result = {} - local max_strw = 0 - + local result, max_strw = {}, 0 for i = 1, 10, 1 do - local num - - if format then - num = format(i * 10) - else - num = tostring(i * 10) - end - + local num = format and format(i * 10) or tostring(i * 10) if num:len() > max_strw then - max_strw = #num + max_strw = num:len() end - table.insert(result, num) end result = vim.tbl_map(function(x) - return string.rep(" ", max_strw - #x) .. x + return (" "):rep(max_strw - x:len()) .. x end, result) return { labels = result, maxw = max_strw + 1 } end +---@param virt_txt string +---@param total_w integer +---@param l_pad integer function M.footer_label(virt_txt, total_w, l_pad) - local strw = vim.api.nvim_strwidth(virt_txt[1]) / 2 - local pad = (total_w / 2 + l_pad) - strw - return { { string.rep(" ", pad) }, virt_txt } + local pad = math.floor((total_w / 2 + l_pad) - (vim.api.nvim_strwidth(virt_txt[1]) / 2)) + return { { (" "):rep(pad) }, virt_txt } end return M diff --git a/lua/volt/ui/grid_col.lua b/lua/volt/ui/grid_col.lua index 304b95c..6c85433 100644 --- a/lua/volt/ui/grid_col.lua +++ b/lua/volt/ui/grid_col.lua @@ -1,18 +1,18 @@ -local linew = require("volt.ui.components").line_w - ---- @param lines string[][][]|string[][] +--- @generic T: table +--- @param lines T --- @param w integer --- @param pad integer +--- @return T lines local function add_empty_space(lines, w, pad) for _, line in ipairs(lines) do - table.insert(line, { string.rep(" ", w - linew(line) + pad) }) + table.insert(line, { (" "):rep(w - require("volt.ui.components").line_w(line) + pad) }) end - return lines end ---- @param t1 any[] ---- @param t2 any[] +---@generic T: table, V: table +--- @param t1 T +--- @param t2 V local function append_tb(t1, t2) for _, v in ipairs(t2) do table.insert(t1, v) @@ -38,7 +38,6 @@ return function(columns) end local result = {} ---@type string[][][] - for i = 1, h do if not result[i] then table.insert(result, {}) diff --git a/lua/volt/ui/init.lua b/lua/volt/ui/init.lua index 3e2f582..a79dfc8 100644 --- a/lua/volt/ui/init.lua +++ b/lua/volt/ui/init.lua @@ -1,16 +1,16 @@ -local components = require "volt.ui.components" +local components = require("volt.ui.components") return { - slider = require "volt.ui.slider", + border = components.border, checkbox = components.checkbox, - progressbar = components.progressbar, - table = require "volt.ui.table", - separator = components.separator, - grid_col = require "volt.ui.grid_col", + graphs = require("volt.ui.graphs"), + grid_col = require("volt.ui.grid_col"), grid_row = components.grid_row, - graphs = require "volt.ui.graphs", - border = components.border, hpad = components.hpad, line_w = components.line_w, - tabs = require "volt.ui.tabs", + progressbar = components.progressbar, + separator = components.separator, + slider = require("volt.ui.slider"), + table = require("volt.ui.table"), + tabs = require("volt.ui.tabs"), } diff --git a/lua/volt/ui/slider.lua b/lua/volt/ui/slider.lua index 97c9c8a..a548096 100644 --- a/lua/volt/ui/slider.lua +++ b/lua/volt/ui/slider.lua @@ -1,12 +1,17 @@ -local api = vim.api +---@class volt.UI.Slider local M = {} +---@param w integer +---@param left_txt string +---@param xpad integer +---@param opts? { ratio?: number, thumb?: string } +---@return integer val function M.val(w, left_txt, xpad, opts) opts = opts or {} local txt_len = vim.fn.strwidth(left_txt or "") w = w - txt_len - (opts.ratio and 5 or 0) - local col = (api.nvim_win_get_cursor(0)[2] - txt_len - xpad) + local col = (vim.api.nvim_win_get_cursor(0)[2] - txt_len - xpad) col = opts.thumb and col + 1 or col col = col >= w and w or col @@ -17,9 +22,7 @@ end function M.config(o) local line = {} - local left_txt_len = vim.fn.strwidth(o.txt or "") - if o.txt then table.insert(line, { o.txt }) o.w = o.w - left_txt_len @@ -36,29 +39,9 @@ function M.config(o) thumb_icon = o.val == 0 and "" or thumb_icon end - local active_str = string.rep("━", active_i - vim.fn.strwidth(thumb_icon)) - - local activemark = { - active_str .. thumb_icon, - o.hlon, - { - ui_type = "slider", - click = function() - o.actions() - end, - }, - } - - local inactivemark = { - string.rep("━", o.w - active_i), - o.hloff or "LineNr", - { - ui_type = "slider", - click = function() - o.actions() - end, - }, - } + local active_str = ("━"):rep(active_i - vim.fn.strwidth(thumb_icon)) + local activemark = { active_str .. thumb_icon, o.hlon, { ui_type = "slider", click = o.actions } } + local inactivemark = { ("━"):rep(o.w - active_i), o.hloff or "LineNr", { ui_type = "slider", click = o.actions } } table.insert(line, activemark) table.insert(line, inactivemark) diff --git a/lua/volt/ui/table.lua b/lua/volt/ui/table.lua index 17280ba..5de920d 100644 --- a/lua/volt/ui/table.lua +++ b/lua/volt/ui/table.lua @@ -1,5 +1,3 @@ -local virt_linew = require("volt.ui.components").line_w - --- @param tb string[][][][]|string[][][]|string[][] --- @param w string|integer local function get_column_widths(tb, w) @@ -7,17 +5,14 @@ local function get_column_widths(tb, w) local maxrow = #tb[1] local sum = 0 local result = {} - for i = 1, maxrow do local maxlen = 0 - for _, row in ipairs(tb) do local txt = type(row[i]) == "table" and row[i][1] or row[i] local str = tostring(txt) local tmpw = 0 - if type(row[i]) == "table" then - tmpw = virt_linew(row[i]) + tmpw = require("volt.ui.components").line_w(row[i]) else tmpw = vim.api.nvim_strwidth(str) end @@ -57,14 +52,11 @@ local border_chars = { local function table_border(points, row_type) row_type = row_type or "none" - local str = "" - local tblen = #points - + local tblen, str = #points, "" for i, n in ipairs(points) do local t_char = border_chars.mid[row_type] t_char = i == tblen and "" or t_char - - str = str .. string.rep("─", n + 1) .. t_char + str = str .. ("─"):rep(n + 1) .. t_char end local l_char = border_chars.corners_left[row_type] @@ -73,11 +65,12 @@ local function table_border(points, row_type) return { { l_char .. str .. r_char, "linenr" } } end ---- @param tbl string[][][][]|string[][][]|string[][] +--- @generic T: table +--- @param tbl T --- @param w string|integer --- @param header_hl? string --- @param title? string[]|string ---- @return string[][][]|string[][] lines +--- @return T lines return function(tbl, w, header_hl, title) local col_widths = get_column_widths(tbl, w) @@ -95,19 +88,10 @@ return function(tbl, w, header_hl, title) for i, v in ipairs(row) do local maxlen = col_widths[i] local is_virt = type(v) == "table" - local strlen - - if is_virt then - strlen = virt_linew(v) - else - strlen = vim.api.nvim_strwidth(tostring(v)) - end - + local strlen = is_virt and require("volt.ui.components").line_w(v) or vim.api.nvim_strwidth(tostring(v)) local pad_w = math.floor((maxlen - strlen) / 2) - - local l_pad = string.rep(" ", pad_w) - local r_pad = string.rep(" ", maxlen - pad_w - strlen) - + local l_pad = (" "):rep(pad_w) + local r_pad = (" "):rep(maxlen - pad_w - strlen) local hl = (line_i == 1 and (header_hl or "exgreen") or "normal") table.insert(line, { "│ ", "linenr" }) diff --git a/lua/volt/ui/tabs.lua b/lua/volt/ui/tabs.lua index fb30b76..ce8d2bc 100644 --- a/lua/volt/ui/tabs.lua +++ b/lua/volt/ui/tabs.lua @@ -4,7 +4,6 @@ --- @return string[][][]|string[][] lines return function(data, w, opts) local total_str_w = -1 -- cuz last tab doesnt need gap - for _, v in ipairs(data) do if v ~= "_pad_" then -- 2 = border, 2 = left/right txt padding, 1 = gap @@ -13,16 +12,15 @@ return function(data, w, opts) end local lines = { {}, {}, {} } ---@type string[][][]|string[][] - local datalen = #data for i, v in ipairs(data) do if v == "_pad_" then - local emptychar = string.rep(" ", w - total_str_w) + local emptychar = (" "):rep(w - total_str_w) table.insert(lines[1], { emptychar }) table.insert(lines[2], { emptychar }) table.insert(lines[3], { emptychar }) else - local hchar = string.rep("─", vim.api.nvim_strwidth(v) + 2) + local hchar = ("─"):rep(vim.api.nvim_strwidth(v) + 2) local hl = (opts.active == v and (opts.hlon or "normal")) or (opts.hloff or "commentfg") table.insert(lines[1], { "┌" .. hchar .. "┐", hl }) table.insert(lines[2], { "│ " .. v .. " │", hl }) diff --git a/lua/volt/utils.lua b/lua/volt/utils.lua index 9521b36..051ce85 100644 --- a/lua/volt/utils.lua +++ b/lua/volt/utils.lua @@ -1,45 +1,38 @@ -local M = {} -local api = vim.api -local state = require "volt.state" - local buf_i = 1 ---- @param hex integer|nil +--- @param hex integer|nil|? +--- @return string str local function hexadecimal_to_hex(hex) - return "#" .. ("%06x"):format(hex == nil and 0 or hex) + return "#" .. ("%06x"):format(not hex and 0 or hex) end +---@class volt.Utils +local M = {} + --- @param bufs integer[] function M.cycle_bufs(bufs) buf_i = buf_i == #bufs and 1 or buf_i + 1 - - local new_buf = bufs[buf_i] - local a = vim.fn.bufwinid(new_buf) - - api.nvim_set_current_win(a) + vim.api.nvim_set_current_win(vim.fn.bufwinid(bufs[buf_i])) end --- @param buf integer --- @param step number function M.cycle_clickables(buf, step) - local bufstate = state[buf] - local lines = {} - + local bufstate = require("volt.state")[buf] + local lines = {} ---@type integer[] for row, val in pairs(bufstate.clickables) do if #val > 0 then table.insert(lines, row) end end - local cur_row = api.nvim_win_get_cursor(0)[1] - + local cur_row = vim.api.nvim_win_get_cursor(0)[1] local len = #lines local from_loop = step > 0 and 1 or len local to_loop = step > 0 and len or 1 - for i = from_loop, to_loop, step do if (step > 0 and lines[i] > cur_row) or (step < 0 and lines[i] < cur_row) then - api.nvim_win_set_cursor(0, { lines[i], 0 }) + vim.api.nvim_win_set_cursor(0, { lines[i], 0 }) return end end @@ -47,13 +40,11 @@ end function M.close(val) local event_bufs = require("volt.events").bufs - for _, buf in ipairs(val.bufs) do - local valid_buf = api.nvim_buf_is_valid(buf) - + local valid_buf = vim.api.nvim_buf_is_valid(buf) if valid_buf then - api.nvim_buf_delete(buf, { force = true }) - state[buf] = nil + vim.api.nvim_buf_delete(buf, { force = true }) + require("volt.state")[buf] = nil end --- remove buf from event_bufs table @@ -78,15 +69,13 @@ end --- @param name string --- @return vim.api.keyset.highlight result function M.get_hl(name) - ---@type vim.api.keyset.highlight - local result = {} - local hl = api.nvim_get_hl(0, { name = name }) + local result = {} ---@type vim.api.keyset.highlight + local hl = vim.api.nvim_get_hl(0, { name = name }) - if hl.fg ~= nil then + if hl.fg then result.fg = hexadecimal_to_hex(hl.fg) end - - if hl.bg ~= nil then + if hl.bg then result.bg = hexadecimal_to_hex(hl.bg) end