feat: fzf-lua

This commit is contained in:
punkfairie 2025-01-02 20:50:09 -08:00
parent 983705f3b0
commit 5533dbd787
Signed by: punkfairie
GPG key ID: A509E8F77FB9D696
4 changed files with 315 additions and 4 deletions

View file

@ -55,6 +55,7 @@ with final.pkgs.lib; let
trouble-nvim
todo-comments-nvim
aerial-nvim
fzf-lua
# Treesitter
nvim-treesitter-textobjects
@ -113,7 +114,12 @@ with final.pkgs.lib; let
extraPackages = with pkgs; [
# System packages
ripgrep
lazygit
lazygit # snacks.nvim
fzf # fzf-lua
fd # fzf-lua
bat # fzf-lua
delta # fzf-lua
chafa # fzf-lua
# Language servers
lua-language-server

View file

@ -0,0 +1,294 @@
---@param picker string
---@param opts? table
local function pick(picker, opts)
opts = opts or {}
return function()
require('fzf-lua')[picker](opts)
end
end
return {
'fzf-lua',
cmd = 'FzfLua',
keys = {
-- Find.
{
'<LEADER>fb',
pick('buffers', { sort_mru = true, sort_lastused = true }),
desc = 'buffers',
},
{ '<LEADER>ff', pick('files'), desc = 'find files (root dir)' },
{
'<LEADER>fF',
pick('files', { root = false }),
desc = 'find files (cwd)',
},
{ '<LEADER>fg', pick('git_files'), desc = 'find files (git)' },
{ '<LEADER>fr', pick('oldfiles'), desc = 'recent' },
{
'<LEADER>fR',
pick('oldfiles', { cwd = vim.uv.cwd() }),
desc = 'recent (cwd)',
},
-- Git.
{ '<LEADER>gc', pick('git_commits'), desc = 'commits' },
{ '<LEADER>gs', pick('git_status'), desc = 'status' },
-- Search.
{ '<LEADER>sa', pick('autocmds'), desc = 'auto-commands' },
{ '<LEADER>sb', pick('grep_curbuf'), desc = 'buffer' },
{ '<LEADER>sc', pick('command_history'), desc = 'command history' },
{ '<LEADER>sC', pick('commands'), desc = 'commands' },
{
'<LEADER>sd',
pick('diagnostics_document'),
desc = 'document diagnostics',
},
{
'<LEADER>sD',
pick('diagnostics_workspace'),
desc = 'workspace diagnostics',
},
{ '<LEADER>sg', pick('live_grep'), desc = 'grep (root dir)' },
{ '<LEADER>sG', pick('live_grep', { root = false }), desc = 'grep (cwd)' },
{ '<LEADER>sh', pick('help_tags'), desc = 'help pages' },
{ '<LEADER>sH', pick('highlights'), desc = 'search highlight groups' },
{ '<LEADER>sj', pick('jumps'), desc = 'jumplist' },
{ '<LEADER>sk', pick('keymaps'), desc = 'keymaps' },
{ '<LEADER>sl', pick('loclist'), desc = 'location list' },
{ '<LEADER>sm', pick('marks'), desc = 'jump to mark' },
{ '<LEADER>sM', pick('man_pages'), desc = 'man pages' },
{ '<LEADER>sq', pick('quickfix'), desc = 'quickfix list' },
{ '<LEADER>sR', pick('resume'), desc = 'resume last picker' },
{ '<LEADER>sw', pick('grep_cword'), desc = 'word under cursor (root dir)' },
{
'<LEADER>sw',
pick('grep_visual'),
mode = 'v',
desc = 'selection (root dir)',
},
{
'<LEADER>sW',
pick('grep_cword', { root = false }),
desc = 'word under cursor (cwd)',
},
{
'<LEADER>sW',
pick('grep_visual', { root = false }),
mode = 'v',
desc = 'selection (cwd)',
},
{ '<LEADER>s"', pick('registers'), desc = 'registers' },
-- Misc.
{ '<LEADER>uC', pick('colorschemes'), desc = 'colorschemes' },
{ '<LEADER><SPACE>', pick('files'), desc = 'find files (root dir)' },
{
'<LEADER>,',
pick('buffers', { sort_mru = true, sort_lastused = true }),
desc = 'switch buffer',
},
{ '<LEADER>/', pick('live_grep'), desc = 'grep (root dir)' },
{ '<LEADER>:', pick('command_history'), desc = 'command history' },
},
before_all = function()
vim.ui.select = function(...)
require('lz.n').trigger_load('fzf-lua')
require('fzf-lua').register_ui_select(function(fzf_opts, items)
return vim.tbl_deep_extend('force', fzf_opts, {
prompt = '',
winopts = {
title = ' '
.. vim.trim((fzf_opts.prompt or 'Select'):gsub('%s*:%s*$', ''))
.. ' ',
title_pos = 'center',
},
}, fzf_opts.kind == 'codeaction' and {
winopts = {
layout = 'vertical',
height = math.floor(
math.min(vim.o.lines * 0.8 - 16, #items + 2) + 0.5
) + 16,
preview = not vim.tbl_isempty(
vim.lsp.get_clients({ bufnr = 0, name = 'vtsls' })
)
and {
layout = 'vertical',
vertical = 'down:15,border-top',
hidden = 'hidden',
}
or {
layout = 'vertical',
vertical = 'down:15,border-top',
},
},
} or {
winopts = {
width = 0.5,
height = math.floor(math.min(vim.o.lines * 0.8, #items + 2) + 0.5),
},
})
end)
return vim.ui.select(...)
end
end,
after = function()
local config = require('fzf-lua.config')
local actions = require('fzf-lua.actions')
-- quickfix
config.defaults.keymap.fzf['ctrl-q'] = 'select-all+accept'
config.defaults.keymap.fzf['ctrl-u'] = 'half-page-up'
config.defaults.keymap.fzf['ctrl-d'] = 'half-page-down'
config.defaults.keymap.fzf['ctrl-x'] = 'jump'
config.defaults.keymap.fzf['ctrl-f'] = 'preview-page-down'
config.defaults.keymap.fzf['ctrl-b'] = 'preview-page-up'
config.defaults.keymap.builtin['<c-f>'] = 'preview-page-down'
config.defaults.keymap.builtin['<c-b>'] = 'preview-page-up'
-- trouble.nvim
config.defaults.actions.files['ctrl-t'] =
require('trouble.sources.fzf').actions.open
local img_previewer = { 'chafa', '{file}', '--format=symbols' }
local opts = {
-- Base profile.
'default-title',
fzf_colors = true,
fzf_opts = {
['--no-scrollbar'] = true,
},
defaults = {
formatter = 'path.dirname_first',
},
previewers = {
builtin = {
extensions = {
['png'] = img_previewer,
['jpg'] = img_previewer,
['jpeg'] = img_previewer,
['gif'] = img_previewer,
['webp'] = img_previewer,
},
},
},
winopts = {
width = 0.8,
height = 0.8,
row = 0.5,
col = 0.5,
preview = {
scrollchars = { '', '' },
},
},
files = {
cwd_prompt = false,
actions = {
['alt-i'] = { actions.toggle_ignore },
['alt-h'] = { actions.toggle_hidden },
},
},
grep = {
actions = {
['alt-i'] = { actions.toggle_ignore },
['alt-h'] = { actions.toggle_hidden },
},
},
lsp = {
symbols = {
symbol_hl = function(s)
return 'TroubleIcon' .. s
end,
symbol_fmt = function(s)
return s:lower() .. '\t'
end,
child_prefix = false,
},
code_actions = {
previewer = 'codeaction_native',
},
},
}
-- Use the same prompt for all pickers for profile 'default-title'.
local function fix(table)
table.prompt = table.prompt ~= nil and '' or nil
-- Recurse into subtables.
for _, value in pairs(table) do
if type(value) == 'table' then
fix(value)
end
end
return table
end
opts = vim.tbl_deep_extend(
'force',
fix(require('fzf-lua.profiles.default-title')),
opts
)
-- Don't let fzf-lua apply the profile as we've already done so above.
opts[1] = nil
require('fzf-lua').setup(opts)
-- LSP keybinds.
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if not client then
return
end
local set = vim.keymap.set
local pickOpts =
{ jump_to_single_result = true, ignore_current_line = true }
set(
'n',
'gI',
pick('lsp_implementations', pickOpts),
{ desc = 'implementation' }
)
set(
'n',
'gr',
pick('lsp_references', pickOpts),
{ desc = 'references', nowait = true }
)
set(
'n',
'gy',
pick('lsp_typedefs', pickOpts),
{ desc = 't[y]pe definition' }
)
if client.supports_method('textDocument/definition') then
set(
'n',
'gd',
pick('lsp_definitions', pickOpts),
{ desc = 'definition' }
)
end
end,
})
end,
}

View file

@ -3,6 +3,7 @@ local req = MarleyVim.local_require('plugins.editor')
return {
req('aerial-nvim'),
req('flash-nvim'),
req('fzf-lua'),
req('gitsigns-nvim'),
req('grug-far-nvim'),
req('neo-tree-nvim'),

View file

@ -3,10 +3,20 @@ return {
event = { 'BufReadPost', 'BufWritePost', 'BufNewFile' },
cmd = { 'TodoTrouble', 'TodoTelescope' },
keys = {
{ '<LEADER>st', '<CMD>TodoTelescope<CR>', desc = 'todo search' },
{
'<LEADER>st',
function()
require('todo-comments.fzf').todo()
end,
desc = 'todo search',
},
{
'<LEADER>sT',
'<CMD>TodoTelescope keywords=TODO,FIX,FIXME<CR>',
function()
require('todo-comments.fzf').todo({
keywords = { 'TODO', 'FIX', 'FIXME' },
})
end,
desc = 'todo/fix/fixme search',
},
{ '<LEADER>xt', '<CMD>Trouble todo toggle<CR>', desc = 'todo' },
@ -31,7 +41,7 @@ return {
},
},
before = function()
require('lz.n').trigger_load({ 'trouble.nvim' })
require('lz.n').trigger_load({ 'trouble.nvim', 'fzf-lua' })
end,
after = function()
require('todo-comments').setup({})