diff options
| -rw-r--r-- | lua/clever_f/motion_executor.lua | 4 | ||||
| -rw-r--r-- | tests/run.lua | 44 |
2 files changed, 48 insertions, 0 deletions
diff --git a/lua/clever_f/motion_executor.lua b/lua/clever_f/motion_executor.lua index afa3ee1..c22bed9 100644 --- a/lua/clever_f/motion_executor.lua +++ b/lua/clever_f/motion_executor.lua @@ -76,6 +76,7 @@ local function require_host(host) or type(host.read_cursor) ~= "function" or type(host.read_selection) ~= "function" or type(host.apply_cursor) ~= "function" + or type(host.apply_selection) ~= "function" then fail("MotionExecutor host must provide movement state", 3) end @@ -245,6 +246,9 @@ function MotionExecutor:_execute_visual(request) local origin = host:read_cursor() local outcome = calculate(self, request, origin) request.selection = selection + if outcome.successful_steps > 0 then + host:apply_selection(selection:with_focus(outcome.endpoint)) + end return domain.ActionOutcome.from_search(outcome, request.plan.descriptor) end diff --git a/tests/run.lua b/tests/run.lua index 957a4bb..725fe98 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -3375,6 +3375,50 @@ test("Visual calculation retains the active selection", function() same(active, host:read_selection()) end) +test("Visual execution applies exact endpoints for every selection kind", function() + local origin = domain.Position.new(1, 1) + local destination = domain.Position.new(1, 3) + local cases = { + { mode = "v", kind = domain.SelectionKind.CHARACTER }, + { mode = "V", kind = domain.SelectionKind.LINE }, + { mode = string.char(0x16), kind = domain.SelectionKind.BLOCK }, + } + + for _, case in ipairs(cases) do + local host = MemoryHost.new({ + buffer_lines = { "abx" }, + cursor = origin, + mode = case.mode, + selection = domain.Selection.active( + case.kind, + origin, + origin, + domain.SelectionOption.INCLUSIVE + ), + }) + local plan = motion_plan.build( + target_plan.build(target("x"), matching_policy()), + "f" + ) + local outcome = motion_executor.new(host):execute( + text_topology.from_host(host), + case.mode, + plan, + 1, + true + ) + local selection = host:read_selection() + + same(domain.ActionKind.MOVEMENT, outcome.kind, case.mode) + same(destination, outcome.position, case.mode) + truthy(selection.active, case.mode) + same(case.kind, selection.kind, case.mode) + same(origin, selection.anchor, case.mode) + same(destination, selection.focus, case.mode) + same(destination, host:read_cursor(), case.mode) + end +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then |
