Skip to content

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

@delphinus

Description

@delphinus

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementEnhancement to performance, inner workings or existent features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions