return { 'folke/which-key.nvim', event = 'VeryLazy', config = function() local wk = require('which-key') wk.setup({ preset = 'helix', plugins = { marks = true, registers = true, spelling = { enabled = true, suggestions = 30, }, }, presets = { operators = true, motions = true, text_objects = true, windows = true, nav = true, z = true, g = true, }, icons = { breadcrumb = ' ', separator = ' ', group = '', keys = { Space = ' ', }, rules = false, -- enable auto icon rules }, show_help = false, show_keys = true, triggers = { { '', mode = 'nvisoct' }, { '', mode = { 'n', 'v' } }, }, }) local normal_mappings = { mode = 'n', { 'x', ':x', desc = ' Save and Quit' }, -- { "a", group = " AI" }, { 'b', group = ' Buffer' }, { 'c', group = ' Code' }, { 'cF', ':retab', desc = 'Fix Tabs' }, { 'cd', ':RootDir', desc = 'Root Directory' }, { 'cf', ':lua vim.lsp.buf.format({async = true})', desc = 'Format File' }, { 'cg', ':Neogen', desc = 'Generate Docstring' }, { 'cl', '::g/^\\s*$/d', desc = 'Clean Empty Lines' }, { 'cm', ':MarkdownPreviewToggle', desc = 'Markdown Preview' }, { 'cq', ':lua Snacks.picker.qflist()', desc = 'Quickfix List' }, { 'e', group = ' Edit' }, { 'ea', ':b#', desc = 'Alternate File' }, { 'eC', group = 'Edit Configs' }, { 'ee', function() local minifiles = require('mini.files') minifiles.open(vim.api.nvim_buf_get_name(0), true) minifiles.reveal_cwd() end, desc = 'Explore Tree', }, { 'eE', ':lua Snacks.explorer()', desc = 'File Explorer' }, { 'ef', 'gf', desc = 'File Under Cursor' }, { 'em', ':e README.md', desc = 'Readme' }, { 'en', ':enew', desc = 'New File' }, { 'er', ":lua require('snacks').rename.rename_file()", desc = 'Rename Current File' }, { 'f', group = ' Find' }, { 'fx', ':%bd|e#|bd#', desc = 'Close except current' }, { 'ff', ':lua Snacks.picker.files()', desc = 'Find Files' }, { 'fg', ':lua Snacks.picker.grep()', desc = 'Live Grep' }, { 'fp', ':lua Snacks.picker.projects()', desc = 'Projects' }, { 'ct', function() local curr_path = vim.fn.expand('%:p') Snacks.picker.todo_comments({ transform = function(item) local item_path = vim.fn.fnamemodify(item.cwd .. '/' .. item.file, ':p') return item_path == curr_path end, }) end, desc = 'Search Todos in Current File', }, { 'fT', ':lua Snacks.picker.todo_comments()', desc = 'Search Todos' }, { 'fu', ':lua Snacks.picker.undo()', desc = 'Undotree' }, { 'g', group = ' Git' }, { 'gA', ':Gitsigns stage_buffer', desc = 'Stage Buffer' }, { 'gR', ':Gitsigns reset_buffer', desc = 'Reset Buffer' }, { 'ga', ':Gitsigns stage_hunk', desc = 'Stage Hunk' }, { 'gb', ":lua require('gitsigns').blame_line({full = true})", desc = 'Blame' }, { 'gB', ":lua require('snacks').git.blame_line()", desc = 'Detailed Blame' }, { 'gc', ':Gitignore', desc = 'Generate .gitignore' }, { 'gd', ':Gitsigns diffthis HEAD', desc = 'Git Diff' }, { 'gF', ':Git', desc = 'Fugitive Panel' }, { 'gi', ':Gitsigns preview_hunk', desc = 'Hunk Info' }, { 'gj', ':Gitsigns next_hunk', desc = 'Next Hunk' }, { 'gk', ':Gitsigns prev_hunk', desc = 'Prev Hunk' }, { 'gl', ':lua Snacks.picker.git_log()', desc = 'Checkout commit' }, { 'gr', ':Gitsigns reset_hunk', desc = 'Reset Hunk' }, { 'gs', ':lua Snacks.picker.git_status()', desc = 'Open changed file' }, { 'gu', ':Gitsigns undo_stage_hunk', desc = 'Undo Stage Hunk' }, { 'gv', ':Gitsigns select_hunk', desc = 'Select Hunk' }, { 'gw', ':lua require("snacks").gitbrowse()', desc = 'Git Browse' }, { 'gp', ':lua Snacks.picker.git_branches()', desc = 'Pick and Switch Git Branches' }, { 'gt', group = 'Toggle' }, { 'gtb', ':Gitsigns toggle_current_line_blame', desc = 'Blame' }, { 'gtd', ':Gitsigns toggle_deleted', desc = 'Deleted' }, { 'gtl', ':Gitsigns toggle_linehl', desc = 'Line HL' }, { 'gtn', ':Gitsigns toggle_numhl', desc = 'Number HL' }, { 'gts', ':Gitsigns toggle_signs', desc = 'Signs' }, { 'gtw', ':Gitsigns toggle_word_diff', desc = 'Word Diff' }, { 'i', group = ' Insert' }, { 'id', ":put =strftime('## %a, %d %b, %Y, %r')", desc = 'Date' }, { 'if', ":put =expand('%:t')", desc = 'File Name' }, { 'ip', ':put %', desc = 'Relative Path' }, { 'iP', ':put %:p', desc = 'Absolute Path' }, { 'it', ":put =strftime('## %r')", desc = 'Time' }, { 'l', group = ' LSP' }, { 'la', ':Lspsaga code_action', desc = 'Code Action' }, { 'ld', ':Lspsaga goto_definition', desc = 'Goto Definition' }, { 'lf', ':Lspsaga finder', desc = 'Finder' }, { 'lh', ':Lspsaga hover_doc', desc = 'Hover' }, { 'lI', ':LspInfo', desc = 'LSP Info' }, { 'lj', ':Lspsaga diagnostic_jump_next', desc = 'Next Diagnostic' }, { 'lk', ':Lspsaga diagnostic_jump_prev', desc = 'Prev Diagnostic' }, { 'lo', ':Lspsaga outline', desc = 'Outline' }, { 'lp', ':Lspsaga peek_definition', desc = 'Peek Definition' }, { 'lq', ':LspStop', desc = 'Stop LSP' }, { 'lQ', ':LspRestart', desc = 'Restart LSP' }, { 'lr', ':Lspsaga rename', desc = 'Rename' }, { 'lR', ':Lspsaga project_replace', desc = 'Replace' }, { 'lt', ':Lspsaga goto_type_definition', desc = 'Goto Type Definition' }, { 'lT', ':Lspsaga peek_type_definition', desc = 'Peek Type Definition' }, { 'o', group = ' Options' }, { 'oi', 'vim.show_pos', desc = 'Inspect Position' }, { 'oN', ':lua Snacks.notifier.show_history()', desc = 'Notification History' }, { 'or', ':set relativenumber!', desc = 'Relative Numbers' }, { 'p', group = ' Packages' }, { 'pc', ':Lazy check', desc = 'Check' }, { 'pd', ':Lazy debug', desc = 'Debug' }, { 'pe', ':lua require("snacks").profiler.scratch()', desc = 'Profiler Scratch' }, { 'pf', ':lua require("snacks").profiler.pick()', desc = 'Profiler Pick' }, { 'pi', ':Lazy install', desc = 'Install' }, { 'pl', ':Lazy log', desc = 'Log' }, { 'pm', ':Mason', desc = 'Mason' }, { 'pp', ':Lazy', desc = 'Plugins' }, { 'pP', ':Lazy profile', desc = 'Profile' }, { 'pr', ':Lazy restore', desc = 'Restore' }, { 'ps', ':Lazy sync', desc = 'Sync' }, { 'pt', ':lua require("snacks").profiler.toggle()', desc = 'Profiler Toggle' }, { 'pu', ':Lazy update', desc = 'Update' }, { 'px', ':Lazy clean', desc = 'Clean' }, { 'q', group = ' Quit' }, { 'qa', ':qall', desc = 'Quit All' }, { 'qb', ':bw', desc = 'Close Buffer' }, { 'qd', ':lua require("snacks").bufdelete()', desc = 'Delete Buffer' }, { 'qf', ':qall!', desc = 'Force Quit' }, { 'qo', ':%bdelete|b#|bdelete#', desc = 'Close Others' }, { 'qq', ':q', desc = 'Quit' }, { 'qs', 'c', desc = 'Close Split' }, { 'qw', ':wq', desc = 'Write and Quit' }, { 'r', group = ' Refactor' }, { 'rd', '', desc = 'Go To Definition' }, -- treesitter navigation { 'rD', '', desc = 'List Definition' }, { 'rh', '', desc = 'List Definition Head' }, { 'rj', '', desc = 'Next Usage' }, { 'rk', '', desc = 'Previous Usage' }, { 'rn', '', desc = 'Swap Next' }, { 'rp', '', desc = 'Swap Previous' }, { 'rr', '', desc = 'Smart Rename' }, { 'rs', ':%s/\\<\\>//gI', desc = 'Replace Word Buffer' }, { 's', group = ' Split' }, { 's+', ':resize +10', desc = 'Increase window height' }, { 's-', ':vertical resize -20', desc = 'Decrease window width' }, { 's/', 's', desc = 'Split Below' }, { 's=', ':vertical resize +20', desc = 'Increase window width' }, { 'sH', ':vertical resize -10', desc = 'Decrease window width' }, { 'sJ', ':resize -5', desc = 'Decrease window height' }, { 'sK', ':resize +5', desc = 'Increase window height' }, { 'sL', ':vertical resize +10', desc = 'Increase window width' }, { 's\\', 'v', desc = 'Split Right' }, { 's_', ':resize -10', desc = 'Decrease window height' }, { 's`', 'p', desc = 'Previous Window' }, { 'sa', ':split', desc = 'Horizontal Split' }, { 'sc', ':tabclose', desc = 'Close Tab' }, { 'sf', ':tabfirst', desc = 'First Tab' }, { 'sh', 'h', desc = 'Move Left' }, { 'sj', 'j', desc = 'Move Down' }, { 'sk', 'k', desc = 'Move Up' }, { 'sl', 'l', desc = 'Move Right' }, { 'sp', ':NavigatorPrevious', desc = 'Previous Pane' }, { 'sq', 'c', desc = 'Close Split' }, { 'ss', ':vsplit', desc = 'Vertical Split' }, { 't', group = ' Terminal' }, { 't1', '1ToggleTerm', desc = 'Toggle Terminal' }, { 't2', '2ToggleTerm', desc = 'Toggle Terminal' }, { 'tc', 'close', desc = 'Hide Terminal' }, { 'th', group = 'Inlay Hints' }, { 'w', group = ' Writing' }, { 'wc', ':set spell!', desc = 'Spellcheck' }, { 'wd', ':lua require("snacks").dim.enable()', desc = 'Dim On' }, { 'wD', ':lua require("snacks").dim.disable()', desc = 'Dim Off' }, { 'wf', ":lua require'utils'.sudo_write()", desc = 'Force Write' }, { 'wj', ']s', desc = 'Next Misspell' }, { 'wk', '[s', desc = 'Prev Misspell' }, { 'wn', ':WriteNoFormat', desc = 'Write Without Formatting' }, { 'wq', ':wq', desc = 'Write and Quit' }, { 'ww', ':w', desc = 'Write' }, { 'wz', ':lua require("snacks").zen.zen()', desc = 'Zen' }, { 'wZ', ':lua require("snacks").zen.zoom()', desc = 'Zoom' }, { 'y', group = ' Yank' }, { 'yL', ':CopyAbsolutePathWithLine', desc = 'Absolute Path with Line' }, { 'yP', ':CopyAbsolutePath', desc = 'Absolute Path' }, { 'ya', ':%y+', desc = 'Copy Whole File' }, { 'yf', ':CopyFileName', desc = 'File Name' }, { 'yg', ':lua require"gitlinker".get_buf_range_url()', desc = 'Copy Git URL' }, { 'yl', ':CopyRelativePathWithLine', desc = 'Relative Path with Line' }, { 'yp', ':CopyRelativePath', desc = 'Relative Path' }, } local visual_mappings = { mode = 'v', -- { "a", group = " AI" }, { 'c', group = ' Code' }, { 'cS', ':sort!', desc = 'Sort Desc' }, { 'ci', ':sort i', desc = 'Sort Case Insensitive' }, { 'cs', ':sort', desc = 'Sort Asc' }, { 'cu', ':!uniq', desc = 'Unique' }, { 'cx', ':lua', desc = 'Execute Lua' }, { 'g', group = ' Git' }, { 'ga', ":'<,'>Gitsigns stage_hunk", desc = 'Stage Hunk' }, { 'gr', ":'<,'>Gitsigns reset_hunk", desc = 'Reset Hunk' }, { 'gu', ":'<,'>Gitsigns undo_stage_hunk", desc = 'Undo Stage Hunk' }, { 'l', group = ' LSP' }, { 'la', ':Lspsaga range_code_action', desc = 'Code Action' }, { 'o', group = ' Options' }, { 'oc', ':CodeSnap', desc = 'CodeSnap into clipboard' }, { 'oC', ':CodeSnapSave', desc = 'CodeSnap in ~/Pictures' }, { 'y', group = ' Yank' }, { 'yg', ':lua require"gitlinker".get_buf_range_url("v")', desc = 'Copy Git URL' }, } local no_leader_mappings = { mode = 'n', { '', ':resize -10', desc = 'Decrease window height' }, { '', ':vertical resize -10', desc = 'Decrease window width' }, { '', ':vertical resize +10', desc = 'Increase window width' }, { '', ':resize +10', desc = 'Increase window height' }, { '', ':NavigatorLeft', desc = 'Move Left' }, { '', ':NavigatorDown', desc = 'Move Down' }, { '', ':NavigatorUp', desc = 'Move Up' }, { '', ':NavigatorRight', desc = 'Move Right' }, { '', ':NavigatorPrevious', desc = 'Previous Pane' }, -- { '', ':bprevious', desc = 'Previous Buffer' }, -- { '', ':bnext', desc = 'Next Buffer' }, { '', ':bnext', desc = 'Next Buffer' }, { '', ':bprevious', desc = 'Previous Buffer' }, { 'K', ':Lspsaga hover_doc', desc = 'LSP Hover' }, { 'Q', ':qall!', desc = 'Force Quit!' }, { 'U', ':redo', desc = 'Redo' }, { '[', group = ' Previous' }, { '[g', ':Gitsigns prev_hunk', desc = 'Git Hunk' }, { '[o', group = 'Textobjects' }, { ']', group = ' Next' }, { ']g', ':Gitsigns next_hunk', desc = 'Git Hunk' }, { ']o', group = 'Textobjects' }, { 'gd', ':Lspsaga goto_definition', desc = 'Goto Definition' }, } wk.add(normal_mappings) wk.add(visual_mappings) wk.add(no_leader_mappings) end, }