Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add a combined picker between buffers & git_files/files #1879

Open
1 task done
LoricAndre opened this issue Mar 12, 2025 · 5 comments
Open
1 task done

Feature: add a combined picker between buffers & git_files/files #1879

LoricAndre opened this issue Mar 12, 2025 · 5 comments
Labels
feature request New feature

Comments

@LoricAndre
Copy link

Have you RTFM'd?

  • I have done proper research

Feature Request

I'd love a picker that would show me my open buffers at the top, then show me files (or git_files, I'm not so sure). I tried building it from the public API but most utility functions are local which makes it quite complicated to implement robustly and maintain with future changes.
More generally (but probably harder), it would be interesting to be able to combine multiple pickers, and be able to specify the ordering.

@LoricAndre LoricAndre added the feature request New feature label Mar 12, 2025
@LoricAndre
Copy link
Author

Note: a way for me to build something like this in my config would be to expose the contents for specific pickers, that I could retrieve and try to combine myself

@LoricAndre
Copy link
Author

LoricAndre commented Mar 12, 2025

For now, I put this together, but I'm still missing the icons for the buffers and some robustness:

function FzfLuaSmart(opts)
  local config = require('fzf-lua.config')
  local core = require('fzf-lua.core')
  local path = require('fzf-lua.path')
  local libuv = require('fzf-lua.libuv')
  local make_entry = require('fzf-lua.make_entry')
  opts = config.normalize_opts(opts, 'git.files')
  if not opts then
    return
  end
  opts.cwd = path.git_root(opts)
  opts.git_icons = true
  opts.file_icons = true
  if not opts.cwd then
    return
  end
  local git_cmd = core.mt_cmd_wrapper(opts)
  local git_fn = libuv.spawn_nvim_fzf_cmd({
    cmd = git_cmd,
    cwd = opts.cwd,
    cb_pid = function(pid)
      opts.__pid = pid
    end,
  })
  local contents = function(x, cb, y)
    make_entry.preprocess(opts)
    for _, buf_id in ipairs(vim.api.nvim_list_bufs()) do
      if
        vim.api.nvim_buf_is_loaded(buf_id) and vim.fn.buflisted(buf_id) == 1
      then
        local p = vim.api.nvim_buf_get_name(buf_id)
        local exists, stats = pcall(vim.uv.fs_stat, p)
        if exists and stats and stats.type == 'file' then
          cb(make_entry.file(p .. '\n', opts))
        end
      end
    end

    git_fn(x, cb, y)
  end
  opts = core.set_header(opts, opts.headers or { 'cwd' })
  return core.fzf_exec(contents, opts)
end

@phanen
Copy link
Contributor

phanen commented Mar 12, 2025

Maybe in this way you can get icons for buffer:

@@ -31,7 +31,7 @@ function FzfLuaSmart(opts)
         local p = vim.api.nvim_buf_get_name(buf_id)
         local exists, stats = pcall(vim.uv.fs_stat, p)
         if exists and stats and stats.type == "file" then
-          cb(make_entry.file(p .. "\n", opts))
+          x(make_entry.file(p, opts))
         end
       end
     end

Maybe there's other ways for this purpose, e.g. give a higher priority for atime when using fd/find/fzf (but they seems don't support this feature natively...)

@LoricAndre
Copy link
Author

Thanks ! This works for the icons.
As a skim maintainer, I can see a few way to do something like sorting using the atime` (using nth/with-nth for instance), but I don't think that's really what I want for now.

Note: I wasn't able to find much about these arguments (hence the x and y). Where can I find some to better understand it ?

@ibhagwan
Copy link
Owner

Note: a way for me to build something like this in my config would be to expose the contents for specific pickers, that I could retrieve and try to combine myself

That’s def the better approach which I started working towards, lsp_finder has been using a contents array for a long time now:

M.fzf_exec = function(contents, opts)
if type(contents) == "table" and type(contents[1]) == "table" then
contents = contents_from_arr(contents)
end

The issue I’m facing with these type of pickers is combing buffers which is lua type contents with files that is an external shell command (with a neovim headless wrapper), ATM these can’t be combined as it means I’d have to transfer the entire current state of the main instance to the headless instance to get buffers working properly.

Obviously we can use the simple approach and call vim.system for the files enumeration but that wouldn’t be performant and thus defeating the purpose IMHO.

Note: I wasn't able to find much about these arguments (hence the x and y). Where can I find some to better understand it ?

fzf-lua/lua/fzf-lua/fzf.lua

Lines 171 to 174 in 15d5cd9

-- nvim-fzf compatibility, builds the user callback functions
-- 1st argument: callback function that adds newline to each write
-- 2nd argument: callback function that writes the data as is
-- 3rd argument: direct access to the pipe object

We could always improve on docs and annotations, these didn’t even exist properly with lua_la when I started this project…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature
Projects
None yet
Development

No branches or pull requests

3 participants