-- Clues Config.leader_group_clues = { { mode = 'n', keys = 'b', desc = '+Buffer' }, { mode = 'n', keys = 'd', desc = '+Debug' }, { mode = 'n', keys = 'e', desc = '+Explore' }, { mode = 'n', keys = 'f', desc = '+Find' }, { mode = 'n', keys = 'g', desc = '+Git' }, { mode = 'n', keys = 'l', desc = '+Language' }, { mode = 'n', keys = 'r', desc = '+Request' }, { mode = 'n', keys = 't', desc = '+Terminal' }, { mode = 'n', keys = '', desc = '+Tab' }, { mode = 'x', keys = 'g', desc = '+Git' }, { mode = 'x', keys = 'l', desc = '+Language' }, } -- Keymap Helpers local leader = function(suffix, rhs, desc, mode) vim.keymap.set(mode or 'n', '' .. suffix, rhs, { desc = desc, silent = true }) end -- Buffers local new_scratch_buffer = function() vim.api.nvim_win_set_buf(0, vim.api.nvim_create_buf(true, true)) end local close_invisible_buffers = function() local visible = vim.iter(vim.api.nvim_list_wins()):map(vim.api.nvim_win_get_buf):totable() vim.iter(vim.api.nvim_list_bufs()) :filter(function(buf) return not vim.list_contains(visible, buf) end) :each(function(buf) pcall(vim.api.nvim_buf_delete, buf, { force = false }) end) end leader('bd', vim.cmd.bdelete, 'Delete') leader('bs', new_scratch_buffer, 'Scratch') leader('bw', vim.cmd.bwipeout, 'Wipeout') leader('bo', close_invisible_buffers, 'Close invisible buffers') -- Debug leader('db', function() require('dap').toggle_breakpoint() end, 'Toggle Breakpoint') leader('dl', function() require('dap').set_breakpoint(nil, nil, vim.fn.input('Log point: ')) end, 'Log point') leader('dc', function() require('dap').continue() end, 'Run/Continue') leader('dC', function() require('dap').run_to_cursor() end, 'Run to Cursor') leader('de', function() require('dap.ui.widgets').hover() end, 'Inspect') leader('dr', function() require('dap').repl.open() end, 'Open REPL') leader('dt', function() require('dap').terminate() end, 'Terminate') -- Explore local explore_at_file = function() local file = vim.api.nvim_buf_get_name(0) MiniFiles.open(vim.uv.fs_stat(file) and file or nil) end leader('ed', function() MiniFiles.open() end, 'Directory') leader('ef', explore_at_file, 'File directory') leader('ey', function() vim.fn.setreg('+', vim.fn.fnamemodify(vim.api.nvim_buf_get_name(0), ':.')) end, 'Yank relative path') leader('eY', function() vim.fn.setreg('+', vim.api.nvim_buf_get_name(0)) end, 'Yank absolute path') leader('en', vim.cmd.messages, 'Notifications') -- Find leader('fb', function() MiniPick.builtin.buffers() end, 'Buffers') leader('fc', function() MiniExtra.pickers.git_commits() end, 'Commits (all)') leader('fC', function() MiniExtra.pickers.git_commits({ path = vim.fn.expand('%') }) end, 'Commits (buf)') leader('fd', function() MiniExtra.pickers.diagnostic({ scope = 'all' }) end, 'Diagnostic workspace') leader('fD', function() MiniExtra.pickers.diagnostic({ scope = 'current' }) end, 'Diagnostic buffer') leader('ff', function() MiniPick.builtin.files() end, 'Files') leader('fg', function() MiniPick.builtin.grep_live() end, 'Grep live') leader('fG', function() MiniPick.builtin.grep({ pattern = vim.fn.expand('') }) end, 'Grep word') leader('fh', function() MiniPick.builtin.help() end, 'Help tags') leader('fl', function() MiniExtra.pickers.buf_lines({ scope = 'all' }) end, 'Lines (all)') leader('fL', function() MiniExtra.pickers.buf_lines({ scope = 'current' }) end, 'Lines (buf)') leader('fm', function() require('git').status() end, 'Modified / changed files') leader('fo', function() MiniExtra.pickers.oldfiles() end, 'Old / recent files') leader('fr', function() MiniPick.builtin.resume() end, 'Resume') leader('fs', function() MiniExtra.pickers.lsp({ scope = 'workspace_symbol_live' }) end, 'Symbols workspace') leader('fS', function() MiniExtra.pickers.lsp({ scope = 'document_symbol' }) end, 'Symbols document') leader('f:', function() MiniExtra.pickers.history({ scope = ':' }) end, 'Command history') -- Git local diff_unstaged = function() vim.cmd.diffthis() vim.cmd('vert Git show :./%') vim.cmd.diffthis() end leader('ga', function() vim.cmd('Git add %') end, 'Add current file') leader('gd', diff_unstaged, 'Diff unstaged') leader('gs', function() MiniGit.show_at_cursor() end, 'Show at cursor') leader('gs', function() MiniGit.show_at_cursor() end, 'Show at selection', 'x') -- Language leader('la', function() vim.lsp.buf.code_action() end, 'Actions') leader('lf', function() require('conform').format({ async = true }) end, 'Format') leader('lf', function() require('conform').format({ async = true }) end, 'Format selection', 'x') leader('li', function() vim.lsp.buf.implementation() end, 'Implementation') leader('ll', function() vim.lsp.codelens.run() end, 'Lens') leader('lr', function() vim.lsp.buf.rename() end, 'Rename') leader('lR', function() vim.lsp.buf.references() end, 'References') leader('ls', function() vim.lsp.buf.definition() end, 'Source definition') leader('lt', function() vim.lsp.buf.type_definition() end, 'Type definition') -- Request leader('rs', function() require('kulala').run() end, 'Send HTTP request') -- Terminal local open_ai = function() vim.cmd('vertical term ' .. (vim.fn.executable('pi') == 1 and 'pi' or 'claude')) end leader('tT', function() vim.cmd('horizontal term') end, 'Terminal (horizontal)') leader('tt', function() vim.cmd('vertical term') end, 'Terminal (vertical)') leader('ta', open_ai, 'AI') leader('tf', function() require('terminal').open(vim.o.shell) end, 'Terminal (popup)') leader('tg', function() require('terminal').open('lazygit') end, 'LazyGit') leader('ts', function() require('terminal').open('lazysql') end, 'LazySQL') -- Tabs leader('', vim.cmd.tabnew, 'New tab') leader('d', vim.cmd.tabclose, 'Close tab') leader(']', vim.cmd.tabnext, 'Next tab') leader('[', vim.cmd.tabprevious, 'Previous tab') -- Overwrites vim.keymap.set('n', '', vim.cmd.nohlsearch, { desc = 'Clear highlights', silent = true }) vim.keymap.set('t', '', '', { desc = 'Terminal window navigation', silent = true })