mirror of
https://github.com/taigrr/glaze.nvim.git
synced 2026-04-02 03:09:10 -07:00
initial commit
This commit is contained in:
132
lua/glaze/text.lua
Normal file
132
lua/glaze/text.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
---@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
|
||||
|
||||
---@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] ~= "" then
|
||||
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
|
||||
extmark = { hl_group = extmark, end_col = col + width }
|
||||
end
|
||||
---@cast extmark GlazeExtmark
|
||||
local extmark_col = extmark.col or col
|
||||
extmark.col = nil
|
||||
pcall(vim.api.nvim_buf_set_extmark, buf, ns, l - 1, extmark_col, extmark)
|
||||
end
|
||||
col = col + width
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.Text = Text
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user