-- 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', 'x' }, keys = 'g', desc = '+Git' }, { mode = { 'n', 'x' }, keys = 'l', desc = '+Language' }, { mode = 'n', keys = 'r', desc = '+Request' }, { mode = 'n', keys = 't', desc = '+Terminal' }, { mode = 'n', keys = '', desc = '+Tab' }, } -- 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', { 'n', 'x' }) -- Language leader('la', function() vim.lsp.buf.code_action() end, 'Actions') leader('lf', function() require('conform').format({ async = true }) end, 'Format', { 'n', '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 })