factor out line-patching into a separate function
Some checks failed
NeoVim tests / plenary-tests (push) Failing after 8s

This commit is contained in:
Jonathan Apodaca 2025-04-24 10:00:55 -06:00
parent 7ad3d941f4
commit 5a6451a85e

View File

@ -132,6 +132,64 @@ end -- }}}
--- }
function Renderer.markup_to_string(opts) return table.concat(Renderer.markup_to_lines(opts), '\n') end
--- @param bufnr number
--- @param old_lines string[] | nil
--- @param new_lines string[]
function Renderer.patch_lines(bufnr, old_lines, new_lines)
--
-- Helpers:
--
--- @param start integer
--- @param end_ integer
--- @param strict_indexing boolean
--- @param replacement string[]
local function _set_lines(start, end_, strict_indexing, replacement)
vim.api.nvim_buf_set_lines(bufnr, start, end_, strict_indexing, replacement)
end
--- @param start_row integer
--- @param start_col integer
--- @param end_row integer
--- @param end_col integer
--- @param replacement string[]
local function _set_text(start_row, start_col, end_row, end_col, replacement)
vim.api.nvim_buf_set_text(bufnr, start_row, start_col, end_row, end_col, replacement)
end
-- Morph the text to the desired state:
local line_changes =
H.levenshtein(old_lines or vim.api.nvim_buf_get_lines(bufnr, 0, -1, false), new_lines)
for _, line_change in ipairs(line_changes) do
local lnum0 = line_change.index - 1
if line_change.kind == 'add' then
_set_lines(lnum0, lnum0, true, { line_change.item })
elseif line_change.kind == 'change' then
-- Compute inter-line diff, and apply:
local col_changes =
H.levenshtein(vim.split(line_change.from, ''), vim.split(line_change.to, ''))
for _, col_change in ipairs(col_changes) do
local cnum0 = col_change.index - 1
if col_change.kind == 'add' then
_set_text(lnum0, cnum0, lnum0, cnum0, { col_change.item })
elseif col_change.kind == 'change' then
_set_text(lnum0, cnum0, lnum0, cnum0 + 1, { col_change.to })
elseif col_change.kind == 'delete' then
_set_text(lnum0, cnum0, lnum0, cnum0 + 1, {})
else
-- No change
end
end
elseif line_change.kind == 'delete' then
_set_lines(lnum0, lnum0 + 1, true, {})
else
-- No change
end
end
end
--- @param tree u.renderer.Tree
function Renderer:render(tree) -- {{{
local changedtick = vim.b[self.bufnr].changedtick
@ -210,45 +268,16 @@ end
--- @private
function Renderer:_reconcile() -- {{{
local line_changes = H.levenshtein(self.old.lines, self.curr.lines)
self.old = self.curr
--
-- Step 1: morph the text to the desired state:
--
for _, line_change in ipairs(line_changes) do
local lnum0 = line_change.index - 1
if line_change.kind == 'add' then
self:_set_lines(lnum0, lnum0, true, { line_change.item })
elseif line_change.kind == 'change' then
-- Compute inter-line diff, and apply:
local col_changes =
H.levenshtein(vim.split(line_change.from, ''), vim.split(line_change.to, ''))
for _, col_change in ipairs(col_changes) do
local cnum0 = col_change.index - 1
if col_change.kind == 'add' then
self:_set_text(lnum0, cnum0, lnum0, cnum0, { col_change.item })
elseif col_change.kind == 'change' then
self:_set_text(lnum0, cnum0, lnum0, cnum0 + 1, { col_change.to })
elseif col_change.kind == 'delete' then
self:_set_text(lnum0, cnum0, lnum0, cnum0 + 1, {})
else
-- No change
end
end
elseif line_change.kind == 'delete' then
self:_set_lines(lnum0, lnum0 + 1, true, {})
else
-- No change
end
end
Renderer.patch_lines(self.bufnr, self.old.lines, self.curr.lines)
self.changedtick = vim.b[self.bufnr].changedtick
--
-- Step 2: reconcile extmarks:
--
-- Clear current extmarks:
vim.api.nvim_buf_clear_namespace(self.bufnr, self.ns, 0, -1)
-- Set current extmarks:
@ -265,6 +294,8 @@ function Renderer:_reconcile() -- {{{
}, extmark.opts)
)
end
self.old = self.curr
end -- }}}
--- @private