@@ -77,6 +77,48 @@ M.globals = setmetatable({}, {
7777 local function setup_defaults ()
7878 return M ._profile_opts and (M ._profile_opts .defaults or {}) or M .setup_opts .defaults or {}
7979 end
80+ local special_tbl = function (opts , k )
81+ local fzflua_default = utils .map_get (M .defaults , k )
82+ local setup_default = utils .map_get (setup_defaults (), k )
83+ local setup_value = utils .map_get (setup_opts (), k )
84+ -- convert function types
85+ if type (opts [k ]) == " function" then opts [k ] = opts [k ](opts ) end
86+ if type (setup_value ) == " function" then setup_value = setup_value (opts ) end
87+ -- NOTE: maybe we should assert for non-table values?
88+ -- return all non table values in this priority
89+ -- (1) setup `defaults = { k = ...}` trumps all
90+ -- (2) opts.<k>
91+ -- (3) setup({ <k> })
92+ if setup_default ~= nil and type (setup_default ) ~= " table" then return setup_default end
93+ if opts [k ] ~= nil and type (opts [k ]) ~= " table" then return opts [k ] end
94+ if not setup_default and not opts [k ]
95+ and setup_value ~= nil and type (setup_value ) ~= " table"
96+ then
97+ return setup_value
98+ end
99+ opts [k ] = opts [k ] or {}
100+ fzflua_default = fzflua_default or {}
101+ setup_default = setup_default or {}
102+ setup_value = type (setup_value ) == " table" and setup_value or {}
103+ -- (1) setup defaults trumps all, e.g. `defaults = { winopts = {...} }`
104+ -- (2) merge setup on top, e.g. `setup({ winopts = {...} })`
105+ -- (3) merge fzf-lua true defaults on top
106+ opts [k ] = vim .tbl_deep_extend (" force" , {}, opts [k ], setup_default )
107+ opts [k ] = vim .tbl_deep_extend (" keep" , opts [k ], setup_value )
108+ opts [k ] = vim .tbl_deep_extend (" keep" , opts [k ], fzflua_default )
109+ local function build_bind_tables (keys )
110+ for _ , _k in ipairs (keys ) do
111+ -- TODO: lowercase merge, handle [1] = {true|false|
112+ opts [k ][_k ][1 ] = nil
113+ end
114+ end
115+ if k == " actions" then
116+ build_bind_tables ({ " files" , " buffers" })
117+ elseif k == " keymap" then
118+ build_bind_tables ({ " fzf" , " builtin" })
119+ end
120+ return opts
121+ end
80122 -- build normalized globals, option priority below:
81123 -- (1) provider specific globals (post-setup)
82124 -- (2) generic global-defaults (post-setup), i.e. `setup({ defaults = { ... } })`
@@ -122,16 +164,31 @@ M.globals = setmetatable({}, {
122164 elseif fzflua_default == nil and setup_value == nil then
123165 return
124166 end
167+ -- the existence of the `actions` key implies we're dealing with a picker
168+ local is_picker =
169+ (fzflua_default and (fzflua_default .actions or fzflua_default ._actions ))
170+ or (setup_value and (setup_value .actions or setup_value ._actions ))
125171 -- (1) use fzf-lua's true defaults (pre-setup) as our options base
126172 local ret = utils .tbl_deep_clone (fzflua_default ) or {}
127- if (fzflua_default and (fzflua_default .actions or fzflua_default ._actions ))
128- or (setup_value and (setup_value .actions or setup_value ._actions )) then
129- -- (2) the existence of the `actions` key implies we're dealing with a picker
130- -- override global provider defaults supplied by the user's setup `defaults` table
173+ if is_picker then
174+ -- (2.1) override global picker defaults with the user's setup `defaults` table
131175 ret = vim .tbl_deep_extend (" force" , ret , setup_defaults ())
176+ elseif type (setup_default ) == " table" then
177+ -- (2.2) index was included in defaults, e.g. `{ defaults = winopts = { ... } }`
178+ -- TODO: do we ever get here after the special_tbl change?
179+ assert (index )
180+ ret = vim .tbl_deep_extend (" force" , ret , setup_default )
132181 end
133182 -- (3) override with the specific provider options from the users's `setup` option
134183 ret = vim .tbl_deep_extend (" force" , ret , utils .map_get (setup_opts (), index ) or {})
184+ -- (4) for pickers, special tables which merge from true globals but can be
185+ -- overwritten from setup defaults, e.g. `{ defaults = winopts = { ... } }`
186+ if is_picker then
187+ for _ , k in ipairs ({ " winopts" , " keymap" , " fzf_opts" , " fzf_colors" , " fzf_tmux_opts" , " hls" })
188+ do
189+ ret = special_tbl (ret , k )
190+ end
191+ end
135192 return ret
136193 end ,
137194 __newindex = function (_ , index , _ )
@@ -334,53 +391,6 @@ function M.normalize_opts(opts, globals, __resume_key) ---@diagnostic disable
334391 -- merge with provider defaults from globals (defaults + setup options)
335392 opts = vim .tbl_deep_extend (" keep" , opts , utils .tbl_deep_clone (globals ))
336393
337- -- Backward compat: merge `winopts` with outputs from `winopts_fn`
338- local winopts_fn = opts .winopts_fn or M .globals .winopts_fn
339- if type (winopts_fn ) == " function" then
340- vim .deprecate (" winopts_fn" , " winopts" , " Jan 2026" , " FzfLua" )
341- local ret = winopts_fn (opts ) or {}
342- if not utils .tbl_isempty (ret ) and (not opts .winopts or type (opts .winopts ) == " table" ) then
343- opts .winopts = vim .tbl_deep_extend (" force" , opts .winopts or {}, ret )
344- end
345- end
346-
347- local extend_opts = function (m , k )
348- local setup_val = m [k ]
349- if type (setup_val ) == " function" then
350- setup_val = setup_val (opts )
351- if type (setup_val ) == " table" then
352- local default_val = utils .map_get (M .defaults , k )
353- if type (default_val ) == " table" then
354- setup_val = vim .tbl_deep_extend (" force" , {}, default_val , setup_val )
355- end
356- end
357- end
358- if type (setup_val ) == " table" then
359- -- must clone or map will be saved as reference
360- -- and then overwritten if found in 'backward_compat'
361- setup_val = utils .tbl_deep_clone (setup_val )
362- end
363- if opts [k ] == nil then
364- opts [k ] = setup_val
365- else
366- if type (opts [k ]) == " function" then
367- opts [k ] = opts [k ](opts )
368- end
369- if type (opts [k ]) == " table" then
370- opts [k ] = vim .tbl_deep_extend (" keep" ,
371- opts [k ], type (setup_val ) == " table" and setup_val or {})
372- end
373- end
374- end
375-
376- -- Merge values from globals
377- for _ , k in ipairs ({
378- " winopts" , " keymap" , " fzf_opts" , " fzf_colors" , " fzf_tmux_opts" , " hls"
379- }) do
380- extend_opts (globals , k )
381- extend_opts (M .globals , k )
382- end
383-
384394 -- backward compat: no-value flags should be set to `true`, in the past these
385395 -- would be set to an empty string which would now translate into a shell escaped
386396 -- string as we automatically shell escape all fzf_opts
0 commit comments