nvim-telescope/telescope.nvim

Group entries per file showing the total number of occurrences

2ax3ax5 opened this issue · 3 comments

Describe the solution you'd like
I'd like to see the live_grep information, but with only one entry per each file, showing also the number of matches per each file.

Is your feature request related to a problem? Please describe.
Sometime you use the live_grep for strings that are used a lot in some files. So you want to know at a glance the files that contain such string.

If you're willing to give up seeing the number of occurrences per file, this is pretty easily accomplished like so

local actions = require("telescope.actions")
local finders = require("telescope.finders")
local make_entry = require("telescope.make_entry")
local pickers = require("telescope.pickers")
local sorters = require("telescope.sorters")
local conf = require("telescope.config").values

local function files_with_matches(opts)
  opts = opts or {}
  opts.cwd = vim.loop.cwd()

  local live_grepper = finders.new_job(function(prompt)
    if not prompt or prompt == "" then
      return nil
    end

    return { "rg", "--files-with-matches", "--color", "never", "--", prompt }
  end, make_entry.gen_from_file(opts), opts.max_results, opts.cwd)

  pickers
  .new(opts, {
    prompt_title = "Files with Matches",
    finder = live_grepper,
    previewer = conf.grep_previewer(opts),
    sorter = sorters.highlighter_only(opts),
    attach_mappings = function(_, map)
      map("i", "<c-space>", actions.to_fuzzy_refine)
      return true
    end,
  })
  :find()
end

If seeing the number of occurrences is a hard requirement, this is no longer trivial. You would need to post-process the results from ripgrep and also need a custom entry maker.
Either way, I don't think this is something we'd be adding into telescope core. I can offer some guidance if you're interested in implementing this yourself but otherwise I'll close the issue.

Well, for my case I rather prefer calling rg with the -c option and not being able to jump to the files. This can be fixed by adding some plugin that handles opening filenames with the format PATH:LINE, like 'wsdjeg/vim-fetch', which is not what really you want in this case, but quite close...

At some point I will go further and post the proper solution in this thread - since I guess that for being able to jump to the files is what you described in

this is no longer trivial. You would need to post-process the results from ripgrep and also need a custom entry maker

Oh yeah I forgot about --count. With this you can get closer to what you're looking for I think

local actions = require("telescope.actions")
local finders = require("telescope.finders")
local make_entry = require("telescope.make_entry")
local pickers = require("telescope.pickers")
local sorters = require("telescope.sorters")
local conf = require("telescope.config").values
local utils = require("telescope.utils")

local function files_with_matches(opts)
  opts = opts or {}
  opts.cwd = vim.loop.cwd()

  -- metatable trickier for entry maker (currently undocumented)
  opts.entry_index = {
    data = function(entry)
      local file, count = unpack(vim.split(entry.value, ":"))
      return { file = file, count = count }, true
    end,
    path = function(entry)
      return entry.data.file, true
    end,
    display = function(entry)
      local hl_group, icon
      local display = utils.transform_path(opts, entry.path) .. ":" .. entry.data.count

      display, hl_group, icon = utils.transform_devicons(entry.path, display)

      if hl_group then
        return display, { { { 0, #icon }, hl_group } }
      else
        return display
      end
    end,
  }

  local live_grepper = finders.new_job(function(prompt)
    if not prompt or prompt == "" then
      return nil
    end

    return { "rg", "--count", "--color", "never", "--", prompt }
  end, make_entry.gen_from_file(opts), opts.max_results, opts.cwd)

  pickers
  .new(opts, {
    prompt_title = "Files with Matches",
    finder = live_grepper,
    previewer = conf.grep_previewer(opts),
    sorter = sorters.highlighter_only(opts),
    attach_mappings = function(_, map)
      map("i", "<c-space>", actions.to_fuzzy_refine)
      return true
    end,
  })
  :find()
end