mirror of
https://github.com/taigrr/glaze.nvim.git
synced 2026-04-02 03:09:10 -07:00
Phase 1 - Bug fixes:
- Fix extmark rendering in text.lua (table vs string hl handling)
- Fix timer leak: WinClosed autocmd now triggers view.close()
- Add GOBIN/GOPATH/~/go/bin awareness to is_installed() and new bin_path()
- Reject update_all() while tasks running (race condition fix)
- Implement _toggle_details with full binary info expansion
Phase 2 - Lazy.nvim-style controls:
- U = Update all, u = update cursor binary
- I = Install all missing, i = install cursor binary
- x = Abort, CR = toggle details, q/Esc = close
- Line-to-binary mapping for cursor-aware actions
Phase 3 - Auto-update checking:
- New checker module with go list/go version -m integration
- auto_check config option (daily/weekly/custom frequency)
- Persistent state in stdpath('data')/glaze/state.json
- :GlazeCheck command for manual checks
- Update indicators in UI (version info + arrows)
Phase 4 - Repo polish:
- MIT LICENSE file
- Doughnut-themed README with badges and Why Glaze? section
- Updated help docs with all new features/keybinds/API
155 lines
3.8 KiB
Lua
155 lines
3.8 KiB
Lua
---@brief [[
|
|
--- glaze.nvim text rendering (based on lazy.nvim)
|
|
--- Handles buffered text with highlight segments
|
|
---@brief ]]
|
|
|
|
local M = {}
|
|
|
|
---@class GlazeTextSegment
|
|
---@field str string
|
|
---@field hl? string|GlazeExtmark
|
|
|
|
---@class GlazeExtmark
|
|
---@field hl_group? string
|
|
---@field col? number
|
|
---@field end_col? number
|
|
---@field virt_text? table
|
|
---@field virt_text_win_col? number
|
|
|
|
---@class GlazeText
|
|
---@field _lines GlazeTextSegment[][]
|
|
---@field padding number
|
|
---@field wrap number
|
|
local Text = {}
|
|
|
|
function Text.new()
|
|
local self = setmetatable({}, { __index = Text })
|
|
self._lines = {}
|
|
self.padding = 2
|
|
self.wrap = 80
|
|
return self
|
|
end
|
|
|
|
---@param str string
|
|
---@param hl? string|GlazeExtmark
|
|
---@param opts? { indent?: number, wrap?: boolean }
|
|
---@return GlazeText
|
|
function Text:append(str, hl, opts)
|
|
opts = opts or {}
|
|
if #self._lines == 0 then
|
|
self:nl()
|
|
end
|
|
|
|
local lines = vim.split(str, "\n")
|
|
for i, line in ipairs(lines) do
|
|
if opts.indent then
|
|
line = string.rep(" ", opts.indent) .. line
|
|
end
|
|
if i > 1 then
|
|
self:nl()
|
|
end
|
|
-- Handle wrap
|
|
if opts.wrap and str ~= "" and self:col() > 0 and self:col() + vim.fn.strwidth(line) + self.padding > self.wrap then
|
|
self:nl()
|
|
end
|
|
table.insert(self._lines[#self._lines], { str = line, hl = hl })
|
|
end
|
|
return self
|
|
end
|
|
|
|
---Append a virtual text extmark on the current line (empty string segment).
|
|
---@param extmark GlazeExtmark Extmark options (virt_text, virt_text_win_col, etc.)
|
|
---@return GlazeText
|
|
function Text:append_extmark(extmark)
|
|
if #self._lines == 0 then
|
|
self:nl()
|
|
end
|
|
table.insert(self._lines[#self._lines], { str = "", hl = extmark })
|
|
return self
|
|
end
|
|
|
|
---@return GlazeText
|
|
function Text:nl()
|
|
table.insert(self._lines, {})
|
|
return self
|
|
end
|
|
|
|
---@return number
|
|
function Text:row()
|
|
return #self._lines == 0 and 1 or #self._lines
|
|
end
|
|
|
|
---@return number
|
|
function Text:col()
|
|
if #self._lines == 0 then
|
|
return 0
|
|
end
|
|
local width = 0
|
|
for _, segment in ipairs(self._lines[#self._lines]) do
|
|
width = width + vim.fn.strwidth(segment.str)
|
|
end
|
|
return width
|
|
end
|
|
|
|
function Text:trim()
|
|
while #self._lines > 0 and #self._lines[#self._lines] == 0 do
|
|
table.remove(self._lines)
|
|
end
|
|
end
|
|
|
|
---@param buf number
|
|
---@param ns number
|
|
function Text:render(buf, ns)
|
|
local lines = {}
|
|
|
|
for _, line in ipairs(self._lines) do
|
|
local str = string.rep(" ", self.padding)
|
|
for _, segment in ipairs(line) do
|
|
str = str .. segment.str
|
|
end
|
|
if str:match("^%s*$") then
|
|
str = ""
|
|
end
|
|
table.insert(lines, str)
|
|
end
|
|
|
|
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
|
|
vim.api.nvim_buf_clear_namespace(buf, ns, 0, -1)
|
|
|
|
for l, line in ipairs(self._lines) do
|
|
if lines[l] ~= "" or true then -- process even empty lines for extmarks
|
|
local col = self.padding
|
|
for _, segment in ipairs(line) do
|
|
local width = vim.fn.strwidth(segment.str)
|
|
local extmark = segment.hl
|
|
|
|
if extmark then
|
|
if type(extmark) == "string" then
|
|
-- Simple highlight group string
|
|
if width > 0 then
|
|
pcall(vim.api.nvim_buf_set_extmark, buf, ns, l - 1, col, {
|
|
hl_group = extmark,
|
|
end_col = col + width,
|
|
})
|
|
end
|
|
elseif type(extmark) == "table" then
|
|
-- Full extmark table (virt_text, etc.)
|
|
local extmark_col = extmark.col or col
|
|
local opts = vim.tbl_extend("force", {}, extmark)
|
|
opts.col = nil -- col is positional, not an extmark option
|
|
if not opts.end_col and width > 0 and opts.hl_group then
|
|
opts.end_col = extmark_col + width
|
|
end
|
|
pcall(vim.api.nvim_buf_set_extmark, buf, ns, l - 1, extmark_col, opts)
|
|
end
|
|
end
|
|
col = col + width
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
M.Text = Text
|
|
|
|
return M
|