(Range) preserve visual selection orientation in from_motion
Some checks failed
ci / ci (push) Failing after 1m7s
Some checks failed
ci / ci (push) Failing after 1m7s
This commit is contained in:
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -2,7 +2,3 @@
|
|||||||
path = library/busted
|
path = library/busted
|
||||||
url = https://github.com/LuaCATS/busted
|
url = https://github.com/LuaCATS/busted
|
||||||
branch = main
|
branch = main
|
||||||
[submodule "library/luv"]
|
|
||||||
path = library/luv
|
|
||||||
url = https://github.com/LuaCATS/luv
|
|
||||||
branch = main
|
|
||||||
|
|||||||
Submodule library/luv deleted from 3615eb12c9
26
lua/u.lua
26
lua/u.lua
@@ -542,6 +542,7 @@ function Range.from_motion(motion, opts)
|
|||||||
local is_bracket_txtobj = is_txtobj and BRACKET_MAP[motion_rest] ~= nil
|
local is_bracket_txtobj = is_txtobj and BRACKET_MAP[motion_rest] ~= nil
|
||||||
|
|
||||||
-- SECTION: Capture original state for restoration
|
-- SECTION: Capture original state for restoration
|
||||||
|
local vinf, vinf_inverted = Range.from_vtext()
|
||||||
local original_state = {
|
local original_state = {
|
||||||
winview = vim.fn.winsaveview(),
|
winview = vim.fn.winsaveview(),
|
||||||
unnamed_register = vim.fn.getreg '"',
|
unnamed_register = vim.fn.getreg '"',
|
||||||
@@ -551,7 +552,8 @@ function Range.from_motion(motion, opts)
|
|||||||
opfunc = vim.go.operatorfunc,
|
opfunc = vim.go.operatorfunc,
|
||||||
prev_captured_range = _G.Range__from_motion_opfunc_captured_range,
|
prev_captured_range = _G.Range__from_motion_opfunc_captured_range,
|
||||||
prev_mode = vim.fn.mode(),
|
prev_mode = vim.fn.mode(),
|
||||||
vinf = Range.from_vtext(),
|
vinf = vinf,
|
||||||
|
vinf_inverted = vinf_inverted,
|
||||||
}
|
}
|
||||||
--- @type u.Range|nil
|
--- @type u.Range|nil
|
||||||
_G.Range__from_motion_opfunc_captured_range = nil
|
_G.Range__from_motion_opfunc_captured_range = nil
|
||||||
@@ -603,7 +605,9 @@ function Range.from_motion(motion, opts)
|
|||||||
vim.fn.setpos('.', original_state.cursor)
|
vim.fn.setpos('.', original_state.cursor)
|
||||||
vim.fn.setpos("'[", original_state.mark_lbracket)
|
vim.fn.setpos("'[", original_state.mark_lbracket)
|
||||||
vim.fn.setpos("']", original_state.mark_rbracket)
|
vim.fn.setpos("']", original_state.mark_rbracket)
|
||||||
if original_state.prev_mode ~= 'n' then original_state.vinf:set_visual_selection() end
|
if original_state.prev_mode ~= 'n' then
|
||||||
|
original_state.vinf:set_visual_selection(original_state.vinf_inverted)
|
||||||
|
end
|
||||||
vim.go.operatorfunc = original_state.opfunc
|
vim.go.operatorfunc = original_state.opfunc
|
||||||
_G.Range__from_motion_opfunc_captured_range = original_state.prev_captured_range
|
_G.Range__from_motion_opfunc_captured_range = original_state.prev_captured_range
|
||||||
|
|
||||||
@@ -663,7 +667,8 @@ end
|
|||||||
function Range.from_vtext()
|
function Range.from_vtext()
|
||||||
local r = Range.from_marks('v', '.')
|
local r = Range.from_marks('v', '.')
|
||||||
if vim.fn.mode() == 'V' then r = r:to_linewise() end
|
if vim.fn.mode() == 'V' then r = r:to_linewise() end
|
||||||
return r
|
local inverted = Pos.from_pos '.' ~= r.stop
|
||||||
|
return r, inverted
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get range information from the current text range being operated on
|
--- Get range information from the current text range being operated on
|
||||||
@@ -806,18 +811,23 @@ end
|
|||||||
|
|
||||||
function Range:save_to_extmark() return Extmark.from_range(self, NS) end
|
function Range:save_to_extmark() return Extmark.from_range(self, NS) end
|
||||||
|
|
||||||
function Range:set_visual_selection()
|
--- @param inverted boolean?
|
||||||
|
function Range:set_visual_selection(inverted)
|
||||||
if self:is_empty() then return end
|
if self:is_empty() then return end
|
||||||
if vim.api.nvim_get_current_buf() ~= self.start.bufnr then
|
if vim.api.nvim_get_current_buf() ~= self.start.bufnr then
|
||||||
error 'Range:set_visual_selection() called on a buffer other than the current buffer'
|
error 'Range:set_visual_selection() called on a buffer other than the current buffer'
|
||||||
end
|
end
|
||||||
|
|
||||||
local curr_mode = vim.fn.mode()
|
local curr_mode = vim.fn.mode():sub(1, 1)
|
||||||
if curr_mode ~= self.mode then vim.cmd.normal { args = { self.mode }, bang = true } end
|
if curr_mode ~= self.mode then vim.cmd.normal { args = { ESC .. self.mode }, bang = true } end
|
||||||
|
|
||||||
self.start:save_to_pos '.'
|
local start, stop = self.start, self.stop
|
||||||
|
if inverted then
|
||||||
|
start, stop = stop, start
|
||||||
|
end
|
||||||
|
start:save_to_pos '.'
|
||||||
vim.cmd.normal { args = { 'o' }, bang = true }
|
vim.cmd.normal { args = { 'o' }, bang = true }
|
||||||
self.stop:save_to_pos '.'
|
stop:save_to_pos '.'
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -468,6 +468,42 @@ describe('Range', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('from_motion preserves visual selection orientation (cursor at start)', function()
|
||||||
|
withbuf({ 'the quick brown fox' }, function()
|
||||||
|
vim.fn.setpos('.', { 0, 1, 5, 0 })
|
||||||
|
vim.cmd.normal 'v'
|
||||||
|
vim.cmd.normal { args = { 'o' }, bang = true }
|
||||||
|
vim.fn.setpos('.', { 0, 1, 3, 0 })
|
||||||
|
vim.cmd.normal { args = { 'o' }, bang = true }
|
||||||
|
|
||||||
|
vim.cmd.normal { args = { 'o' }, bang = true }
|
||||||
|
local cursor_before = vim.fn.getpos('.')[3]
|
||||||
|
|
||||||
|
Range.from_motion 'aw'
|
||||||
|
|
||||||
|
vim.cmd.normal { args = { 'o' }, bang = true }
|
||||||
|
local cursor_after = vim.fn.getpos('.')[3]
|
||||||
|
|
||||||
|
assert.are_not_same(cursor_before, cursor_after)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('from_motion preserves visual selection orientation (cursor at stop)', function()
|
||||||
|
withbuf({ 'the quick brown fox' }, function()
|
||||||
|
vim.fn.setpos('.', { 0, 1, 3, 0 })
|
||||||
|
vim.cmd.normal 'vll'
|
||||||
|
|
||||||
|
local cursor_before = vim.fn.getpos('.')[3]
|
||||||
|
|
||||||
|
Range.from_motion 'aw'
|
||||||
|
|
||||||
|
vim.cmd.normal { args = { 'o' }, bang = true }
|
||||||
|
local cursor_after = vim.fn.getpos('.')[3]
|
||||||
|
|
||||||
|
assert.are_not_same(cursor_before, cursor_after)
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
describe('from_motion with max_lines', function()
|
describe('from_motion with max_lines', function()
|
||||||
it('returns nil when bracket chars are beyond max_lines', function()
|
it('returns nil when bracket chars are beyond max_lines', function()
|
||||||
-- A large block where { and } are far from cursor
|
-- A large block where { and } are far from cursor
|
||||||
|
|||||||
Reference in New Issue
Block a user