summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/clever_f/direct_preview_planner.lua64
-rw-r--r--tests/run.lua18
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