Skip to content

Commit 85b432a

Browse files
committed
feat(ui): config option to override buffer switching logic
1 parent aee5fbb commit 85b432a

2 files changed

Lines changed: 60 additions & 46 deletions

File tree

lua/fff/conf.lua

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ local M = {}
5555
--- @field time_budget_ms number
5656
--- @field modes string[]
5757

58+
--- @alias FffSelectAction 'edit' | 'split' | 'vsplit' | 'tabedit'
59+
60+
--- @class FffSelectConfig
61+
--- @field pre_select_hook fun(current_buf: integer, action: FffSelectAction)
62+
5863
--- @class FffConfig
5964
--- @field base_path string
6065
--- @field prompt string
@@ -68,6 +73,7 @@ local M = {}
6873
--- @field hl table<string, string>
6974
--- @field frecency FffFrecencyConfig
7075
--- @field history FffHistoryConfig
76+
--- @field select FffSelectConfig
7177
--- @field git table
7278
--- @field debug table
7379
--- @field logging table
@@ -186,6 +192,42 @@ local function fallback_hl(name)
186192
return resolved_hl or name[#name]
187193
end
188194

195+
--- Find the first visible window with a normal file buffer
196+
--- @return number|nil Window ID of the first suitable window, or nil if none found
197+
local function find_suitable_window()
198+
local current_tabpage = vim.api.nvim_get_current_tabpage()
199+
local windows = vim.api.nvim_tabpage_list_wins(current_tabpage)
200+
201+
for _, win in ipairs(windows) do
202+
if vim.api.nvim_win_is_valid(win) then
203+
local buf = vim.api.nvim_win_get_buf(win)
204+
if vim.api.nvim_buf_is_valid(buf) then
205+
local buftype = vim.api.nvim_get_option_value('buftype', { buf = buf })
206+
local modifiable = vim.api.nvim_get_option_value('modifiable', { buf = buf })
207+
local filetype = vim.api.nvim_get_option_value('filetype', { buf = buf })
208+
209+
local is_picker_window = (
210+
win == M.state.input_win
211+
or win == M.state.list_win
212+
or win == M.state.preview_win
213+
or win == M.state.file_info_win
214+
)
215+
216+
if
217+
(buftype == '' or buftype == 'acwrite')
218+
and modifiable
219+
and not is_picker_window
220+
and filetype ~= 'undotree'
221+
then
222+
return win
223+
end
224+
end
225+
end
226+
end
227+
228+
return nil
229+
end
230+
189231
local function init()
190232
local config = vim.g.fff or {}
191233
local default_config = {
@@ -308,6 +350,21 @@ local function init()
308350
min_combo_count = 3, -- Minimum selections before combo boost applies (3 = boost starts on 3rd selection)
309351
combo_boost_score_multiplier = 100, -- Score multiplier for combo matches (files repeatedly opened with same query)
310352
},
353+
select = {
354+
--- @param current_buf integer
355+
--- @param action FffSelectAction
356+
pre_select_hook = function(current_buf, action)
357+
if action ~= 'edit' then return end
358+
local current_buftype = vim.api.nvim_get_option_value('buftype', { buf = current_buf })
359+
local current_buf_modifiable = vim.api.nvim_get_option_value('modifiable', { buf = current_buf })
360+
361+
-- If current active buffer is not a normal buffer we find a suitable window with a tab otherwise opening a new split
362+
if current_buftype ~= '' or not current_buf_modifiable then
363+
local suitable_win = find_suitable_window()
364+
if suitable_win then vim.api.nvim_set_current_win(suitable_win) end
365+
end
366+
end,
367+
},
311368
-- Git integration
312369
git = {
313370
status_text_color = false, -- Apply git status colors to filename text (default: false, only sign column)

lua/fff/picker_ui.lua

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2100,42 +2100,6 @@ function M.recall_query_from_history()
21002100
end)
21012101
end
21022102

2103-
--- Find the first visible window with a normal file buffer
2104-
--- @return number|nil Window ID of the first suitable window, or nil if none found
2105-
local function find_suitable_window()
2106-
local current_tabpage = vim.api.nvim_get_current_tabpage()
2107-
local windows = vim.api.nvim_tabpage_list_wins(current_tabpage)
2108-
2109-
for _, win in ipairs(windows) do
2110-
if vim.api.nvim_win_is_valid(win) then
2111-
local buf = vim.api.nvim_win_get_buf(win)
2112-
if vim.api.nvim_buf_is_valid(buf) then
2113-
local buftype = vim.api.nvim_get_option_value('buftype', { buf = buf })
2114-
local modifiable = vim.api.nvim_get_option_value('modifiable', { buf = buf })
2115-
local filetype = vim.api.nvim_get_option_value('filetype', { buf = buf })
2116-
2117-
local is_picker_window = (
2118-
win == M.state.input_win
2119-
or win == M.state.list_win
2120-
or win == M.state.preview_win
2121-
or win == M.state.file_info_win
2122-
)
2123-
2124-
if
2125-
(buftype == '' or buftype == 'acwrite')
2126-
and modifiable
2127-
and not is_picker_window
2128-
and filetype ~= 'undotree'
2129-
then
2130-
return win
2131-
end
2132-
end
2133-
end
2134-
end
2135-
2136-
return nil
2137-
end
2138-
21392103
--- Build a unique key for a grep match occurrence.
21402104
--- Format: "path:line:col" — uniquely identifies one match entry.
21412105
---@param item table Grep match item with path, line_number, col
@@ -2330,17 +2294,10 @@ function M.select(action)
23302294
vim.cmd('stopinsert')
23312295
M.close()
23322296

2333-
if action == 'edit' then
2334-
local current_buf = vim.api.nvim_get_current_buf()
2335-
local current_buftype = vim.api.nvim_get_option_value('buftype', { buf = current_buf })
2336-
local current_buf_modifiable = vim.api.nvim_get_option_value('modifiable', { buf = current_buf })
2337-
2338-
-- If current active buffer is not a normal buffer we find a suitable window with a tab otherwise opening a new split
2339-
if current_buftype ~= '' or not current_buf_modifiable then
2340-
local suitable_win = find_suitable_window()
2341-
if suitable_win then vim.api.nvim_set_current_win(suitable_win) end
2342-
end
2297+
local current_buf = vim.api.nvim_get_current_buf()
2298+
M.state.config.pre_select_hook(current_buf, action)
23432299

2300+
if action == 'edit' then
23442301
vim.cmd('edit ' .. vim.fn.fnameescape(relative_path))
23452302
elseif action == 'split' then
23462303
vim.cmd('split ' .. vim.fn.fnameescape(relative_path))

0 commit comments

Comments
 (0)