watch text-changes with signals
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m23s
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m23s
This commit is contained in:
parent
9054f4453f
commit
9bd0ff2088
@ -22,29 +22,10 @@ tracker.create_effect(function()
|
||||
-- constructed with `h(...)` calls). To help organize the markup, text and
|
||||
-- tags can be nested in tables at any depth. Line breaks must be specified
|
||||
-- manually, with '\n'.
|
||||
local text_ref = ui_buf.renderer:create_ref()
|
||||
ui_buf:render {
|
||||
'Reactive Counter Example\n',
|
||||
'========================\n\n',
|
||||
|
||||
{
|
||||
'Text field: ',
|
||||
h('text', { hl = 'DiffAdd', ref = text_ref }, { '[]' }),
|
||||
'\n',
|
||||
h('text', {
|
||||
hl = 'DiffAdd',
|
||||
nmap = {
|
||||
['<CR>'] = function()
|
||||
vim.notify(text_ref:text())
|
||||
return ''
|
||||
end,
|
||||
},
|
||||
}, ' Submit '),
|
||||
},
|
||||
|
||||
'\n',
|
||||
'\n',
|
||||
|
||||
{ 'Counter: ', tostring(count), '\n' },
|
||||
|
||||
'\n',
|
||||
|
@ -1,3 +1,5 @@
|
||||
local Signal = require('u.tracker').Signal
|
||||
|
||||
local M = {}
|
||||
local H = {}
|
||||
|
||||
@ -33,52 +35,6 @@ M.h = setmetatable({}, {
|
||||
end,
|
||||
})
|
||||
|
||||
-- TagRef {{{
|
||||
--- @class u.renderer.TagRef
|
||||
--- @field tag? u.renderer.Tag
|
||||
--- @field renderer u.renderer.Renderer
|
||||
local TagRef = {}
|
||||
TagRef.__index = TagRef
|
||||
|
||||
function TagRef:extmark()
|
||||
if not self.tag then return {} end
|
||||
|
||||
--- @type u.renderer.RendererExtmark?
|
||||
local extmark_inf = vim
|
||||
.iter(self.renderer.curr.extmarks)
|
||||
--- @param x u.renderer.RendererExtmark
|
||||
:find(function(x) return x.tag == self.tag end)
|
||||
if not extmark_inf then return {} end
|
||||
|
||||
local extmark = vim.api.nvim_buf_get_extmark_by_id(
|
||||
self.renderer.bufnr,
|
||||
self.renderer.ns,
|
||||
extmark_inf.id,
|
||||
{ details = true }
|
||||
)
|
||||
return extmark
|
||||
end
|
||||
|
||||
function TagRef:range()
|
||||
local extmark = self:extmark()
|
||||
if not extmark then return nil end
|
||||
local Range = require 'u.range'
|
||||
return Range.from_extmark(self.renderer.bufnr, extmark)
|
||||
end
|
||||
|
||||
function TagRef:lines()
|
||||
local range = self:range()
|
||||
if not range then return {} end
|
||||
return range:lines()
|
||||
end
|
||||
|
||||
function TagRef:text()
|
||||
local range = self:range()
|
||||
if not range then return '' end
|
||||
return range:text()
|
||||
end
|
||||
-- }}}
|
||||
|
||||
-- Renderer {{{
|
||||
--- @class u.renderer.RendererExtmark
|
||||
--- @field id? number
|
||||
@ -124,11 +80,15 @@ function Renderer.new(bufnr) -- {{{
|
||||
old = { lines = {}, extmarks = {} },
|
||||
curr = { lines = {}, extmarks = {} },
|
||||
}, Renderer)
|
||||
|
||||
vim.api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI', 'TextChangedP' }, {
|
||||
buffer = bufnr,
|
||||
callback = function() self:_on_text_changed() end,
|
||||
})
|
||||
|
||||
return self
|
||||
end -- }}}
|
||||
|
||||
function Renderer:create_ref() return setmetatable({ renderer = self }, TagRef) end
|
||||
|
||||
--- @param opts {
|
||||
--- tree: u.renderer.Tree;
|
||||
--- on_tag?: fun(tag: u.renderer.Tag, start0: [number, number], stop0: [number, number]): any;
|
||||
@ -276,14 +236,13 @@ function Renderer:render(tree) -- {{{
|
||||
tag.attributes.extmark.hl_group = tag.attributes.extmark.hl_group or hl
|
||||
end
|
||||
|
||||
local extmark_opts = tag.attributes.extmark
|
||||
local extmark_opts = tag.attributes.extmark or {}
|
||||
|
||||
-- Set any necessary keymaps:
|
||||
for _, mode in ipairs { 'i', 'n', 'v', 'x', 'o' } do
|
||||
for lhs, _ in pairs(tag.attributes[mode .. 'map'] or {}) do
|
||||
-- Force creating an extmark if there are key handlers. To accurately
|
||||
-- sense the bounds of the text, we need an extmark:
|
||||
extmark_opts = extmark_opts or {}
|
||||
vim.keymap.set(
|
||||
mode,
|
||||
lhs,
|
||||
@ -293,22 +252,12 @@ function Renderer:render(tree) -- {{{
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for refs:
|
||||
if tag.attributes.ref and getmetatable(tag.attributes.ref) == TagRef then
|
||||
--- @type u.renderer.TagRef
|
||||
local ref = tag.attributes.ref
|
||||
ref.tag = tag
|
||||
extmark_opts = extmark_opts or {}
|
||||
end
|
||||
|
||||
if extmark_opts then
|
||||
table.insert(extmarks, {
|
||||
start = start0,
|
||||
stop = stop0,
|
||||
opts = extmark_opts,
|
||||
tag = tag,
|
||||
})
|
||||
end
|
||||
table.insert(extmarks, {
|
||||
start = start0,
|
||||
stop = stop0,
|
||||
opts = extmark_opts,
|
||||
tag = tag,
|
||||
})
|
||||
end
|
||||
end, -- }}}
|
||||
}
|
||||
@ -404,6 +353,40 @@ function Renderer:_expr_map_callback(mode, lhs) -- {{{
|
||||
return cancel and '' or lhs
|
||||
end -- }}}
|
||||
|
||||
function Renderer:_on_text_changed()
|
||||
--- @type integer, integer
|
||||
local l, c = unpack(vim.api.nvim_win_get_cursor(0))
|
||||
l = l - 1 -- make it actually 0-based
|
||||
local pos_infos = self:get_pos_infos { l, c }
|
||||
for _, pos_info in ipairs(pos_infos) do
|
||||
local extmark_inf = pos_info.extmark
|
||||
local tag = pos_info.tag
|
||||
if tag.attributes.signal and getmetatable(tag.attributes.signal) == Signal then
|
||||
--- @type u.Signal
|
||||
local signal = tag.attributes.signal
|
||||
|
||||
local extmark =
|
||||
vim.api.nvim_buf_get_extmark_by_id(self.bufnr, self.ns, extmark_inf.id, { details = true })
|
||||
|
||||
--- @type integer, integer, vim.api.keyset.extmark_details
|
||||
local start_row0, start_col0, details = unpack(extmark)
|
||||
local end_row0, end_col0 = details.end_row, details.end_col
|
||||
|
||||
if start_row0 == end_row0 and start_col0 == end_col0 then
|
||||
-- Invalid extmark
|
||||
else
|
||||
local lines = vim.fn.getregion(
|
||||
{ self.bufnr, start_row0 + 1, start_col0 + 1 },
|
||||
{ self.bufnr, end_row0 + 1, end_col0 },
|
||||
{ type = 'v' }
|
||||
)
|
||||
local text = table.concat(lines, '\n')
|
||||
if text ~= signal:get() then signal:schedule_set(text) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns pairs of extmarks and tags associate with said extmarks. The
|
||||
--- returned tags/extmarks are sorted smallest (innermost) to largest
|
||||
--- (outermost).
|
||||
|
Loading…
x
Reference in New Issue
Block a user