Skip to content

Commit

Permalink
feat(text): multiline support and pattern highlights
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Nov 23, 2022
1 parent 68a8d57 commit 815bb2c
Showing 1 changed file with 66 additions and 20 deletions.
86 changes: 66 additions & 20 deletions lua/lazy/view/text.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
local Config = require("lazy.core.config")

---@alias TextSegment {str: string, hl?:string, extmark?:table}
---@alias TextSegment {str: string, hl?:string|Extmark}
---@alias Extmark {hl_group?:string, col?:number, end_col?:number}

---@class Text
---@field _lines TextSegment[][]
---@field padding number
local Text = {}

function Text.new()
Expand All @@ -16,17 +18,30 @@ function Text.new()
end

---@param str string
---@param hl? string|table
function Text:append(str, hl)
---@param hl? string|Extmark
---@param opts? {indent?: number, prefix?: string}
function Text:append(str, hl, opts)
opts = opts or {}
if #self._lines == 0 then
self:nl()
end

table.insert(self._lines[#self._lines], {
str = str,
hl = type(hl) == "string" and hl or nil,
extmark = type(hl) == "table" and hl or nil,
})
local lines = vim.split(str, "\n")
for l, line in ipairs(lines) do
if opts.prefix then
line = opts.prefix .. line
end
if opts.indent then
line = string.rep(" ", opts.indent) .. line
end
if l > 1 then
self:nl()
end
table.insert(self._lines[#self._lines], {
str = line,
hl = hl,
})
end

return self
end
Expand All @@ -36,12 +51,11 @@ function Text:nl()
return self
end

function Text:render(buf, padding)
padding = padding or 0
function Text:render(buf)
local lines = {}

for _, line in ipairs(self._lines) do
local str = (" "):rep(padding)
local str = (" "):rep(self.padding)

for _, segment in ipairs(line) do
str = str .. segment.str
Expand All @@ -53,27 +67,59 @@ function Text:render(buf, padding)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)

for l, line in ipairs(self._lines) do
local col = padding
local col = self.padding

for _, segment in ipairs(line) do
local width = vim.fn.strlen(segment.str)

if segment.hl then
vim.api.nvim_buf_set_extmark(buf, Config.ns, l - 1, col, {
hl_group = segment.hl,
end_col = col + width,
})
end
local extmark = segment.hl
if extmark then
if type(extmark) == "string" then
extmark = { hl_group = extmark, end_col = col + width }
end
---@cast extmark Extmark

if segment.extmark then
vim.api.nvim_buf_set_extmark(buf, Config.ns, l - 1, col, segment.extmark)
local extmark_col = extmark.col or col
extmark.col = nil
vim.api.nvim_buf_set_extmark(buf, Config.ns, l - 1, extmark_col, extmark)
end

col = col + width
end
end
end

---@param patterns table<string,string>
function Text:highlight(patterns)
local col = self.padding
local last = self._lines[#self._lines]
---@type TextSegment?
local text
for s, segment in ipairs(last) do
if s == #last then
text = segment
break
end
col = col + vim.fn.strlen(segment.str)
end
if text then
for pattern, hl in pairs(patterns) do
local from, to, match = text.str:find(pattern)
while from do
if match then
from, to = text.str:find(match, from, true)
end
self:append("", {
col = col + from - 1,
end_col = col + to,
hl_group = hl,
})
from, to = text.str:find(pattern, to + 1)
end
end
end
end

function Text:trim()
while #self._lines > 0 and #self._lines[1] == 0 do
table.remove(self._lines, 1)
Expand Down

0 comments on commit 815bb2c

Please sign in to comment.