watch text-changes with signals
Some checks failed
NeoVim tests / code-quality (push) Failing after 1m19s
Some checks failed
NeoVim tests / code-quality (push) Failing after 1m19s
This commit is contained in:
parent
9054f4453f
commit
a4058e11c4
@ -22,29 +22,10 @@ tracker.create_effect(function()
|
|||||||
-- constructed with `h(...)` calls). To help organize the markup, text and
|
-- 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
|
-- tags can be nested in tables at any depth. Line breaks must be specified
|
||||||
-- manually, with '\n'.
|
-- manually, with '\n'.
|
||||||
local text_ref = ui_buf.renderer:create_ref()
|
|
||||||
ui_buf:render {
|
ui_buf:render {
|
||||||
'Reactive Counter Example\n',
|
'Reactive Counter Example\n',
|
||||||
'========================\n\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' },
|
{ 'Counter: ', tostring(count), '\n' },
|
||||||
|
|
||||||
'\n',
|
'\n',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local Signal = require('u.tracker').Signal
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
local H = {}
|
local H = {}
|
||||||
|
|
||||||
@ -33,52 +35,6 @@ M.h = setmetatable({}, {
|
|||||||
end,
|
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 {{{
|
-- Renderer {{{
|
||||||
--- @class u.renderer.RendererExtmark
|
--- @class u.renderer.RendererExtmark
|
||||||
--- @field id? number
|
--- @field id? number
|
||||||
@ -124,11 +80,15 @@ function Renderer.new(bufnr) -- {{{
|
|||||||
old = { lines = {}, extmarks = {} },
|
old = { lines = {}, extmarks = {} },
|
||||||
curr = { lines = {}, extmarks = {} },
|
curr = { lines = {}, extmarks = {} },
|
||||||
}, Renderer)
|
}, Renderer)
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd({ 'TextChangedI', 'TextChangedP' }, {
|
||||||
|
buffer = bufnr,
|
||||||
|
callback = function() self:_on_text_changed() end,
|
||||||
|
})
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end -- }}}
|
end -- }}}
|
||||||
|
|
||||||
function Renderer:create_ref() return setmetatable({ renderer = self }, TagRef) end
|
|
||||||
|
|
||||||
--- @param opts {
|
--- @param opts {
|
||||||
--- tree: u.renderer.Tree;
|
--- tree: u.renderer.Tree;
|
||||||
--- on_tag?: fun(tag: u.renderer.Tag, start0: [number, number], stop0: [number, number]): any;
|
--- 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
|
tag.attributes.extmark.hl_group = tag.attributes.extmark.hl_group or hl
|
||||||
end
|
end
|
||||||
|
|
||||||
local extmark_opts = tag.attributes.extmark
|
local extmark_opts = tag.attributes.extmark or {}
|
||||||
|
|
||||||
-- Set any necessary keymaps:
|
-- Set any necessary keymaps:
|
||||||
for _, mode in ipairs { 'i', 'n', 'v', 'x', 'o' } do
|
for _, mode in ipairs { 'i', 'n', 'v', 'x', 'o' } do
|
||||||
for lhs, _ in pairs(tag.attributes[mode .. 'map'] or {}) do
|
for lhs, _ in pairs(tag.attributes[mode .. 'map'] or {}) do
|
||||||
-- Force creating an extmark if there are key handlers. To accurately
|
-- Force creating an extmark if there are key handlers. To accurately
|
||||||
-- sense the bounds of the text, we need an extmark:
|
-- sense the bounds of the text, we need an extmark:
|
||||||
extmark_opts = extmark_opts or {}
|
|
||||||
vim.keymap.set(
|
vim.keymap.set(
|
||||||
mode,
|
mode,
|
||||||
lhs,
|
lhs,
|
||||||
@ -293,22 +252,12 @@ function Renderer:render(tree) -- {{{
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check for refs:
|
table.insert(extmarks, {
|
||||||
if tag.attributes.ref and getmetatable(tag.attributes.ref) == TagRef then
|
start = start0,
|
||||||
--- @type u.renderer.TagRef
|
stop = stop0,
|
||||||
local ref = tag.attributes.ref
|
opts = extmark_opts,
|
||||||
ref.tag = tag
|
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
|
|
||||||
end
|
end
|
||||||
end, -- }}}
|
end, -- }}}
|
||||||
}
|
}
|
||||||
@ -404,6 +353,42 @@ function Renderer:_expr_map_callback(mode, lhs) -- {{{
|
|||||||
return cancel and '' or lhs
|
return cancel and '' or lhs
|
||||||
end -- }}}
|
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
|
--- Returns pairs of extmarks and tags associate with said extmarks. The
|
||||||
--- returned tags/extmarks are sorted smallest (innermost) to largest
|
--- returned tags/extmarks are sorted smallest (innermost) to largest
|
||||||
--- (outermost).
|
--- (outermost).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user