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

Resume picker and select next/prev entry and open it automatically #3391

Open
delphinus opened this issue Dec 25, 2024 · 1 comment · May be fixed by #3394
Open

Resume picker and select next/prev entry and open it automatically #3391

delphinus opened this issue Dec 25, 2024 · 1 comment · May be fixed by #3394
Labels
enhancement Enhancement to performance, inner workings or existent features

Comments

@delphinus
Copy link
Member

delphinus commented Dec 25, 2024

Is your feature request related to a problem? Please describe.

After opening an entry from a picker, I often do :Telescope resume and select the next/prev entry and open it. For example,

  1. :Telescope find_files
  2. open the file: /path/to/cwd/foo-01.txt
  3. :Telescope resume
  4. open the next file: /path/to/cwd/foo-02.txt

It is annoying that I need three key presses for this: (1) mapping for :Telescope resume, (2) <C-n>, (3) <CR>. I want to do this with one mapping.

Describe the solution you'd like

I've written a function to do this, but this is too ugly to contribute into telescope.nvim. Can anyone write more simply?

resume_snd_select()
local function get_picker(prompt_bufnr)
  local action_state = require "telescope.actions.state"
  local actions = require "telescope.actions"

  local picker = action_state.get_current_picker(prompt_bufnr)
  if not picker then
    vim.notify("found no picker", vim.log.levels.WARN)
    return
  elseif picker.manager:num_results() <= 1 then
    vim.notify("picker has no entry to open", vim.log.levels.WARN)
    actions.close(prompt_bufnr)
    if picker.initial_mode == "insert" then
      vim.api.nvim_feedkeys([[<C-\><C-n>]], "i", true)
    end
    return
  end
  return picker
end

---@async
local function select_and_open(picker, change)
  local actions = require "telescope.actions"
  local async = require "plenary.async"

  local start = vim.uv.hrtime()
  while true do
    local displayed = picker.stats.displayed
    if displayed and displayed > 0 then
      picker:move_selection(change)
      actions.select_default(picker.prompt_bufnr)
      return
    elseif vim.uv.hrtime() - start > 2 * 1e9 then
      vim.notify("cannot get results from picker", vim.log.levels.WARN)
      actions.close(picker.prompt_bufnr)
      return
    end
    async.util.sleep(10)
  end
end

local function resume_and_select(change)
  return function()
    vim.api.nvim_create_autocmd("FileType", {
      group = vim.api.nvim_create_augroup("resume_and_select", {}),
      pattern = "TelescopePrompt",
      once = true,
      callback = function(args)
        local picker = get_picker(args.buf)
        if picker then
          require("plenary.async").void(select_and_open)(picker, change)
        end
      end,
    })

    require("telescope.builtin").resume {}
  end
end

With this function, I can achieve this feature with example mappings below.

vim.keymap.set(
  "n",
  "<Leader>fj",
  resume_and_select(1),
  { desc = "Resume Telescope picker and open the next candidate" }
)
vim.keymap.set(
  "n",
  "<Leader>fk",
  resume_and_select(-1),
  { desc = "Resume Telescope picker and open the previous candidate" }
)

Describe alternatives you've considered

telescope.nvim has a similar feature: <C-q> (actions.send_to_qflist). But this only works with file-like entries. For pickers that provides non-file-like entries, such as :Telescope help_tags, send_to_qflist does not work, but resume_and_select() works good.

Additional context

@delphinus delphinus added the enhancement Enhancement to performance, inner workings or existent features label Dec 25, 2024
@delphinus
Copy link
Member Author

Sorry, I found User TelescopeResumePost event can handle the time when resuming has been completed. I can omit code considerably, so later I will push PR to add functions to do this.

      local function get_picker(prompt_bufnr)
        local action_state = require "telescope.actions.state"
        local actions = require "telescope.actions"

        local picker = action_state.get_current_picker(prompt_bufnr)
        if not picker then
          vim.notify("found no picker", vim.log.levels.WARN)
          return
        elseif picker.manager:num_results() <= 1 then
          vim.notify("picker has no entry to open", vim.log.levels.WARN)
          actions.close(prompt_bufnr)
          if picker.initial_mode == "insert" then
            vim.api.nvim_feedkeys([[<C-\><C-n>]], "i", true)
          end
          return
        end
        return picker
      end

      local function resume_and_select(change)
        return function()
          vim.api.nvim_create_autocmd("User", {
            group = vim.api.nvim_create_augroup("resume_and_select", {}),
            pattern = "TelescopeResumePost",
            once = true,
            callback = function(args)
              local picker = get_picker(args.buf)
              if picker then
                vim.schedule(function()
                  picker:move_selection(change)
                  require("telescope.actions").select_default(args.buf)
                end)
              end
            end,
          })

          require("telescope.builtin").resume {}
        end
      end

@delphinus delphinus linked a pull request Jan 3, 2025 that will close this issue
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhancement to performance, inner workings or existent features
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant