diff --git a/lua/u/buffer.lua b/lua/u/buffer.lua index 410d1d3..0305349 100644 --- a/lua/u/buffer.lua +++ b/lua/u/buffer.lua @@ -75,6 +75,9 @@ function Buffer:autocmd(event, opts) vim.api.nvim_create_autocmd(event, vim.tbl_extend('force', opts, { buffer = self.bufnr })) end +--- @param fn function +function Buffer:call(fn) return vim.api.nvim_buf_call(self.bufnr, fn) end + --- @param tree u.renderer.Tree function Buffer:render(tree) return self.renderer:render(tree) end diff --git a/lua/u/renderer.lua b/lua/u/renderer.lua index 0a98d61..2a1d353 100644 --- a/lua/u/renderer.lua +++ b/lua/u/renderer.lua @@ -157,7 +157,7 @@ function Renderer.markup_to_string(opts) return table.concat(Renderer.markup_to_ --- @param bufnr number --- @param old_lines string[] | nil --- @param new_lines string[] -function Renderer.patch_lines(bufnr, old_lines, new_lines) +function Renderer.patch_lines(bufnr, old_lines, new_lines) -- {{{ -- -- Helpers: -- @@ -210,7 +210,7 @@ function Renderer.patch_lines(bufnr, old_lines, new_lines) -- No change end end -end +end -- }}} --- @param tree u.renderer.Tree function Renderer:render(tree) -- {{{ @@ -274,25 +274,6 @@ function Renderer:render(tree) -- {{{ self:_reconcile() end -- }}} ---- @private ---- @param start integer ---- @param end_ integer ---- @param strict_indexing boolean ---- @param replacement string[] -function Renderer:_set_lines(start, end_, strict_indexing, replacement) - vim.api.nvim_buf_set_lines(self.bufnr, start, end_, strict_indexing, replacement) -end - ---- @private ---- @param start_row integer ---- @param start_col integer ---- @param end_row integer ---- @param end_col integer ---- @param replacement string[] -function Renderer:_set_text(start_row, start_col, end_row, end_col, replacement) - vim.api.nvim_buf_set_text(self.bufnr, start_row, start_col, end_row, end_col, replacement) -end - --- @private function Renderer:_reconcile() -- {{{ -- @@ -372,7 +353,7 @@ function Renderer:_expr_map_callback(mode, lhs) -- {{{ return cancel and '' or lhs end -- }}} -function Renderer:_on_text_changed() +function Renderer:_on_text_changed() -- {{{ -- Reset changedtick, so that the reconciler knows to refresh its cached -- buffer-content before computing the diff: self.changedtick = 0 @@ -428,9 +409,10 @@ function Renderer:_on_text_changed() end end end -end +end -- }}} -function Renderer:_debug() +--- @private +function Renderer:_debug() -- {{{ local prev_w = vim.api.nvim_get_current_win() vim.cmd.vnew() local info_bufnr = vim.api.nvim_get_current_buf() @@ -450,6 +432,8 @@ function Renderer:_debug() ids, vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { callback = function() + if vim.api.nvim_get_current_win() ~= prev_w then return end + local l, c = unpack(vim.api.nvim_win_get_cursor(0)) l = l - 1 -- make it actually 0-based @@ -489,7 +473,7 @@ function Renderer:_debug() ) vim.api.nvim_set_current_win(prev_w) -end +end -- }}} --- Returns pairs of extmarks and tags associate with said extmarks. The --- returned tags/extmarks are sorted smallest (innermost) to largest @@ -610,6 +594,19 @@ function Renderer:get_tags_at(pos0, mode) -- {{{ return matching_tags end -- }}} + +--- @private +--- @param tag_or_id string | u.renderer.Tag +--- @return { start: [number, number]; stop: [number, number] } | nil +function Renderer:get_tag_bounds(tag_or_id) -- {{{ + for _, x in ipairs(self.curr.extmarks) do + local pos = { start = x.start, stop = x.stop } + local does_tag_match = type(tag_or_id) == 'string' and x.tag.attributes.id == tag_or_id + or x.tag == tag_or_id + if does_tag_match then return pos end + end +end -- }}} + -- }}} -- TreeBuilder {{{ diff --git a/spec/renderer_spec.lua b/spec/renderer_spec.lua index 60036db..a4d5833 100644 --- a/spec/renderer_spec.lua +++ b/spec/renderer_spec.lua @@ -203,4 +203,60 @@ describe('Renderer', function() assert.are.same(captured_changed_text, 'bleh') end) end) + + it('should find tags by position', function() + withbuf({}, function() + local r = R.Renderer.new(0) + r:render { + 'pre', + R.h('text', { + id = 'outer', + }, { + 'inner-pre', + R.h('text', { + id = 'inner', + }, { + 'inner-text', + }), + 'inner-post', + }), + 'post', + } + + local tags = r:get_tags_at { 0, 11 } + assert.are.same(#tags, 1) + assert.are.same(tags[1].tag.attributes.id, 'outer') + + tags = r:get_tags_at { 0, 12 } + assert.are.same(#tags, 2) + assert.are.same(tags[1].tag.attributes.id, 'inner') + assert.are.same(tags[2].tag.attributes.id, 'outer') + end) + end) + + it('should find tags by id', function() + withbuf({}, function() + local r = R.Renderer.new(0) + r:render { + R.h('text', { + id = 'outer', + }, { + 'inner-pre', + R.h('text', { + id = 'inner', + }, { + 'inner-text', + }), + 'inner-post', + }), + 'post', + } + + local bounds = r:get_tag_bounds 'outer' + assert.are.same(bounds, { start = { 0, 0 }, stop = { 0, 29 } }) + + bounds = r:get_tag_bounds 'inner' + assert.are.same(bounds, { start = { 0, 9 }, stop = { 0, 19 } }) + end) + end) end)