Skip to content

Commit 1be5cde

Browse files
committed
fix(global): fix resume, imrpove logic
docs: update README with global/combine pickers
1 parent c93a64b commit 1be5cde

5 files changed

Lines changed: 136 additions & 87 deletions

File tree

README.md

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,40 @@ Alternatively, resuming work on a specific picker:
163163
> })
164164
> ```
165165
166+
### Combining Pickers
167+
168+
Fzf-Lua can combine any of the available pickers into a single display
169+
using the `combine` method, for example file history (oldfiles) and
170+
git-files:
171+
```lua
172+
:lua FzfLua.combine({ pickers = "oldfiles;git_files" })
173+
-- or using the `FzfLua` vim command:
174+
:FzfLua combine pickers=oldfiles;git_files
175+
```
176+
177+
> [!NOTE]
178+
> The first picker options determine the options used by the combined
179+
> picker, that includes formatters, previewer, path_shorten, etc.
180+
> To avoid errors combine only pickers of the same entry types (i.e files)
181+
182+
### Global Picker
183+
184+
Fzf-Lua conveniently comes with a VS-Code like picker by default
185+
(customizable) combining files, buffers and LSP symbols:
186+
187+
|Prefix |Behavior |
188+
|-----------|-----------------------------------|
189+
|`no prefix`|Files |
190+
|`$` |Buffers |
191+
|`@` |LSP Symbols (current buffer) |
192+
|`#` |LSP Symbols (workspace/project) |
193+
194+
```lua
195+
:lua FzfLua.global()
196+
-- or using the `FzfLua` vim command:
197+
:FzfLua global
198+
```
199+
166200
**LIST OF AVAILABLE COMMANDS BELOW** 👇
167201

168202
## Commands
@@ -278,32 +312,34 @@ Alternatively, resuming work on a specific picker:
278312

279313
### Misc
280314

281-
| Command | List |
282-
| ---------------------- | ------------------------------ |
283-
| `resume` | resume last command/query |
284-
| `builtin` | fzf-lua builtin commands |
285-
| `profiles` | fzf-lua configuration profiles |
286-
| `helptags` | help tags |
287-
| `manpages` | man pages |
288-
| `colorschemes` | color schemes |
289-
| `awesome_colorschemes` | Awesome Neovim color schemes |
290-
| `highlights` | highlight groups |
291-
| `commands` | neovim commands |
292-
| `command_history` | command history |
293-
| `search_history` | search history |
294-
| `marks` | :marks |
295-
| `jumps` | :jumps |
296-
| `changes` | :changes |
297-
| `registers` | :registers |
298-
| `tagstack` | :tags |
299-
| `autocmds` | :autocmd |
300-
| `nvim_options` | neovim options |
301-
| `keymaps` | key mappings |
302-
| `filetypes` | filetypes |
303-
| `menus` | menus |
304-
| `spellcheck` | misspelled words in buffer |
305-
| `spell_suggest` | spelling suggestions |
306-
| `packadd` | :packadd <package> |
315+
| Command | List |
316+
| ---------------------- | --------------------------------------------- |
317+
| `resume` | resume last command/query |
318+
| `builtin` | fzf-lua builtin commands |
319+
| `combine` | combine different fzf-kua pickers |
320+
| `global` | global picker for files,buffers and symbols |
321+
| `profiles` | fzf-lua configuration profiles |
322+
| `helptags` | help tags |
323+
| `manpages` | man pages |
324+
| `colorschemes` | color schemes |
325+
| `awesome_colorschemes` | Awesome Neovim color schemes |
326+
| `highlights` | highlight groups |
327+
| `commands` | neovim commands |
328+
| `command_history` | command history |
329+
| `search_history` | search history |
330+
| `marks` | :marks |
331+
| `jumps` | :jumps |
332+
| `changes` | :changes |
333+
| `registers` | :registers |
334+
| `tagstack` | :tags |
335+
| `autocmds` | :autocmd |
336+
| `nvim_options` | neovim options |
337+
| `keymaps` | key mappings |
338+
| `filetypes` | filetypes |
339+
| `menus` | menus |
340+
| `spellcheck` | misspelled words in buffer |
341+
| `spell_suggest` | spelling suggestions |
342+
| `packadd` | :packadd <package> |
307343

308344
</details>
309345
<details>

lua/fzf-lua/actions.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ end
9898

9999
M.act = function(selected, opts)
100100
if not selected then return end
101+
if opts.__alt_opts then
102+
opts.__alt_opts.last_query = opts.last_query
103+
opts.__alt_opts.__INFO = opts.__INFO
104+
end
101105
local actions = opts.actions
102106
local keybind, entries = M.normalize_selected(selected, opts)
103107
-- fzf >= 0.53 and `--exit-0`
@@ -112,10 +116,10 @@ M.act = function(selected, opts)
112116
-- (1) map containing action properties (reload, noclose, etc)
113117
-- (2) array of actions to be executed serially
114118
if action.fn then
115-
action.fn(entries, opts)
119+
action.fn(entries, opts.__alt_opts or opts)
116120
else
117121
for _, f in ipairs(action) do
118-
f(entries, opts)
122+
f(entries, opts.__alt_opts or opts)
119123
end
120124
end
121125
elseif type(action) == "function" then

lua/fzf-lua/defaults.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,10 @@ M.defaults.global = vim.tbl_deep_extend("force", M.defaults.files,
364364
cwd_prompt = true,
365365
line_query = true,
366366
pickers = {
367-
[""] = "files",
368-
["$"] = "buffers",
369-
["@"] = "lsp_document_symbols",
370-
["#"] = "lsp_workspace_symbols",
367+
{ "files", desc = "Files" },
368+
{ "buffers", desc = "Bufs", prefix = "$" },
369+
{ "lsp_document_symbols", desc = "Symbols (buf)", prefix = "@" },
370+
{ "lsp_workspace_symbols", desc = "Symbols (project)", prefix = "#" },
371371
},
372372
fzf_opts = { ["--nth"] = false, ["--with-nth"] = false },
373373
winopts = { preview = { winopts = { cursorline = true } } },

lua/fzf-lua/profiles/hide.lua

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,16 @@ return {
6767
act.exec_silent = true
6868
act.desc = act.desc or fzf.config.get_action_helpstr(fn)
6969
act.fn = function(...)
70+
local sel = select(1, ...)
71+
local o = select(2, ...)
72+
if o.__alt_opts then
73+
o.__alt_opts.last_query = o.last_query
74+
o.__alt_opts.__INFO = o.__INFO
75+
end
7076
fzf.hide()
71-
fn(...)
77+
fn(sel, o.__alt_opts or o)
7278
-- As the process never terminates fzf history is never written
7379
-- manually append to the fzf history file if needed
74-
local o = select(2, ...)
7580
if histfile and type(o.last_query) == "string" and #o.last_query > 0 then
7681
local fd = uv.fs_open(histfile, "a", -1)
7782
if fd then

lua/fzf-lua/providers/meta.lua

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -106,23 +106,22 @@ M.combine = function(t)
106106

107107
-- First picker options set the tone
108108
local opts1 = (function()
109-
if t.pickers[1] then
109+
if t.pickers and t.pickers[1] then
110110
local ok, opts = pcall(config.normalize_opts, t, t.pickers[1])
111-
if not ok or not opts then
112-
utils.warn("Must specify at least one valid picker")
113-
else
114-
return opts
115-
end
111+
return ok and opts
116112
end
117113
end)()
118-
if not opts1 then return end
114+
if not opts1 then
115+
utils.warn("Must specify at least one valid picker")
116+
return
117+
end
119118

120119
-- Let fzf_wrap know to NOT start the coroutine
121120
opts1._start = false
122121

123122
local cmds, opts = (function()
124123
local ret, opts = {}, nil
125-
for _, p in ipairs(t.pickers) do
124+
for _, p in ipairs(t.pickers --[[@as table]]) do
126125
-- local ok, msg, cmd, o = pcall(FzfLua[p], opts1)
127126
-- if not ok or not cmd then
128127
local _, cmd, o = FzfLua[p](opts1)
@@ -162,87 +161,92 @@ M.global = function(opts)
162161
opts._start = false
163162
local pickers = {}
164163
local opts_copy = vim.deepcopy(opts)
165-
for c, p in pairs(opts.pickers) do
166-
if FzfLua[p] then
167-
if #c == 0 then
164+
for _, t in ipairs(opts.pickers) do
165+
local name = t[1]
166+
if FzfLua[name] then
167+
if not t.prefix then
168168
-- Default picker opts set the tone for this picker options
169169
-- this way convert reload / exec_silent actions will use a consistent
170170
-- opts ref in the callbacks so we can later modify internal values
171-
pickers[p] = { FzfLua[p](opts) }
171+
pickers[name] = { FzfLua[name](opts) }
172172
-- Override opts with the return opts and store a copy of `pickers[]`
173173
-- as we patch the opts when switching a picker in the change event
174-
opts = pickers[p][3]
174+
opts = pickers[name][3]
175175
opts._start = nil -- remove the start suppression
176-
pickers[p][3] = vim.deepcopy(opts)
176+
pickers[name][3] = vim.deepcopy(opts)
177177
else
178178
-- Each subsequent picker gets a fresh copy of the original opts
179179
-- (unmodified by the default picker)
180-
pickers[p] = { FzfLua[p](opts_copy) }
180+
pickers[name] = { FzfLua[name](opts_copy) }
181181
end
182182
else
183-
utils.warn(string.format("invalid picker '%s', ignoring.", p))
183+
utils.warn(string.format("invalid picker '%s', ignoring.", name))
184184
end
185185
end
186186

187+
-- Test for default/starting picker
188+
local default_picker = opts.pickers[1] and pickers[opts.pickers[1][1]]
189+
if not default_picker or default_picker.prefix then
190+
utils.err("default picker not defined or has a prefix, aborting.")
191+
return
192+
end
193+
187194
---@param q string?
188195
---@return table?, integer?
189196
local get_picker = function(q)
190-
q = type(q) == "string" and q or ""
191-
if #q == 0 then
192-
return pickers[opts.pickers[""]], 1
193-
end
194-
for c, p in pairs(opts.pickers) do
195-
if #c > 0 and q:match("^" .. utils.lua_regex_escape(c)) then
196-
return pickers[p], #c + 1
197+
if type(q) == "string" and #q > 0 then
198+
for _, t in ipairs(opts.pickers) do
199+
local name = t[1]
200+
if t.prefix and #t.prefix > 0 and q:match("^" .. utils.lua_regex_escape(t.prefix)) then
201+
return pickers[name], #t.prefix + 1
202+
end
197203
end
198204
end
205+
return default_picker, 1
199206
end
200207

201-
-- Copy all keys without destroying the parent opts ref
202-
-- or we will mess up the actions (especially hide)
203-
local patch_opts = function(t1, t2)
204-
for k, _ in pairs(t1) do
205-
if k ~= "actions" then t1[k] = nil end
206-
end
207-
for k, v in pairs(t2) do
208-
(function()
209-
if k == "actions" then return end
210-
if type(v) == "table" then
211-
t1[k] = vim.tbl_deep_extend("force", t1[k] or {}, v)
212-
else
213-
t1[k] = v
214-
end
215-
end)()
216-
end
217-
return t1
218-
end
219208

220-
-- Get starting picker
221-
local cur_picker, cur_sub = get_picker()
222-
if not cur_picker then
223-
utils.warn("default picker not found, aborting.")
224-
return
225-
end
209+
local cur_picker, cur_sub
226210

227-
table.insert(opts._fzf_cli_args, "--bind=" .. libuv.shellescape("change:+transform:"
228-
.. FzfLua.shell.stringify_data(function(args, _, _)
211+
local transform_picker = function(start)
212+
return FzfLua.shell.stringify_data(function(args, _, _)
229213
local q = args[1]
230214
local new_picker, new_sub = get_picker(q)
215+
assert(new_picker)
231216
local reload = ""
232-
if new_picker and new_picker ~= cur_picker then
217+
if start or new_picker and new_picker ~= cur_picker then
233218
-- New picker requested, reload the contents and transform
234219
-- the search string to exclude the picker prefix
235220
cur_sub = new_sub
236221
cur_picker = new_picker
237222
-- Patch the opts refs with important values for path parsing
238223
-- e.g. formatter, path_shorten, etc
239-
opts = patch_opts(opts, cur_picker[3])
224+
-- TODO: is there a better way to override the callback opts ref?
225+
opts.__alt_opts = new_picker[3]
240226
reload = string.format("reload(%s)+", new_picker[2])
241227
end
242228
return reload .. string.format("search(%s)", q:sub(cur_sub))
243-
end, opts, "{q}")))
229+
end, opts, "{q}")
230+
end
231+
232+
table.insert(opts._fzf_cli_args, "--bind="
233+
.. libuv.shellescape("start:+transform:" .. transform_picker(true)))
234+
235+
table.insert(opts._fzf_cli_args, "--bind="
236+
.. libuv.shellescape("change:+transform:" .. transform_picker(false)))
237+
238+
if opts.header ~= false then
239+
local header = {}
240+
for _, t in pairs(opts.pickers) do
241+
table.insert(header, string.format("<%s> %s",
242+
utils.ansi_from_hl(opts.hls.header_bind, t.prefix or "default"),
243+
utils.ansi_from_hl(opts.hls.header_text, t.desc or t[1])))
244+
end
245+
246+
opts.header = table.concat(header, "|")
247+
end
244248

245-
return core.fzf_wrap(cur_picker[2], opts)
249+
return core.fzf_wrap(utils.shell_nop(), opts)
246250
end
247251

248252
return M

0 commit comments

Comments
 (0)