(Range.from_cmd_args) more correct handling
All checks were successful
NeoVim tests / code-quality (push) Successful in 1m22s

This commit is contained in:
Jonathan Apodaca 2025-06-16 20:43:41 -06:00
parent 933c187148
commit 28714fb51b
3 changed files with 92 additions and 17 deletions

View File

@ -249,19 +249,22 @@ end
--- @param args unknown
--- @return u.Range|nil
function Range.from_cmd_args(args)
--- @type 'v'|'V'
local mode
--- @type nil|u.Pos
local start
local stop
if args.range == 0 then
return nil
else
start = Pos.from_pos "'<"
stop = Pos.from_pos "'>"
mode = stop:is_col_max() and 'V' or 'v'
if args.range == 0 then return nil end
local bufnr = vim.api.nvim_get_current_buf()
if args.range == 1 then
return Range.new(Pos.new(bufnr, args.line1, 1), Pos.new(bufnr, args.line1, Pos.MAX_COL), 'V')
end
local is_visual = vim.fn.histget('cmd', -1):sub(1, 5) == [['<,'>]]
--- @type 'v'|'V'
local mode = is_visual and vim.fn.visualmode() or 'V'
if is_visual then
return Range.new(Pos.from_pos "'<", Pos.from_pos "'>", mode)
else
return Range.new(Pos.new(bufnr, args.line1, 1), Pos.new(bufnr, args.line2, Pos.MAX_COL), mode)
end
return Range.new(start, stop, mode)
end
function Range.find_nearest_brackets()

View File

@ -526,7 +526,8 @@ function TreeBuilder:nest(fn)
return self
end
--- @param arr <T>[]
--- @generic T
--- @param arr T[]
--- @param f fun(tb: u.renderer.TreeBuilder, item: T, idx: number): any
function TreeBuilder:ipairs(arr, f)
return self:nest(function(tb)

View File

@ -318,18 +318,89 @@ describe('Range', function()
end)
end)
it('from_cmd_args', function()
local args = { range = 1 }
it('from_cmd_args: range=0', function()
local args = { range = 0 }
withbuf(
{ 'line one', 'and line two' },
function() assert.are.same(Range.from_cmd_args(args), nil) end
)
end)
it('from_cmd_args: range=1', function()
local args = { range = 1, line1 = 1 }
withbuf({ 'line one', 'and line two' }, function()
local a = Pos.new(nil, 1, 1)
local b = Pos.new(nil, 2, 2)
local b = Pos.new(nil, 1, Pos.MAX_COL)
local range = Range.from_cmd_args(args) --[[@as u.Range]]
assert.are.same(range.start, a)
assert.are.same(range.stop, b)
assert.are.same(range.mode, 'V')
assert.are.same(range:text(), 'line one')
end)
end)
it('from_cmd_args: range=2: no-visual', function()
local args = { range = 2, line1 = 1, line2 = 2 }
withbuf({ 'line one', 'and line two' }, function()
local range = Range.from_cmd_args(args) --[[@as u.Range]]
assert.are.same(range.start, Pos.new(nil, 1, 1))
assert.are.same(range.stop, Pos.new(nil, 2, Pos.MAX_COL))
assert.are.same(range.mode, 'V')
assert.are.same(range:text(), 'line one\nand line two')
end)
end)
it('from_cmd_args: range=2: visual: linewise', function()
local args = { range = 2, line1 = 1, line2 = 2 }
withbuf({ 'line one', 'and line two' }, function()
local a = Pos.new(nil, 1, 1)
local b = Pos.new(nil, 2, Pos.MAX_COL)
a:save_to_pos "'<"
b:save_to_pos "'>"
local range = Range.from_cmd_args(args) --[[@as u.Range]]
assert.are.same(range.start, a)
assert.are.same(range.stop, b)
assert.are.same(range.mode, 'V')
assert.are.same(range:text(), 'line one\nand line two')
end)
end)
local range = Range.from_cmd_args(args)
it('from_cmd_args: range=2: visual: charwise', function()
local args = { range = 2, line1 = 1, line2 = 1 }
withbuf({ 'line one', 'and line two' }, function()
-- Simulate a visual selection:
local a = Pos.new(nil, 1, 1)
local b = Pos.new(nil, 1, 4)
a:save_to_pos "'<"
b:save_to_pos "'>"
Range.new(a, b, 'v'):set_visual_selection()
assert.are.same(vim.fn.mode(), 'v')
-- In this simulated setup, we need to force visualmode() to return
-- 'v' and histget() to return [['<,'>]]:
-- visualmode()
local orig_visualmode = vim.fn.visualmode
--- @diagnostic disable-next-line: duplicate-set-field
function vim.fn.visualmode() return 'v' end
assert.are.same(vim.fn.visualmode(), 'v')
-- histget()
local orig_histget = vim.fn.histget
--- @diagnostic disable-next-line: duplicate-set-field
function vim.fn.histget(x, y) return [['<,'>]] end
-- Now run the test:
local range = Range.from_cmd_args(args) --[[@as u.Range]]
assert.are.same(range.start, a)
assert.are.same(range.stop, b)
assert.are.same(range.mode, 'v')
assert.are.same(range:text(), 'line')
-- Reset visualmode() and histget():
vim.fn.visualmode = orig_visualmode
vim.fn.histget = orig_histget
end)
end)