more cleanup
This commit is contained in:
parent
87930bf3af
commit
3fe84197c1
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
/.lux/
|
/.lux/
|
||||||
|
lux.lock
|
||||||
*.src.rock
|
*.src.rock
|
||||||
|
@ -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[]
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
vim.api.nvim_buf_call(opts.bufnr, function()
|
|
||||||
local original_state = {
|
local original_state = {
|
||||||
winview = vim.fn.winsaveview(),
|
winview = vim.fn.winsaveview(),
|
||||||
regquote = vim.fn.getreg '"',
|
regquote = vim.fn.getreg '"',
|
||||||
posdot = vim.fn.getpos '.',
|
cursor = vim.fn.getpos '.',
|
||||||
poslb = vim.fn.getpos "'[",
|
pos_lbrack = vim.fn.getpos "'[",
|
||||||
posrb = vim.fn.getpos "']",
|
pos_rbrack = vim.fn.getpos "']",
|
||||||
}
|
}
|
||||||
|
vim.api.nvim_buf_call(opts.bufnr, function()
|
||||||
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 "']"
|
||||||
|
end)
|
||||||
-- Restore original state:
|
-- Restore original state:
|
||||||
vim.fn.winrestview(original_state.winview)
|
vim.fn.winrestview(original_state.winview)
|
||||||
vim.fn.setreg('"', original_state.regquote)
|
vim.fn.setreg('"', original_state.regquote)
|
||||||
vim.fn.setpos('.', original_state.posdot)
|
vim.fn.setpos('.', original_state.cursor)
|
||||||
vim.fn.setpos("'[", original_state.poslb)
|
vim.fn.setpos("'[", original_state.pos_lbrack)
|
||||||
vim.fn.setpos("']", original_state.posrb)
|
vim.fn.setpos("']", original_state.pos_rbrack)
|
||||||
|
|
||||||
|
if start == stop and start:is_invalid() then return nil end
|
||||||
|
|
||||||
|
-- Fixup the bounds:
|
||||||
if
|
if
|
||||||
-- I have no idea why, but when yanking `i"`, the stop-mark is
|
-- I have no idea why, but when yanking `i"`, the stop-mark is
|
||||||
-- placed on the ending quote. For other text-objects, the stop-
|
-- placed on the ending quote. For other text-objects, the stop-
|
||||||
-- mark is placed before the closing character.
|
-- mark is placed before the closing character.
|
||||||
(is_quote and selection_type == 'i' and stop:char() == obj_type)
|
(is_quote_txtobj and scope == 'i' and stop:char() == motion_rest)
|
||||||
-- *Sigh*, this also sometimes happens for `it` as well.
|
-- *Sigh*, this also sometimes happens for `it` as well.
|
||||||
or (text_obj == 'it' and stop:char() == '<')
|
or (motion == 'it' and stop:char() == '<')
|
||||||
then
|
then
|
||||||
stop = stop:next(-1) or stop
|
stop = stop:next(-1) or stop
|
||||||
end
|
end
|
||||||
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 start == stop and start:is_invalid() then return nil end
|
if opts.contains_cursor and not Range.new(start, stop):contains(Pos.new(unpack(original_state.cursor))) then
|
||||||
if opts.contains_cursor and not Range.new(start, stop):contains(cursor) then return nil end
|
return nil
|
||||||
|
|
||||||
if is_quote and selection_type == 'a' then
|
|
||||||
start = start:find_next(1, obj_type) or start
|
|
||||||
stop = stop:find_next(-1, obj_type) or stop
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Range.new(start, stop)
|
return Range.new(start, stop)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user