From 5533dbd7872caa6d7a0f4af5457f9d08220dc192 Mon Sep 17 00:00:00 2001 From: punkfairie Date: Thu, 2 Jan 2025 20:50:09 -0800 Subject: [PATCH] feat: fzf-lua --- nix/neovim-overlay.nix | 8 +- nvim/lua/plugins/editor/fzf-lua.lua | 294 ++++++++++++++++++ nvim/lua/plugins/editor/init.lua | 1 + .../lua/plugins/editor/todo-comments-nvim.lua | 16 +- 4 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 nvim/lua/plugins/editor/fzf-lua.lua diff --git a/nix/neovim-overlay.nix b/nix/neovim-overlay.nix index 98d2646..dc878d5 100644 --- a/nix/neovim-overlay.nix +++ b/nix/neovim-overlay.nix @@ -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 diff --git a/nvim/lua/plugins/editor/fzf-lua.lua b/nvim/lua/plugins/editor/fzf-lua.lua new file mode 100644 index 0000000..aa03b49 --- /dev/null +++ b/nvim/lua/plugins/editor/fzf-lua.lua @@ -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. + { + 'fb', + pick('buffers', { sort_mru = true, sort_lastused = true }), + desc = 'buffers', + }, + { 'ff', pick('files'), desc = 'find files (root dir)' }, + { + 'fF', + pick('files', { root = false }), + desc = 'find files (cwd)', + }, + { 'fg', pick('git_files'), desc = 'find files (git)' }, + { 'fr', pick('oldfiles'), desc = 'recent' }, + { + 'fR', + pick('oldfiles', { cwd = vim.uv.cwd() }), + desc = 'recent (cwd)', + }, + + -- Git. + { 'gc', pick('git_commits'), desc = 'commits' }, + { 'gs', pick('git_status'), desc = 'status' }, + + -- Search. + { 'sa', pick('autocmds'), desc = 'auto-commands' }, + { 'sb', pick('grep_curbuf'), desc = 'buffer' }, + { 'sc', pick('command_history'), desc = 'command history' }, + { 'sC', pick('commands'), desc = 'commands' }, + { + 'sd', + pick('diagnostics_document'), + desc = 'document diagnostics', + }, + { + 'sD', + pick('diagnostics_workspace'), + desc = 'workspace diagnostics', + }, + { 'sg', pick('live_grep'), desc = 'grep (root dir)' }, + { 'sG', pick('live_grep', { root = false }), desc = 'grep (cwd)' }, + { 'sh', pick('help_tags'), desc = 'help pages' }, + { 'sH', pick('highlights'), desc = 'search highlight groups' }, + { 'sj', pick('jumps'), desc = 'jumplist' }, + { 'sk', pick('keymaps'), desc = 'keymaps' }, + { 'sl', pick('loclist'), desc = 'location list' }, + { 'sm', pick('marks'), desc = 'jump to mark' }, + { 'sM', pick('man_pages'), desc = 'man pages' }, + { 'sq', pick('quickfix'), desc = 'quickfix list' }, + { 'sR', pick('resume'), desc = 'resume last picker' }, + { 'sw', pick('grep_cword'), desc = 'word under cursor (root dir)' }, + { + 'sw', + pick('grep_visual'), + mode = 'v', + desc = 'selection (root dir)', + }, + { + 'sW', + pick('grep_cword', { root = false }), + desc = 'word under cursor (cwd)', + }, + { + 'sW', + pick('grep_visual', { root = false }), + mode = 'v', + desc = 'selection (cwd)', + }, + { 's"', pick('registers'), desc = 'registers' }, + + -- Misc. + { 'uC', pick('colorschemes'), desc = 'colorschemes' }, + { '', pick('files'), desc = 'find files (root dir)' }, + { + ',', + pick('buffers', { sort_mru = true, sort_lastused = true }), + desc = 'switch buffer', + }, + { '/', pick('live_grep'), desc = 'grep (root dir)' }, + { ':', 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[''] = 'preview-page-down' + config.defaults.keymap.builtin[''] = '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, +} diff --git a/nvim/lua/plugins/editor/init.lua b/nvim/lua/plugins/editor/init.lua index d3083e6..1d855eb 100644 --- a/nvim/lua/plugins/editor/init.lua +++ b/nvim/lua/plugins/editor/init.lua @@ -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'), diff --git a/nvim/lua/plugins/editor/todo-comments-nvim.lua b/nvim/lua/plugins/editor/todo-comments-nvim.lua index f2e98ae..51ffc7c 100644 --- a/nvim/lua/plugins/editor/todo-comments-nvim.lua +++ b/nvim/lua/plugins/editor/todo-comments-nvim.lua @@ -3,10 +3,20 @@ return { event = { 'BufReadPost', 'BufWritePost', 'BufNewFile' }, cmd = { 'TodoTrouble', 'TodoTelescope' }, keys = { - { 'st', 'TodoTelescope', desc = 'todo search' }, + { + 'st', + function() + require('todo-comments.fzf').todo() + end, + desc = 'todo search', + }, { 'sT', - 'TodoTelescope keywords=TODO,FIX,FIXME', + function() + require('todo-comments.fzf').todo({ + keywords = { 'TODO', 'FIX', 'FIXME' }, + }) + end, desc = 'todo/fix/fixme search', }, { 'xt', 'Trouble todo toggle', 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({})