more cleanup

This commit is contained in:
Jonathan Apodaca 2025-04-12 08:56:10 -06:00
parent 87930bf3af
commit 3fe84197c1
5 changed files with 47 additions and 44 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/.lux/ /.lux/
lux.lock
*.src.rock *.src.rock

View File

@ -67,11 +67,11 @@ end
--- @param stop number 1-based line index --- @param stop number 1-based line index
function Buffer:lines(start, stop) return Range.from_lines(self.bufnr, start, stop) end function Buffer:lines(start, stop) return Range.from_lines(self.bufnr, start, stop) end
--- @param txt_obj string --- @param motion string
--- @param opts? { contains_cursor?: boolean; pos?: u.Pos } --- @param opts? { contains_cursor?: boolean; pos?: u.Pos }
function Buffer:txtobj(txt_obj, opts) function Buffer:motion(motion, opts)
opts = vim.tbl_extend('force', opts or {}, { bufnr = self.bufnr }) opts = vim.tbl_extend('force', opts or {}, { bufnr = self.bufnr })
return Range.from_motion(txt_obj, opts) return Range.from_motion(motion, opts)
end end
--- @param event string|string[] --- @param event string|string[]

View File

@ -77,7 +77,7 @@ function Pos.from_pos(name)
return Pos.new(p[1], p[2], p[3], p[4]) return Pos.new(p[1], p[2], p[3], p[4])
end end
function Pos:is_invalid() return self.bufnr == 0 and self.lnum == 0 and self.col == 0 and self.off == 0 end function Pos:is_invalid() return self.lnum == 0 and self.col == 0 and self.off == 0 end
function Pos:clone() return Pos.new(self.bufnr, self.lnum, self.col, self.off) end function Pos:clone() return Pos.new(self.bufnr, self.lnum, self.col, self.off) end

View File

@ -92,35 +92,35 @@ function Range.from_lines(bufnr, start_line, stop_line)
return Range.new(Pos.new(bufnr, start_line, 1), Pos.new(bufnr, stop_line, Pos.MAX_COL), 'V') return Range.new(Pos.new(bufnr, start_line, 1), Pos.new(bufnr, stop_line, Pos.MAX_COL), 'V')
end end
--- @param text_obj string --- @param motion string
--- @param opts? { bufnr?: number; contains_cursor?: boolean; pos?: u.Pos, user_defined?: boolean } --- @param opts? { bufnr?: number; contains_cursor?: boolean; pos?: u.Pos, user_defined?: boolean }
--- @return u.Range|nil --- @return u.Range|nil
function Range.from_motion(text_obj, opts) function Range.from_motion(motion, opts)
-- Options handling:
opts = opts or {} opts = opts or {}
if opts.bufnr == nil then opts.bufnr = vim.api.nvim_get_current_buf() end if opts.bufnr == nil then opts.bufnr = vim.api.nvim_get_current_buf() end
if opts.contains_cursor == nil then opts.contains_cursor = false end if opts.contains_cursor == nil then opts.contains_cursor = false end
if opts.user_defined == nil then opts.user_defined = false end if opts.user_defined == nil then opts.user_defined = false end
--- @type "a" | "i" -- Extract some information from the motion:
local selection_type = text_obj:sub(1, 1) --- @type 'a'|'i', string
local obj_type = text_obj:sub(#text_obj, #text_obj) local scope, motion_rest = motion:sub(1, 1), motion:sub(2)
local is_quote = vim.tbl_contains({ "'", '"', '`' }, obj_type) local is_txtobj = scope == 'a' or scope == 'i'
local cursor = Pos.from_pos '.' local is_quote_txtobj = is_txtobj and vim.tbl_contains({ "'", '"', '`' }, motion_rest)
--- @type u.Pos --- @type u.Pos
local start local start
--- @type u.Pos --- @type u.Pos
local stop local stop
-- Capture the original state of the buffer for restoration later.
local original_state = {
winview = vim.fn.winsaveview(),
regquote = vim.fn.getreg '"',
cursor = vim.fn.getpos '.',
pos_lbrack = vim.fn.getpos "'[",
pos_rbrack = vim.fn.getpos "']",
}
vim.api.nvim_buf_call(opts.bufnr, function() vim.api.nvim_buf_call(opts.bufnr, function()
local original_state = {
winview = vim.fn.winsaveview(),
regquote = vim.fn.getreg '"',
posdot = vim.fn.getpos '.',
poslb = vim.fn.getpos "'[",
posrb = vim.fn.getpos "']",
}
if opts.pos ~= nil then opts.pos:save_to_pos '.' end if opts.pos ~= nil then opts.pos:save_to_pos '.' end
Pos.invalid():save_to_pos "'[" Pos.invalid():save_to_pos "'["
@ -131,39 +131,41 @@ function Range.from_motion(text_obj, opts)
vim.cmd { vim.cmd {
cmd = 'normal', cmd = 'normal',
bang = not opts.user_defined, bang = not opts.user_defined,
args = { '""y' .. text_obj }, args = { '""y' .. motion },
mods = { silent = true }, mods = { silent = true },
} }
on_yank_enabled = prev_on_yank_enabled on_yank_enabled = prev_on_yank_enabled
start = Pos.from_pos "'[" start = Pos.from_pos "'["
stop = Pos.from_pos "']" stop = Pos.from_pos "']"
-- Restore original state:
vim.fn.winrestview(original_state.winview)
vim.fn.setreg('"', original_state.regquote)
vim.fn.setpos('.', original_state.posdot)
vim.fn.setpos("'[", original_state.poslb)
vim.fn.setpos("']", original_state.posrb)
if
-- I have no idea why, but when yanking `i"`, the stop-mark is
-- placed on the ending quote. For other text-objects, the stop-
-- mark is placed before the closing character.
(is_quote and selection_type == 'i' and stop:char() == obj_type)
-- *Sigh*, this also sometimes happens for `it` as well.
or (text_obj == 'it' and stop:char() == '<')
then
stop = stop:next(-1) or stop
end
end) end)
-- Restore original state:
vim.fn.winrestview(original_state.winview)
vim.fn.setreg('"', original_state.regquote)
vim.fn.setpos('.', original_state.cursor)
vim.fn.setpos("'[", original_state.pos_lbrack)
vim.fn.setpos("']", original_state.pos_rbrack)
if start == stop and start:is_invalid() then return nil end if start == stop and start:is_invalid() then return nil end
if opts.contains_cursor and not Range.new(start, stop):contains(cursor) then return nil end
if is_quote and selection_type == 'a' then -- Fixup the bounds:
start = start:find_next(1, obj_type) or start if
stop = stop:find_next(-1, obj_type) or stop -- I have no idea why, but when yanking `i"`, the stop-mark is
-- placed on the ending quote. For other text-objects, the stop-
-- mark is placed before the closing character.
(is_quote_txtobj and scope == 'i' and stop:char() == motion_rest)
-- *Sigh*, this also sometimes happens for `it` as well.
or (motion == 'it' and stop:char() == '<')
then
stop = stop:next(-1) or stop
end
if is_quote_txtobj and scope == 'a' then
start = start:find_next(1, motion_rest) or start
stop = stop:find_next(-1, motion_rest) or stop
end
if opts.contains_cursor and not Range.new(start, stop):contains(Pos.new(unpack(original_state.cursor))) then
return nil
end end
return Range.new(start, stop) return Range.new(start, stop)

View File

@ -1,5 +1,5 @@
package = "u.nvim" package = "u.nvim"
version = "0.1.0" version = "0.2.0"
lua = ">=5.1" lua = ">=5.1"
[description] [description]