Skip to content

Commit 3cbf3fa

Browse files
committed
feat: Boost recently used files in snacks picker
Frequently and recently modified org files now rank higher in ambiguous fuzzy matches. This addresses a common pain point with similar-looking entries like dailies, where the fuzzy matcher alone cannot disambiguate reliably. The boost is intentionally subtle — capped to bridge small score differences without overriding clear match quality. It uses the snacks picker's native frecency mechanism plus mtime-based seeding for files not yet visited in the current session. A new toggle makes per-item scoring visible on demand, prepending raw score and frecency values to each result. Useful for tuning expectations and exploring what ranking heuristics would help for specific workflows.
1 parent 94aef63 commit 3cbf3fa

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

lua/telescope-orgmode/adapters/snacks.lua

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ local function create_finder(state, opts)
115115
file = raw_entry.filename,
116116
pos = { raw_entry.headline.line_number, 0 }, -- {line, col} for preview positioning
117117
preview = 'file', -- Tell preview to use file previewer
118+
-- Enable mtime-based frecency seed for files not yet visited
119+
recent = true,
118120
-- Store original entry data for actions
119121
__entry = raw_entry,
120122
})
@@ -134,6 +136,8 @@ local function create_finder(state, opts)
134136
text = search_text,
135137
file = raw_entry.filename,
136138
preview = 'file', -- Tell preview to use file previewer
139+
-- Enable mtime-based frecency seed for files not yet visited
140+
recent = true,
137141
-- Store original entry data for actions
138142
__entry = raw_entry,
139143
})
@@ -144,14 +148,25 @@ end
144148

145149
---Custom format function for items with pre-formatted segments
146150
---@param item table
151+
---@param _picker table? Snacks picker (unused, passed by Snacks)
152+
---@param debug_scoring boolean? When true, prepend score/frecency debug info
147153
---@return table[] Array of highlight segments
148-
local function format_item(item)
149-
-- Return pre-formatted segments if available
150-
if item._formatted then
151-
return item._formatted
154+
local function format_item(item, _picker, debug_scoring)
155+
local segments = item._formatted or { { item.text or tostring(item) } }
156+
157+
if debug_scoring then
158+
-- Build debug prefix: [score=X.X frec=X.X]
159+
local score = item.score or 0
160+
local frecency = item.frecency or 0
161+
local debug_text = string.format('[s=%6.1f f=%4.1f] ', score, frecency)
162+
local debug_segments = { { debug_text, 'WarningMsg' } }
163+
for _, seg in ipairs(segments) do
164+
table.insert(debug_segments, seg)
165+
end
166+
return debug_segments
152167
end
153-
-- Fallback to plain text
154-
return { { item.text or tostring(item) } }
168+
169+
return segments
155170
end
156171

157172
---Navigate to selected item
@@ -285,6 +300,7 @@ local function create_picker(state, picker_type, base_opts, preserved_query)
285300
'filter_all_buffers',
286301
'filter_headline_file',
287302
'drop_filters',
303+
'toggle_debug_scoring',
288304
}, {
289305
toggle_mode = function(picker)
290306
toggle_mode(state, picker_type, base_opts, picker)
@@ -302,18 +318,25 @@ local function create_picker(state, picker_type, base_opts, preserved_query)
302318
ctx.selected_entry = item and (item.__entry or item)
303319
end),
304320
drop_filters = filter_handler('drop_filters'),
321+
toggle_debug_scoring = filter_handler('toggle_debug_scoring'),
305322
})
306323

307324
-- Build title with filter context
308325
local base_title = picker_config.prompt_titles[mode]
309326
local full_title = state:get_full_title(base_title)
310327

328+
local debug_scoring = state:get_filter('debug_scoring') or false
329+
311330
local picker_opts = {
312331
title = full_title,
313332
items = items,
314333
pattern = preserved_query or '',
315334
preview = 'preview', -- Use default file previewer
316-
format = format_item, -- Custom formatter with highlights
335+
-- Enable native frecency-based scoring boost (subtle tiebreaker for ambiguous matches)
336+
frecency = true,
337+
format = function(item, picker)
338+
return format_item(item, picker, debug_scoring)
339+
end,
317340
win = {
318341
input = {
319342
keys = keys,

lua/telescope-orgmode/lib/keybindings.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ M.bindings = {
4444
description = 'Clear all filters',
4545
modes = { i = '<C-f><C-d>', n = '<C-f><C-d>' },
4646
},
47+
toggle_debug_scoring = {
48+
description = 'Toggle scoring debug display',
49+
modes = { i = '<C-h><C-d>', n = '<C-h><C-d>' },
50+
},
4751
}
4852

4953
---Execute keybinding action (framework-agnostic logic)
@@ -100,6 +104,10 @@ function M.execute_action(action_name, context)
100104
context.state:set_filter('current_files', {})
101105
context.state:set_filter('only_current_file', nil)
102106
context.refresh_fn(context.state)
107+
elseif action_name == 'toggle_debug_scoring' then
108+
local current = context.state:get_filter('debug_scoring')
109+
context.state:set_filter('debug_scoring', not current)
110+
context.refresh_fn(context.state)
103111
end
104112
end
105113

0 commit comments

Comments
 (0)