feat(plugins): add two‑stage find‑by‑extension command with <C-f>e shortcut

This commit is contained in:
Prad Nukala committed 2026-08-13 20:55:26 -04:00
1 parent fe02c6e258
commit fce59322a7
1 file changed
+52
+52
View File
@@ -18,6 +18,54 @@ local function with_trouble(source, opts)
require("snacks").picker[source](opts) require("snacks").picker[source](opts)
end end
-- <C-f>e: two-stage find-by-extension. Stage 1 scans the repo with fd
-- (respects .gitignore) and shows every file extension ranked by count;
-- stage 2 opens the regular files picker restricted to the chosen
-- extension (snacks passes `ft` to fd as `-e`).
local function find_files_by_extension()
local snacks = require "snacks"
local root = snacks.git.get_root() or vim.uv.cwd()
local files = vim.fn.systemlist { "fd", "--type", "f", "--base-directory", root }
if vim.v.shell_error ~= 0 then
vim.notify("fd failed to list files in " .. root, vim.log.levels.ERROR)
return
end
local counts = {}
for _, path in ipairs(files) do
-- last dot of the basename; skips dotfiles (.gitignore) and bare names
local ext = path:match "[^/]%.([%w_%-]+)$"
if ext then counts[ext] = (counts[ext] or 0) + 1 end
end
local items = {}
for ext, count in pairs(counts) do
items[#items + 1] = { text = ext, ext = ext, count = count }
end
if #items == 0 then
vim.notify("No file extensions found in " .. root, vim.log.levels.WARN)
return
end
table.sort(items, function(a, b)
if a.count ~= b.count then return a.count > b.count end
return a.ext < b.ext
end)
snacks.picker {
title = "File Extensions",
layout = { preset = "select" },
items = items,
format = function(item)
return {
{ ("%-12s"):format(item.ext), "SnacksPickerLabel" },
{ ("%d file%s"):format(item.count, item.count == 1 and "" or "s"), "SnacksPickerComment" },
}
end,
confirm = function(picker, item)
picker:close()
if not item then return end
snacks.picker.files { cwd = root, ft = item.ext, transform = file_filter }
end,
}
end
return { return {
"AstroNvim/astrocore", "AstroNvim/astrocore",
---@type AstroCoreOpts ---@type AstroCoreOpts
@@ -230,6 +278,10 @@ return {
function() require("snacks").picker.files { transform = file_filter } end, function() require("snacks").picker.files { transform = file_filter } end,
desc = "Find files (cwd)", desc = "Find files (cwd)",
}, },
["<C-f>e"] = {
find_files_by_extension,
desc = "Find files by extension",
},
["<C-f><C-f>"] = { ["<C-f><C-f>"] = {
function() function()
require("snacks").picker.lsp_symbols { layout = { preset = "vscode", preview = "main" } } require("snacks").picker.lsp_symbols { layout = { preset = "vscode", preview = "main" } }