diff options
| -rw-r--r-- | lua/clever_f/direct_preview_planner.lua | 64 | ||||
| -rw-r--r-- | tests/run.lua | 18 |
2 files changed, 82 insertions, 0 deletions
diff --git a/lua/clever_f/direct_preview_planner.lua b/lua/clever_f/direct_preview_planner.lua new file mode 100644 index 0000000..7ead43f --- /dev/null +++ b/lua/clever_f/direct_preview_planner.lua @@ -0,0 +1,64 @@ +local domain = require("clever_f.domain") +local text_topology = require("clever_f.text_topology") + +local M = {} +local DirectPreviewPlanner = {} +DirectPreviewPlanner.__index = DirectPreviewPlanner +M.DirectPreviewPlanner = DirectPreviewPlanner + +local planner_records = setmetatable({}, { __mode = "k" }) + +local function fail(message, level) + error(message, (level or 1) + 1) +end + +local function require_view(view) + if not text_topology.TextView.is(view) then + fail("direct preview text must be a TextView", 3) + end + return view +end + +function DirectPreviewPlanner.new() + local planner = setmetatable({}, DirectPreviewPlanner) + planner_records[planner] = true + return planner +end + +function DirectPreviewPlanner.is(value) + return type(value) == "table" and planner_records[value] == true +end + +function DirectPreviewPlanner:scan_current_line(view, origin, direction) + require_view(view) + origin = domain.Position.coerce(origin) + direction = domain.Direction.from_string(direction) + local records = {} + for position, character, span in view:iterate( + direction, + view:line_match_start_bounds(origin.line) + ) do + records[#records + 1] = { + position = position, + character = character, + span = span, + } + end + return records +end + +function M.new() + return DirectPreviewPlanner.new() +end + +function M.scan_current_line(view, origin, direction) + return DirectPreviewPlanner.new():scan_current_line(view, origin, direction) +end + +setmetatable(M, { + __call = function() + return DirectPreviewPlanner.new() + end, +}) + +return M diff --git a/tests/run.lua b/tests/run.lua index 7ca4e3c..e16f082 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -9,6 +9,7 @@ package.path = table.concat({ local domain = require("clever_f.domain") local capabilities = require("clever_f.capabilities") local destination_engine = require("clever_f.destination_engine") +local direct_preview_planner = require("clever_f.direct_preview_planner") local feedback_service = require("clever_f.feedback_service") local case_policy = require("clever_f.case_policy") local policy = require("clever_f.policy") @@ -4540,6 +4541,23 @@ test("Cursor suppression requires policy and runtime support", function() same(1, operation_count(enabled, "suppress_cursor_presentation")) end) +test("Direct preview scanning stays on the cursor line", function() + local view = text_topology.new({ "abc", "de", "fgh" }, "utf-8") + local planner = direct_preview_planner.new() + truthy(direct_preview_planner.DirectPreviewPlanner.is(planner)) + + local records = planner:scan_current_line( + view, + domain.Position.new(2, 2), + domain.Direction.FORWARD + ) + same(2, #records) + same(domain.Position.new(2, 1), records[1].position) + same("d", records[1].character) + same(domain.Position.new(2, 2), records[2].position) + same("e", records[2].character) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then |
