diff options
Diffstat (limited to 'lua/clever_f')
| -rw-r--r-- | lua/clever_f/direct_preview_planner.lua | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/lua/clever_f/direct_preview_planner.lua b/lua/clever_f/direct_preview_planner.lua index 9a6b0d2..51d7b18 100644 --- a/lua/clever_f/direct_preview_planner.lua +++ b/lua/clever_f/direct_preview_planner.lua @@ -1,3 +1,4 @@ +local case_policy = require("clever_f.case_policy") local domain = require("clever_f.domain") local text_topology = require("clever_f.text_topology") @@ -19,14 +20,37 @@ local function require_view(view) return view end -function DirectPreviewPlanner.new() +local function require_case_resolver(options) + options = options or {} + if type(options) == "function" then + options = { lowercase = options } + end + if type(options) ~= "table" then + fail("DirectPreviewPlanner options must be a table", 3) + end + local resolver = options.case_resolver + if resolver == nil then + resolver = case_policy.new({ lowercase = options.lowercase }) + end + if type(resolver) ~= "table" or type(resolver.lowercase) ~= "function" then + fail("DirectPreviewPlanner case resolver must provide lowercase", 3) + end + return resolver +end + +function DirectPreviewPlanner.new(options) + if DirectPreviewPlanner.is(options) then + return options + end local planner = setmetatable({}, DirectPreviewPlanner) - planner_records[planner] = true + planner_records[planner] = { + case_resolver = require_case_resolver(options), + } return planner end function DirectPreviewPlanner.is(value) - return type(value) == "table" and planner_records[value] == true + return type(value) == "table" and planner_records[value] ~= nil end function DirectPreviewPlanner:scan_current_line(view, origin, direction) @@ -78,20 +102,40 @@ local function increment_counter(counters, character) return value end -function DirectPreviewPlanner:plan(view, origin, descriptor, count) +local function require_case_setting(settings, name) + local value = settings[name] + if value == nil then + return false + end + if type(value) ~= "boolean" then + fail("direct preview " .. name .. " must be a Boolean", 3) + end + return value +end + +function DirectPreviewPlanner:plan(view, origin, descriptor, count, settings) + settings = settings or {} + if type(settings) ~= "table" then + fail("direct preview case settings must be a table", 2) + end + local ignore_case = require_case_setting(settings, "ignore_case") local selected_occurrence = self:normalize_count(count) local counters = {} local positions = {} + local resolver = planner_records[self].case_resolver for _, record in ipairs(self:scan_for_descriptor(view, origin, descriptor)) do - if increment_counter(counters, record.character) == selected_occurrence then + local counter_key = ignore_case + and resolver:lowercase(record.character) + or record.character + if increment_counter(counters, counter_key) == selected_occurrence then positions[#positions + 1] = record.position end end return positions end -function M.new() - return DirectPreviewPlanner.new() +function M.new(options) + return DirectPreviewPlanner.new(options) end function M.scan_current_line(view, origin, direction) @@ -102,13 +146,19 @@ 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) +function M.plan(view, origin, descriptor, count, settings, options) + return DirectPreviewPlanner.new(options):plan( + view, + origin, + descriptor, + count, + settings + ) end setmetatable(M, { - __call = function() - return DirectPreviewPlanner.new() + __call = function(_, options) + return DirectPreviewPlanner.new(options) end, }) |
