refactor extmark to its own file
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m24s
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m24s
This commit is contained in:
parent
c6b0076630
commit
fc29454c55
@ -2,7 +2,7 @@ local Range = require 'u.range'
|
||||
local Renderer = require('u.renderer').Renderer
|
||||
|
||||
--- @class u.Buffer
|
||||
--- @field bufnr number
|
||||
--- @field bufnr integer
|
||||
--- @field b vim.var_accessor
|
||||
--- @field bo vim.bo
|
||||
--- @field renderer u.renderer.Renderer
|
||||
|
71
lua/u/extmark.lua
Normal file
71
lua/u/extmark.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local Pos = require 'u.pos'
|
||||
|
||||
---@class u.Extmark
|
||||
---@field bufnr integer
|
||||
---@field id integer
|
||||
---@field nsid integer
|
||||
local Extmark = {}
|
||||
Extmark.__index = Extmark
|
||||
|
||||
--- @param bufnr integer
|
||||
--- @param nsid integer
|
||||
--- @param id integer
|
||||
function Extmark.new(bufnr, nsid, id)
|
||||
return setmetatable({
|
||||
bufnr = bufnr,
|
||||
nsid = nsid,
|
||||
id = id,
|
||||
}, Extmark)
|
||||
end
|
||||
|
||||
--- @param range u.Range
|
||||
--- @param nsid integer
|
||||
function Extmark.from_range(range, nsid)
|
||||
local r = range:to_charwise()
|
||||
local stop = r.stop or r.start
|
||||
local end_row = stop.lnum - 1
|
||||
local end_col = stop.col
|
||||
if range.mode == 'V' then
|
||||
end_row = end_row + 1
|
||||
end_col = 0
|
||||
end
|
||||
local id = vim.api.nvim_buf_set_extmark(r.start.bufnr, nsid, r.start.lnum - 1, r.start.col - 1, {
|
||||
right_gravity = false,
|
||||
end_right_gravity = true,
|
||||
end_row = end_row,
|
||||
end_col = end_col,
|
||||
})
|
||||
return Extmark.new(r.start.bufnr, nsid, id)
|
||||
end
|
||||
|
||||
function Extmark:range()
|
||||
local Range = require 'u.range'
|
||||
|
||||
local raw_extmark =
|
||||
vim.api.nvim_buf_get_extmark_by_id(self.bufnr, self.nsid, self.id, { details = true })
|
||||
local start_row0, start_col0, details = unpack(raw_extmark)
|
||||
|
||||
--- @type u.Pos
|
||||
local start = Pos.from00(self.bufnr, start_row0, start_col0)
|
||||
--- @type u.Pos?
|
||||
local stop = details
|
||||
and details.end_row
|
||||
and details.end_col
|
||||
and Pos.from01(self.bufnr, details.end_row, details.end_col)
|
||||
|
||||
local n_buf_lines = vim.api.nvim_buf_line_count(self.bufnr)
|
||||
if stop and stop.lnum > n_buf_lines then
|
||||
stop.lnum = n_buf_lines
|
||||
stop = stop:eol()
|
||||
end
|
||||
if stop and stop.col == 0 then
|
||||
stop.col = 1
|
||||
stop = stop:next(-1)
|
||||
end
|
||||
|
||||
return Range.new(start, stop, 'v')
|
||||
end
|
||||
|
||||
function Extmark:delete() vim.api.nvim_buf_del_extmark(self.bufnr, self.nsid, self.id) end
|
||||
|
||||
return Extmark
|
@ -7,9 +7,9 @@ local function line_text(bufnr, lnum)
|
||||
end
|
||||
|
||||
--- @class u.Pos
|
||||
--- @field bufnr number buffer number
|
||||
--- @field lnum number 1-based line index
|
||||
--- @field col number 1-based column index
|
||||
--- @field bufnr integer buffer number
|
||||
--- @field lnum integer 1-based line index
|
||||
--- @field col integer 1-based column index
|
||||
--- @field off number
|
||||
local Pos = {}
|
||||
Pos.__index = Pos
|
||||
@ -31,14 +31,13 @@ end
|
||||
function Pos.new(bufnr, lnum, col, off)
|
||||
if bufnr == nil or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||
if off == nil then off = 0 end
|
||||
local pos = {
|
||||
--- @type u.Pos
|
||||
return setmetatable({
|
||||
bufnr = bufnr,
|
||||
lnum = lnum,
|
||||
col = col,
|
||||
off = off,
|
||||
}
|
||||
setmetatable(pos, Pos)
|
||||
return pos
|
||||
}, Pos)
|
||||
end
|
||||
|
||||
--- @param bufnr? number
|
||||
@ -47,6 +46,12 @@ end
|
||||
--- @param off? number
|
||||
function Pos.from00(bufnr, lnum0, col0, off) return Pos.new(bufnr, lnum0 + 1, col0 + 1, off) end
|
||||
|
||||
--- @param bufnr? number
|
||||
--- @param lnum0 number 1-based
|
||||
--- @param col1 number 1-based
|
||||
--- @param off? number
|
||||
function Pos.from01(bufnr, lnum0, col1, off) return Pos.new(bufnr, lnum0 + 1, col1, off) end
|
||||
|
||||
--- @param bufnr? number
|
||||
--- @param lnum1 number 1-based
|
||||
--- @param col0 number 1-based
|
||||
|
@ -1,14 +1,9 @@
|
||||
local Extmark = require 'u.extmark'
|
||||
local Pos = require 'u.pos'
|
||||
|
||||
local ESC = vim.api.nvim_replace_termcodes('<Esc>', true, false, true)
|
||||
local NS = vim.api.nvim_create_namespace 'u.range'
|
||||
|
||||
---@class u.ExtmarkRange
|
||||
---@field bufnr number
|
||||
---@field id number
|
||||
local ExtmarkRange = {}
|
||||
ExtmarkRange.__index = ExtmarkRange
|
||||
|
||||
--- @class u.Range
|
||||
--- @field start u.Pos
|
||||
--- @field stop u.Pos|nil
|
||||
@ -90,34 +85,6 @@ function Range.from_marks(lpos, rpos)
|
||||
return Range.new(start, stop, mode)
|
||||
end
|
||||
|
||||
--- @param bufnr number
|
||||
--- @param extmark vim.api.keyset.get_extmark_item_by_id
|
||||
function Range.from_extmark(bufnr, extmark)
|
||||
---@type integer, integer, vim.api.keyset.extmark_details | nil
|
||||
local start_row0, start_col0, details = unpack(extmark)
|
||||
|
||||
local start = Pos.new(bufnr, start_row0 + 1, start_col0 + 1)
|
||||
local stop = details and Pos.new(bufnr, details.end_row + 1, details.end_col)
|
||||
|
||||
if stop ~= nil then
|
||||
-- Check for invalid extmark range:
|
||||
if stop < start then return Range.new(stop) end
|
||||
|
||||
-- Check for stop-mark past the end of the buffer:
|
||||
local buf_max_lines = vim.api.nvim_buf_line_count(bufnr)
|
||||
if stop.lnum > buf_max_lines then
|
||||
stop.lnum = buf_max_lines
|
||||
stop = stop:eol()
|
||||
end
|
||||
|
||||
-- A stop mark at position 0 means it is at the end of the last line.
|
||||
-- Move it back.
|
||||
if stop.col == 0 then stop = stop:must_next(-1) end
|
||||
end
|
||||
|
||||
return Range.new(start, stop, 'v')
|
||||
end
|
||||
|
||||
--- @param bufnr? number
|
||||
function Range.from_buf_text(bufnr)
|
||||
if bufnr == nil or bufnr == 0 then bufnr = vim.api.nvim_get_current_buf() end
|
||||
@ -392,22 +359,7 @@ function Range:save_to_marks(left, right)
|
||||
(self:is_empty() and self.start or self.stop):save_to_mark(right)
|
||||
end
|
||||
|
||||
function Range:save_to_extmark()
|
||||
local r = self:to_charwise()
|
||||
local end_row = r.stop.lnum - 1
|
||||
local end_col = r.stop.col
|
||||
if self.mode == 'V' then
|
||||
end_row = end_row + 1
|
||||
end_col = 0
|
||||
end
|
||||
local id = vim.api.nvim_buf_set_extmark(r.start.bufnr, NS, r.start.lnum - 1, r.start.col - 1, {
|
||||
right_gravity = false,
|
||||
end_right_gravity = true,
|
||||
end_row = end_row,
|
||||
end_col = end_col,
|
||||
})
|
||||
return ExtmarkRange.new(r.start.bufnr, id)
|
||||
end
|
||||
function Range:save_to_extmark() return Extmark.from_range(self, NS) end
|
||||
|
||||
function Range:set_visual_selection()
|
||||
if self:is_empty() then return end
|
||||
@ -703,17 +655,4 @@ function Range:highlight(group, opts)
|
||||
}
|
||||
end
|
||||
|
||||
function ExtmarkRange.new(bufnr, id) return setmetatable({ bufnr = bufnr, id = id }, ExtmarkRange) end
|
||||
|
||||
function ExtmarkRange:range()
|
||||
return Range.from_extmark(
|
||||
self.bufnr,
|
||||
vim.api.nvim_buf_get_extmark_by_id(self.bufnr, NS, self.id, {
|
||||
details = true,
|
||||
})
|
||||
)
|
||||
end
|
||||
|
||||
function ExtmarkRange:delete() vim.api.nvim_buf_del_extmark(self.bufnr, NS, self.id) end
|
||||
|
||||
return Range
|
||||
|
@ -6,19 +6,19 @@ M.debug = false
|
||||
-- class Signal
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--- @class u.Signal
|
||||
--- @class u.Signal<T>
|
||||
--- @field name? string
|
||||
--- @field private changing boolean
|
||||
--- @field private value any
|
||||
--- @field private value T
|
||||
--- @field private subscribers table<function, boolean>
|
||||
--- @field private on_dispose_callbacks function[]
|
||||
local Signal = {}
|
||||
M.Signal = Signal
|
||||
Signal.__index = Signal
|
||||
|
||||
--- @param value any
|
||||
--- @param value `T`
|
||||
--- @param name? string
|
||||
--- @return u.Signal
|
||||
--- @return u.Signal<T>
|
||||
function Signal:new(value, name)
|
||||
local obj = setmetatable({
|
||||
name = name,
|
||||
@ -30,7 +30,7 @@ function Signal:new(value, name)
|
||||
return obj
|
||||
end
|
||||
|
||||
--- @param value any
|
||||
--- @param value T
|
||||
function Signal:set(value)
|
||||
self.value = value
|
||||
|
||||
@ -67,11 +67,12 @@ function Signal:set(value)
|
||||
end
|
||||
end
|
||||
|
||||
--- @param value T
|
||||
function Signal:schedule_set(value)
|
||||
vim.schedule(function() self:set(value) end)
|
||||
end
|
||||
|
||||
--- @return any
|
||||
--- @return T
|
||||
function Signal:get()
|
||||
local ctx = M.ExecutionContext.current()
|
||||
if ctx then ctx:track(self) end
|
||||
@ -85,8 +86,8 @@ function Signal:update(fn) self:set(fn(self.value)) end
|
||||
function Signal:schedule_update(fn) self:schedule_set(fn(self.value)) end
|
||||
|
||||
--- @generic U
|
||||
--- @param fn fun(value: T): U
|
||||
--- @return u.Signal --<U>
|
||||
--- @param fn fun(value: T): `U`
|
||||
--- @return u.Signal<U>
|
||||
function Signal:map(fn)
|
||||
local mapped_signal = M.create_memo(function()
|
||||
local value = self:get()
|
||||
@ -95,13 +96,13 @@ function Signal:map(fn)
|
||||
return mapped_signal
|
||||
end
|
||||
|
||||
--- @return u.Signal
|
||||
--- @return u.Signal<T>
|
||||
function Signal:clone()
|
||||
return self:map(function(x) return x end)
|
||||
end
|
||||
|
||||
--- @param fn fun(value: T): boolean
|
||||
--- @return u.Signal -- <T>
|
||||
--- @return u.Signal<T>
|
||||
function Signal:filter(fn)
|
||||
local filtered_signal = M.create_signal(nil, self.name and self.name .. ':filtered' or nil)
|
||||
local unsubscribe_from_self = self:subscribe(function(value)
|
||||
@ -112,10 +113,10 @@ function Signal:filter(fn)
|
||||
end
|
||||
|
||||
--- @param ms number
|
||||
--- @return u.Signal -- <T>
|
||||
--- @return u.Signal<T>
|
||||
function Signal:debounce(ms)
|
||||
local function set_timeout(timeout, callback)
|
||||
local timer = (vim.uv or vim.loop).new_timer()
|
||||
local timer = assert((vim.uv or vim.loop).new_timer(), 'could not create new timer')
|
||||
timer:start(timeout, 0, function()
|
||||
timer:stop()
|
||||
timer:close()
|
||||
@ -127,7 +128,7 @@ function Signal:debounce(ms)
|
||||
local filtered = M.create_signal(self.value, self.name and self.name .. ':debounced' or nil)
|
||||
|
||||
--- @diagnostic disable-next-line: undefined-doc-name
|
||||
--- @type { queued: { value: T, ts: number }[]; timer?: uv_timer_t; }
|
||||
--- @type { queued: { value: T, ts: number }[], timer?: uv.uv_timer_t }
|
||||
local state = { queued = {}, timer = nil }
|
||||
local function clear_timeout()
|
||||
if state.timer == nil then return end
|
||||
@ -202,6 +203,7 @@ end
|
||||
-- class ExecutionContext
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--- @type u.ExecutionContext|nil
|
||||
local CURRENT_CONTEXT = nil
|
||||
|
||||
--- @class u.ExecutionContext
|
||||
@ -262,16 +264,18 @@ end
|
||||
-- Helpers
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
--- @param value any
|
||||
--- @generic T
|
||||
--- @param value `T`
|
||||
--- @param name? string
|
||||
--- @return u.Signal
|
||||
--- @return u.Signal<T>
|
||||
function M.create_signal(value, name) return Signal:new(value, name) end
|
||||
|
||||
--- @param fn function
|
||||
--- @generic T
|
||||
--- @param fn fun(): `T`
|
||||
--- @param name? string
|
||||
--- @return u.Signal
|
||||
function M.create_memo(fn, name)
|
||||
--- @type u.Signal
|
||||
--- @type u.Signal<T> | nil
|
||||
local result
|
||||
local unsubscribe = M.create_effect(function()
|
||||
local value = fn()
|
||||
@ -282,8 +286,8 @@ function M.create_memo(fn, name)
|
||||
result = M.create_signal(value, name and ('m.s:' .. name) or nil)
|
||||
end
|
||||
end, name)
|
||||
result:on_dispose(unsubscribe)
|
||||
return result
|
||||
assert(result):on_dispose(unsubscribe)
|
||||
return assert(result)
|
||||
end
|
||||
|
||||
--- @param fn function
|
||||
|
Loading…
x
Reference in New Issue
Block a user