nvim-telescope / telescope.nvim

Find, Filter, Preview, Pick. All lua, all the time.
MIT License
16.14k stars 843 forks source link

[feature] Multi-selection #416

Open tjdevries opened 3 years ago

tjdevries commented 3 years ago

Currently half implemented.

Need to fix highlights and other items related to it.

Needs other actions as well.

baldore commented 3 years ago

Hey, first at all, thanks for this great plugin. I'm wondering if, after this feature is added, you can make multiple selections of Rg results and add them to the quickfix. I ask because, if this is possible already, I would love to migrate to this plugin from Fzf.vim.

Conni2461 commented 3 years ago

We can send entries to qflist. You can already do this with all results and the function for sending only selected to qflist is also done. You need to manually set it up right now:

local actions = require('telescope.actions')
require('telescope').setup{
  defaults = {
    mappings = {
      i = {
        ["<C-w>"] = actions.send_selected_to_qflist,
        ["<C-q>"] = actions.send_to_qflist,
      },
      n = {
        ["<C-w>"] = actions.send_selected_to_qflist,
        ["<C-q>"] = actions.send_to_qflist,
      },
    },
  }
}

So this will be possible when multi selection is done and enabled.

larrybotha commented 3 years ago

For anyone looking for a basic fzf-type multiselection, where:

I've done the following:

local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")

local function fzf_multi_select(prompt_bufnr)
    local picker = action_state.get_current_picker(prompt_bufnr)
    local num_selections = #picker:get_multi_selection()

    if num_selections > 1 then
        -- actions.file_edit throws - context of picker seems to change
        --actions.file_edit(prompt_bufnr)
        actions.send_selected_to_qflist(prompt_bufnr)
        actions.open_qflist()
    else
        actions.file_edit(prompt_bufnr)
    end
end

require("telescope").setup {
    defaults = {
        mappings = {
            i = {
                -- close on escape
                ["<esc>"] = actions.close,
                ["<tab>"] = actions.toggle_selection + actions.move_selection_next,
                ["<s-tab>"] = actions.toggle_selection + actions.move_selection_previous,
                ["<cr>"] = fzf_multi_select
            },
            n = {
                ["<tab>"] = actions.toggle_selection + actions.move_selection_next,
                ["<s-tab>"] = actions.toggle_selection + actions.move_selection_previous,
                ["<cr>"] = fzf_multi_select
            }
        }
    }
}

I haven't yet worked out why I'm getting errors when executing actions.file_edit when there are selections, but this gets you 80% of the way to how fzf works.

EDIT: update utility to use # instead of deprecated table.getn

tjdevries commented 3 years ago

it's cause file_edit closes the picker, and then it's lost. I have a PR that is WIP for fixing this problem -- but it requires some larger refactorings.

RunningIkkyu commented 3 years ago

Thanks for @larrybotha's solution👍, It works for me!

chaudry-786 commented 1 year ago

Any progress on this? I have recently moved from fzf and surprised telescope lacks this functionality.

fsouza commented 1 year ago

Any progress on this? I have recently moved from fzf and surprised telescope lacks this functionality.

You can implement this by customizing the action. It's not supported natively, but it's also not impossible to achieve.

zegabr commented 1 year ago

I did a similar solution compared with @larrybotha's one, in case anyone is interested. The difference is that instead of opening the quickfix list, I open each selected file in a new buffer (the same way the single file is open with actions.file_edit):

local action_utils = require "telescope.actions.utils"
local action_state = require "telescope.actions.state"

local function single_or_multi_select(prompt_bufnr)
    local current_picker = action_state.get_current_picker(prompt_bufnr)
    local has_multi_selection = (next(current_picker:get_multi_selection()) ~= nil)

    if(has_multi_selection) then
        -- apply function to each selection
        action_utils.map_selections(prompt_bufnr, function (selection)
            local filename = selection[1]
            vim.cmd(':edit! ' .. filename)
        end)

    else
        -- if does not have multi selection, open single file
        actions.file_edit(prompt_bufnr)
    end
end

telescope.setup {
    defaults = {
        mappings = {
            i = {
                ['<esc>'] = actions.close,
                ['<C-j>'] = actions.move_selection_next,
                ['<C-k>'] = actions.move_selection_previous,
                ['<tab>'] = actions.toggle_selection,
                ['<cr>'] = single_or_multi_select,
            },
        },   
}

However, I haven't worked out why the vim.cmd(':edit ' .. filename) doesn't work, I had to add the exclamation mark (i.e ":edit!") for it to work. Besides that it seems to work as I expect

davidosomething commented 1 year ago

my modified version of the above, but doesn't cause issues from :edit! if you have a currently open buffer:

      local action_state = require("telescope.actions.state")
      local action_utils = require("telescope.actions.utils")
      local function single_or_multi_select(prompt_bufnr)
        local current_picker = action_state.get_current_picker(prompt_bufnr)
        local has_multi_selection = (
          next(current_picker:get_multi_selection()) ~= nil
        )

        if has_multi_selection then
          local results = {}
          action_utils.map_selections(prompt_bufnr, function(selection)
            table.insert(results, selection[1])
          end)

          -- load the selections into buffers list without switching to them
          for _, filepath in ipairs(results) do
            -- not the same as vim.fn.bufadd!
            vim.cmd.badd({ args = { filepath } })
          end

          require("telescope.pickers").on_close_prompt(prompt_bufnr)

          -- switch to newly loaded buffers if on an empty buffer
          if vim.fn.bufname() == "" and not vim.bo.modified then
            vim.cmd.bwipeout()
            vim.cmd.buffer(results[1])
          end
          return
        end

        -- if does not have multi selection, open single file
        require("telescope.actions").file_edit(prompt_bufnr)
      end
erlandsona commented 10 months ago

Curious what the latest is on this. It's the only thing blocking me from switching to telescope (from the fzf thing) but most of the rest of the ecosystem seems to be congregating around telescope.

If I need to I can copy/paste some of the proposed solutions in the responses here but would love a telescope "blessed" solution.