From 01caae6671f456d898f20d1ea29c3315c93f01f2 Mon Sep 17 00:00:00 2001 From: Jackson Moore Date: Fri, 4 Sep 2026 11:42:30 +0200 Subject: Count exact preview characters --- lua/clever_f/direct_preview_planner.lua | 22 ++++++++++++++++++++++ tests/run.lua | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/lua/clever_f/direct_preview_planner.lua b/lua/clever_f/direct_preview_planner.lua index e81d941..9a6b0d2 100644 --- a/lua/clever_f/direct_preview_planner.lua +++ b/lua/clever_f/direct_preview_planner.lua @@ -72,6 +72,24 @@ function DirectPreviewPlanner:scan_for_descriptor(view, origin, descriptor) ) end +local function increment_counter(counters, character) + local value = (counters[character] or 0) + 1 + counters[character] = value + return value +end + +function DirectPreviewPlanner:plan(view, origin, descriptor, count) + local selected_occurrence = self:normalize_count(count) + local counters = {} + local positions = {} + for _, record in ipairs(self:scan_for_descriptor(view, origin, descriptor)) do + if increment_counter(counters, record.character) == selected_occurrence then + positions[#positions + 1] = record.position + end + end + return positions +end + function M.new() return DirectPreviewPlanner.new() end @@ -84,6 +102,10 @@ function M.scan_for_descriptor(view, origin, descriptor) return DirectPreviewPlanner.new():scan_for_descriptor(view, origin, descriptor) end +function M.plan(view, origin, descriptor, count) + return DirectPreviewPlanner.new():plan(view, origin, descriptor, count) +end + setmetatable(M, { __call = function() return DirectPreviewPlanner.new() diff --git a/tests/run.lua b/tests/run.lua index 7c4c52d..7ec0baf 100644 --- a/tests/run.lua +++ b/tests/run.lua @@ -4625,6 +4625,30 @@ test("Direct preview count normalizes absent and entered values", function() end, "positive integer") end) +test("Default direct previews count each exact character", function() + local view = text_topology.new({ "pOge huga Hiyo pOyo" }, "utf-8") + local planner = direct_preview_planner.new() + local origin = domain.Position.new(1, 1) + + local function columns(positions) + local result = {} + for index, position in ipairs(positions) do + result[index] = position.byte_column + end + return result + end + + list_same( + { 2, 3, 4, 5, 6, 7, 9, 11, 12, 13, 14, 16 }, + columns(planner:plan(view, origin, "f", 1)) + ) + list_same( + { 8, 10, 17, 18, 19 }, + columns(planner:plan(view, origin, "f", 2)) + ) + list_same({ 15 }, columns(planner:plan(view, origin, "f", 3))) +end) + for _, item in ipairs(tests) do local ok, failure = xpcall(item.body, debug.traceback) if not ok then -- cgit v1.2.3