@@ -19,6 +19,7 @@ local Promise = require('opencode.promise')
1919--- @field multi_selection ? table<string , boolean> Actions that support multi-selection
2020--- @field preview ? " file" | " none" | false Preview mode : " file" for file preview , " none" or false to disable
2121--- @field layout_opts ? OpencodeUIPickerConfig
22+ --- @field close ? fun () Close the picker programmatically (set by the backend )
2223
2324--- @class TelescopeEntry
2425--- @field value any
@@ -147,6 +148,11 @@ local function telescope_ui(opts)
147148 width = opts .width + 7 , -- extra space for telescope UI
148149 } or nil ,
149150 attach_mappings = function (prompt_bufnr , map )
151+ opts .close = function ()
152+ selection_made = true
153+ actions .close (prompt_bufnr )
154+ end
155+
150156 actions .select_default :replace (function ()
151157 selection_made = true
152158 local selection = action_state .get_selected_entry ()
@@ -197,8 +203,12 @@ local function telescope_ui(opts)
197203 local new_items = action .fn (items_to_process , opts )
198204 Promise .wrap (new_items ):and_then (function (resolved_items )
199205 if action .reload and resolved_items then
200- opts .items = resolved_items
201- refresh_picker ()
206+ if # resolved_items == 0 and opts .close then
207+ opts .close ()
208+ else
209+ opts .items = resolved_items
210+ refresh_picker ()
211+ end
202212 end
203213 end )
204214 end
@@ -295,9 +305,33 @@ local function fzf_ui(opts)
295305 end )
296306 end
297307
308+ local closed = false
309+
310+ opts .close = function ()
311+ if closed then
312+ return
313+ end
314+ closed = true
315+ vim .schedule (function ()
316+ local ok , fzf_win = pcall (require , ' fzf-lua.win' )
317+ if ok and fzf_win .__SELF then
318+ local win = fzf_win .__SELF ()
319+ if win then
320+ win :close ()
321+ end
322+ end
323+ if opts .callback then
324+ opts .callback (nil )
325+ end
326+ end )
327+ end
328+
298329 --- @type FzfLuaActions
299330 local actions_config = {
300331 [' default' ] = function (selected , fzf_opts )
332+ if closed then
333+ return
334+ end
301335 if not selected or # selected == 0 then
302336 if opts .callback then
303337 opts .callback (nil )
@@ -310,6 +344,9 @@ local function fzf_ui(opts)
310344 end
311345 end ,
312346 [' esc' ] = function ()
347+ if closed then
348+ return
349+ end
313350 if opts .callback then
314351 opts .callback (nil )
315352 end
@@ -346,8 +383,12 @@ local function fzf_ui(opts)
346383 Promise .wrap (new_items ):and_then (function (resolved_items )
347384 if action .reload and resolved_items then
348385 --- @cast resolved_items any[]
349- opts .items = resolved_items
350- refresh_fzf ()
386+ if # resolved_items == 0 and opts .close then
387+ opts .close ()
388+ else
389+ opts .items = resolved_items
390+ refresh_fzf ()
391+ end
351392 end
352393 end )
353394 end
@@ -376,6 +417,10 @@ local function mini_pick_ui(opts)
376417
377418 local mappings = {}
378419
420+ opts .close = function ()
421+ mini_pick .stop ()
422+ end
423+
379424 for action_name , action in pairs (opts .actions ) do
380425 if action .key and action .key [1 ] then
381426 mappings [action_name ] = {
@@ -387,8 +432,12 @@ local function mini_pick_ui(opts)
387432 local new_items = action .fn (current .item , opts )
388433 Promise .wrap (new_items ):and_then (function (resolved_items )
389434 if action .reload and resolved_items then
390- opts .items = resolved_items
391- mini_pick_ui (opts )
435+ if # resolved_items == 0 and opts .close then
436+ opts .close ()
437+ else
438+ opts .items = resolved_items
439+ mini_pick_ui (opts )
440+ end
392441 end
393442 end )
394443 end
@@ -522,6 +571,13 @@ local function snacks_picker_ui(opts)
522571 snack_opts .win .input .keys [action .key [1 ]] = { action_name , mode = action .key .mode or ' i' }
523572
524573 snack_opts .actions [action_name ] = function (_picker , item )
574+ if not opts .close then
575+ opts .close = function ()
576+ selection_made = true
577+ _picker :close ()
578+ end
579+ end
580+
525581 if item then
526582 local items_to_process
527583 if action .multi_selection then
@@ -540,9 +596,13 @@ local function snacks_picker_ui(opts)
540596 local new_items = action .fn (items_to_process , opts )
541597 Promise .wrap (new_items ):and_then (function (resolved_items )
542598 if action .reload and resolved_items then
543- opts .items = resolved_items
544- _picker :refresh ()
545- _picker :find ()
599+ if # resolved_items == 0 and opts .close then
600+ opts .close ()
601+ else
602+ opts .items = resolved_items
603+ _picker :refresh ()
604+ _picker :find ()
605+ end
546606 end
547607 end )
548608 end )
0 commit comments