summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/motion_plan.lua66
-rw-r--r--tests/run.lua74
2 files changed, 140 insertions, 0 deletions
diff --git a/lua/clever_f/motion_plan.lua b/lua/clever_f/motion_plan.lua
index 362b978..1d0b4e3 100644
--- a/lua/clever_f/motion_plan.lua
+++ b/lua/clever_f/motion_plan.lua
@@ -91,6 +91,54 @@ function MotionPlanFactory:build(
})
end
+local function selection_option(selection)
+ if selection == nil then
+ return domain.SelectionOption.INCLUSIVE
+ end
+ if domain.Selection.is(selection) then
+ return selection.option
+ end
+ if domain.SelectionOption.is(selection) then
+ return selection
+ end
+ if type(selection) == "table" and selection.option ~= nil then
+ return domain.SelectionOption.from_string(selection.option)
+ end
+ return domain.SelectionOption.from_string(selection)
+end
+
+function M.endpoint_policy(context, selection)
+ context = domain.ModeContext.from_full_mode(context)
+ local option = selection_option(selection)
+ local visual_kind = context.visual_kind
+ if option == domain.SelectionOption.EXCLUSIVE
+ and (visual_kind == domain.SelectionKind.CHARACTER
+ or visual_kind == domain.SelectionKind.LINE)
+ then
+ return domain.EndpointPolicy.VISUAL_EXCLUSIVE
+ end
+ return domain.EndpointPolicy.REGULAR
+end
+
+function MotionPlanFactory:endpoint_policy(context, selection)
+ return M.endpoint_policy(context, selection)
+end
+
+function MotionPlanFactory:build_for_context(
+ target_plan,
+ effective_descriptor,
+ context,
+ selection,
+ search_scope
+)
+ return self:build(
+ target_plan,
+ effective_descriptor,
+ search_scope,
+ self:endpoint_policy(context, selection)
+ )
+end
+
function M.new(options)
return MotionPlanFactory.new(options)
end
@@ -110,8 +158,26 @@ function M.build(
)
end
+function M.build_for_context(
+ target_plan,
+ effective_descriptor,
+ context,
+ selection,
+ search_scope,
+ options
+)
+ return MotionPlanFactory.new(options):build_for_context(
+ target_plan,
+ effective_descriptor,
+ context,
+ selection,
+ search_scope
+ )
+end
+
M.create = M.build
M.resolve = M.build
+M.for_context = M.build_for_context
setmetatable(M, {
__call = function(_, options)
diff --git a/tests/run.lua b/tests/run.lua
index f9fbeb8..60d6b5b 100644
--- a/tests/run.lua
+++ b/tests/run.lua
@@ -2495,6 +2495,80 @@ test("Forward Visual-exclusive TILL uses target positions", function()
)
end)
+test("MotionPlanFactory limits exclusive policy to character and line Visual", function()
+ local view = text_topology.new({ "axz" }, "utf-8")
+ local origin = domain.Position.new(1, 1)
+ local target_match = target_plan.build(target("x"), matching_policy())
+ local factory = motion_plan.new()
+ local engine = destination_engine.new()
+ local cases = {
+ { "v", domain.EndpointPolicy.VISUAL_EXCLUSIVE },
+ { "V", domain.EndpointPolicy.VISUAL_EXCLUSIVE },
+ { string.char(0x16), domain.EndpointPolicy.REGULAR },
+ { "s", domain.EndpointPolicy.REGULAR },
+ { "S", domain.EndpointPolicy.REGULAR },
+ { string.char(0x13), domain.EndpointPolicy.REGULAR },
+ { "n", domain.EndpointPolicy.REGULAR },
+ { "no", domain.EndpointPolicy.REGULAR },
+ }
+
+ for _, case in ipairs(cases) do
+ local context = domain.ModeContext.from_full_mode(case[1])
+ local kind = context.visual_kind or context.select_kind
+ local selection = kind ~= nil
+ and domain.Selection.active(
+ kind,
+ origin,
+ origin,
+ domain.SelectionOption.EXCLUSIVE
+ )
+ or domain.Selection.inactive(domain.SelectionOption.EXCLUSIVE)
+ local plan = factory:build_for_context(
+ target_match,
+ "f",
+ context,
+ selection,
+ domain.SearchScope.BUFFER
+ )
+ same(case[2], plan.endpoint_policy, case[1])
+ local expected_column = case[2] == domain.EndpointPolicy.VISUAL_EXCLUSIVE
+ and 3
+ or 2
+ same(
+ domain.Position.new(1, expected_column),
+ engine:calculate(view, origin, plan, 1, true).endpoint,
+ case[1]
+ )
+ end
+
+ local inclusive_visual = factory:build_for_context(
+ target_match,
+ "f",
+ "v",
+ domain.SelectionOption.INCLUSIVE,
+ "buffer"
+ )
+ same(domain.EndpointPolicy.REGULAR, inclusive_visual.endpoint_policy)
+
+ local exclusive_backward = factory:build_for_context(
+ target_match,
+ "F",
+ "v",
+ domain.SelectionOption.EXCLUSIVE,
+ "buffer"
+ )
+ same(
+ domain.Position.new(1, 2),
+ engine:calculate(
+ view,
+ domain.Position.new(1, 3),
+ exclusive_backward,
+ 1,
+ true
+ ).endpoint
+ )
+end)
+
for _, item in ipairs(tests) do
local ok, failure = xpcall(item.body, debug.traceback)
if not ok then