trouble.nvim icon indicating copy to clipboard operation
trouble.nvim copied to clipboard

[Feature] Possibility to remove an item from the list

Open LudoPinelli opened this issue 2 years ago • 3 comments

I have no idea if it's possible or not! For example if I search for a word with Telescope and send the results to Trouble, I often have some that are irrelevant for what I'm doing, and having the possibility to remove them with a keymap to narrow down and clean up the list would be handy :)

LudoPinelli avatar Jan 08 '22 18:01 LudoPinelli

Hi, I would like to ask if we can add this feature too.

sandangel avatar Jun 05 '22 15:06 sandangel

I wrote this code snippet to do exactly that if you are interested:

vim.api.nvim_create_augroup("WhichKeyTelescope", { clear = true })
vim.api.nvim_create_autocmd({ "FileType" }, {
  pattern = "Trouble",
  callback = function(event)
    local bufopts = { noremap = true, silent = true, buffer = event.buf }
    local trouble_config = require("trouble.config")

    if trouble_config.options.mode == "telescope" then
      vim.keymap.set("n", "D", function()
        require("trouble.providers.telescope").results = {}
        require("trouble").close()
      end, bufopts)

      local delete_entry = function()
        local win = vim.api.nvim_get_current_win()
        local cursor = vim.api.nvim_win_get_cursor(win)
        local line = cursor[1]
        -- Can use Trouble.get_items()
        local results = require("trouble.providers.telescope").results
        local folds = require("trouble.folds")

        local filenames = {}
        for _, result in ipairs(results) do
          if filenames[result.filename] == nil then
            filenames[result.filename] = 1
          else
            filenames[result.filename] = 1 + filenames[result.filename]
          end
        end

        local index = 1
        local cursor_line = 1
        local seen_filename = {}
        while cursor_line < line do
          local result = results[index]
          local filename = result.filename

          if seen_filename[filename] == nil then
            seen_filename[filename] = true
            cursor_line = cursor_line + 1

            if folds.is_folded(filename) then
              index = index + filenames[filename]
            end
          else
            cursor_line = cursor_line + 1
            index = index + 1
          end
        end

        local index_filename = results[index].filename
        local is_filename = (seen_filename[index_filename] == nil)

        if is_filename then
          local filtered_results = {}
          for _, result in ipairs(results) do
            if result.filename ~= index_filename then
              table.insert(filtered_results, result)
            end
          end

          require("trouble.providers.telescope").results = filtered_results
        else
          table.remove(results, index)
        end

        if #require("trouble.providers.telescope").results == 0 then
          require("trouble").close()
        else
          require("trouble").refresh({ provider = "telescope", auto = false })
        end
      end

      vim.keymap.set("n", "d", delete_entry, bufopts)
    end
  end,
})

When you enter a Trouble buffer and the provider is telescope, you can:

  • delete one entry pressing d
  • delete all entries in a file pressing d on the file
  • delete all entries pressing D

I can rewrite it using Trouble internals and open a PR if someone is interested!

Luceurre avatar Jan 26 '23 16:01 Luceurre

I made another version, paste it here in case someone needs. Thanks to @Luceurre

vim.api.nvim_create_autocmd({ "FileType" }, {
  pattern = "Trouble",
  callback = function(event)
    if require("trouble.config").options.mode ~= "telescope" then
      return
    end

    local function delete()
      local folds = require("trouble.folds")
      local telescope = require("trouble.providers.telescope")

      local ord = { "" } -- { filename, ... }
      local files = { [""] = { 1, 1, 0 } } -- { [filename] = { start, end, start_index } }
      for i, result in ipairs(telescope.results) do
        if files[result.filename] == nil then
          local next = files[ord[#ord]][2] + 1
          files[result.filename] = { next, next, i }
          table.insert(ord, result.filename)
        end
        if not folds.is_folded(result.filename) then
          files[result.filename][2] = files[result.filename][2] + 1
        end
      end

      local line = unpack(vim.api.nvim_win_get_cursor(0))
      for i, id in ipairs(ord) do
        if line == files[id][1] then -- Group
          local next = ord[i + 1]
          for _ = files[id][3], next and files[next][3] - 1 or #telescope.results do
            table.remove(telescope.results, files[id][3])
          end
          break
        elseif line <= files[id][2] then -- Item
          table.remove(telescope.results, files[id][3] + (line - files[id][1]) - 1)
          break
        end
      end

      if #telescope.results == 0 then
        require("trouble").close()
      else
        require("trouble").refresh { provider = "telescope", auto = false }
      end
    end

    vim.keymap.set("n", "x", delete, { buffer = event.buf })
  end,
})

sxyazi avatar May 08 '23 02:05 sxyazi