2025-08-26 18:23:14 +01:00
-- Basic Keymaps
-- See `:help vim.keymap.set()`
2025-04-12 23:49:02 +01:00
2025-11-07 22:10:53 +00:00
local helpers = require ' helpers '
2025-04-12 23:49:02 +01:00
-- Swap : and ; around
2025-04-13 22:53:08 +01:00
vim.keymap . set ( { ' n ' , ' v ' } , ' : ' , ' ; ' )
vim.keymap . set ( { ' n ' , ' v ' } , ' ; ' , ' : ' )
2025-04-12 23:49:02 +01:00
-- Clear highlights on search when pressing <Esc> in normal mode
-- See `:help hlsearch`
vim.keymap . set ( ' n ' , ' <Esc> ' , ' <cmd>nohlsearch<CR> ' )
-- Diagnostic keymaps
vim.keymap . set ( ' n ' , ' <leader>q ' , vim.diagnostic . setloclist , { desc = ' Open diagnostic [Q]uickfix list ' } )
2025-08-26 18:23:14 +01:00
vim.keymap . set ( { ' n ' , ' v ' } , ' c ' , ' "zc ' , { desc = ' Change without copying to clipboard ' } )
vim.keymap . set ( { ' n ' , ' v ' } , ' x ' , ' "zx ' , { desc = ' Cut without copying to clipboard ' } )
vim.keymap . set ( ' v ' , ' p ' , ' "zdP ' , { desc = ' Paste over selection without yanking replaced text ' } )
2025-04-12 23:49:02 +01:00
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which
-- is not what someone will guess without a bit more experience.
--
-- NOTE: This won't work in all terminal emulators/tmux/etc. Try your own mapping
-- or just use <C-\><C-n> to exit terminal mode
vim.keymap . set ( ' t ' , ' <Esc><Esc> ' , ' <C- \\ ><C-n> ' , { desc = ' Exit terminal mode ' } )
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
vim.keymap . set ( ' n ' , ' <C-h> ' , ' <C-w><C-h> ' , { desc = ' Move focus to the left window ' } )
vim.keymap . set ( ' n ' , ' <C-l> ' , ' <C-w><C-l> ' , { desc = ' Move focus to the right window ' } )
vim.keymap . set ( ' n ' , ' <C-j> ' , ' <C-w><C-j> ' , { desc = ' Move focus to the lower window ' } )
vim.keymap . set ( ' n ' , ' <C-k> ' , ' <C-w><C-k> ' , { desc = ' Move focus to the upper window ' } )
2025-12-08 00:52:01 +00:00
vim.keymap . set ( { ' i ' } , ' <C-J> ' , function ( )
local ls = require ' luasnip '
if ls.choice_active ( ) then
ls.change_choice ( 1 )
end
end , { silent = true } )
vim.keymap . set ( { ' i ' } , ' <C-k> ' , function ( )
local ls = require ' luasnip '
if ls.choice_active ( ) then
ls.change_choice ( - 1 )
end
end , { silent = true } )
vim.keymap . set ( { ' i ' , ' s ' } , ' <C-L> ' , function ( )
local ls = require ' luasnip '
if ls.expandable ( ) then
ls.expand ( )
elseif ls.in_snippet ( ) then
ls.jump ( 1 )
end
end , { silent = true } )
vim.keymap . set ( { ' i ' , ' s ' } , ' <C-H> ' , function ( )
local ls = require ' luasnip '
if ls.in_snippet ( ) then
ls.jump ( - 1 )
end
end , { silent = true } )
2025-04-12 23:49:02 +01:00
vim.keymap . set ( ' n ' , ' <C-S-h> ' , ' <C-w>H ' , { desc = ' Move window to the left ' } )
vim.keymap . set ( ' n ' , ' <C-S-l> ' , ' <C-w>L ' , { desc = ' Move window to the right ' } )
vim.keymap . set ( ' n ' , ' <C-S-j> ' , ' <C-w>J ' , { desc = ' Move window to the lower ' } )
vim.keymap . set ( ' n ' , ' <C-S-k> ' , ' <C-w>K ' , { desc = ' Move window to the upper ' } )
2025-05-02 20:58:31 +01:00
vim.keymap . set ( ' n ' , ' <Leader>. ' , ' <Cmd>tabnext<CR> ' , { desc = ' Next tab ' } )
vim.keymap . set ( ' n ' , ' <Leader>, ' , ' <Cmd>tabprevious<CR> ' , { desc = ' Previous tab ' } )
2025-04-29 17:22:28 +01:00
2025-04-13 22:53:08 +01:00
-- Overriding CTRL mappings because some of them are stupid
2025-04-14 11:38:42 +01:00
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S-B> ' , ' <CMD>Git blame<CR> ' , { desc = ' Git blame ' } )
2025-04-13 22:53:08 +01:00
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-Q> ' , ' <CMD>Telescope lsp_document_symbols<CR> ' , { desc = ' Show symbols in current document ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S-Q> ' , ' <CMD>Telescope lsp_workspace_symbols<CR> ' , { desc = ' Show symbols in workspace ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-E> ' , ' <CMD>Telescope oldfiles<CR> ' , { desc = ' Show recently opened files ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-P> ' , function ( )
2025-04-15 20:48:35 +01:00
require ( ' telescope.builtin ' ) . find_files {
show_untracked = true ,
no_ignore = false ,
hidden = true ,
}
2025-04-14 15:20:54 +01:00
end , { desc = ' Find all files ' } )
2025-04-13 22:53:08 +01:00
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S-P> ' , function ( )
require ( ' telescope.builtin ' ) . find_files {
2025-04-14 15:20:54 +01:00
show_untracked = true ,
2025-04-13 22:53:08 +01:00
no_ignore = true ,
hidden = true ,
}
end , { desc = ' Find all files ' } )
2025-11-09 23:03:51 +00:00
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-f> ' , function ( )
2025-04-13 22:53:08 +01:00
require ( ' telescope.builtin ' ) . live_grep {
hidden = true ,
}
end , { desc = ' Search within the whole project ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-Y> ' , ' <CMD>Telescope quickfix<CR> ' , { desc = ' Show quickfix list ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S-Y> ' , ' <CMD>Telescope quickfixhistory<CR> ' , { desc = ' Show quickfix history ' } )
2025-04-14 11:38:42 +01:00
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-A> ' , ' <CMD>CodeCompanionChat Toggle<CR> ' , { desc = ' Open AI Actions ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S-A> ' , ' <CMD>CodeCompanionActions<CR> ' , { desc = ' Open AI Actions ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S> ' , function ( )
require ( ' snacks ' ) . scratch ( )
end , { desc = ' Open scratchpad ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-S-S> ' , function ( )
require ( ' snacks ' ) . scratch.select ( )
end , { desc = ' Open scratchpad buffers ' } )
vim.keymap . set ( { ' n ' , ' v ' , ' c ' , ' i ' } , ' <C-T> ' , function ( )
require ( ' snacks ' ) . terminal.toggle ( )
end , { desc = ' Open terminal ' } )
2025-04-13 22:53:08 +01:00
-- Editing helpers
vim.keymap . set ( ' i ' , ' <C-O> ' , ' <Esc>o ' , { desc = ' Add line below ' } )
vim.keymap . set ( ' i ' , ' <C-S-O> ' , ' <Esc>O ' , { desc = ' Add line above ' } )
2025-04-17 08:53:20 +01:00
local esc_keys = { ' jj ' , ' jk ' , ' kk ' }
for _ , key in ipairs ( esc_keys ) do
vim.keymap . set ( ' i ' , key , ' <Esc> ' , { desc = ' Exit insert mode ' } )
end
2025-04-13 22:53:08 +01:00
vim.keymap . set ( ' i ' , ' <C-D> ' , ' <Esc>ddi ' , { desc = ' Delete line ' } )
vim.keymap . set ( ' i ' , ' <Leader>; ' , ' <Esc>mzA;<Esc>`za ' , { desc = ' Append a semicolon ' } )
vim.keymap . set ( ' n ' , ' <Leader>; ' , ' mzA;<Esc>`za ' , { desc = ' Append a semicolon ' } )
vim.keymap . set ( ' n ' , ' <Leader>{ ' , ' mzF[`a<CR><Esc>``%i<CR><Esc>`z ' , { desc = ' Indent an array ' } )
vim.keymap . set ( ' n ' , ' <Leader>} ' , ' mzF[`a<CR><Esc>``%i<CR><Esc>`zvi[:s/, \\ s*/, \\ r/g<CR>vi[=<Esc>`z:nohlsearch<CR> ' , { desc = ' Indent an array some other way? ' } )
-- Git mappings
vim.keymap . set ( ' n ' , ' <Leader>gb ' , ' <CMD>Git blame<CR> ' , { desc = ' Git blame ' } )
vim.keymap . set ( ' n ' , ' <Leader>gd ' , ' <CMD>Git diff<CR> ' , { desc = ' Git diff ' } )
2025-04-14 15:20:54 +01:00
vim.keymap . set ( ' n ' , ' <Leader>gdc ' , ' <CMD>Git diff --cached<CR> ' , { desc = ' Git diff ' } )
2025-11-07 22:10:53 +00:00
vim.keymap . set ( ' n ' , ' <Leader>G ' , function ( )
helpers.open_term { cmd = ' lazygit ' }
end , { desc = ' Git ' } )
2025-04-13 22:53:08 +01:00
2025-04-29 17:22:28 +01:00
-- Add keymaps for diff mode
vim.api . nvim_create_autocmd ( ' BufEnter ' , {
callback = function ( )
if vim.wo . diff then
-- Keymaps for navigating hunks
vim.api . nvim_buf_set_keymap ( 0 , ' n ' , ' <Tab> ' , ' ]c ' , { noremap = true , silent = true , desc = ' Next hunk in diff mode ' } )
vim.api . nvim_buf_set_keymap ( 0 , ' n ' , ' <S-Tab> ' , ' [c ' , { noremap = true , silent = true , desc = ' Previous hunk in diff mode ' } )
-- Keymaps for resolving conflicts
vim.api . nvim_buf_set_keymap ( 0 , ' n ' , ' <leader>dl ' , ' :diffget LOCAL<CR> ' , { noremap = true , silent = true , desc = ' Get LOCAL changes ' } )
vim.api . nvim_buf_set_keymap ( 0 , ' n ' , ' <leader>dr ' , ' :diffget REMOTE<CR> ' , { noremap = true , silent = true , desc = ' Get REMOTE changes ' } )
end
end ,
} )
2025-04-13 22:53:08 +01:00
-- AI mappings
2025-05-11 18:22:45 +01:00
-- vim.keymap.set('v', '<Leader>ae', '<CMD>CodeCompanion<CR>', { desc = 'Edit selection with AI' })
-- vim.keymap.set('n', '<Leader>ac', '<CMD>CodeCompanionCmd<CR>', { desc = 'Run Neovim commands with AI' })
2025-04-29 17:22:28 +01:00
vim.api . nvim_create_autocmd ( ' FileType ' , {
pattern = ' codecompanion ' ,
callback = function ( )
2025-05-05 07:25:00 +01:00
vim.keymap . set ( ' i ' , ' <Enter> ' , function ( )
2025-05-02 20:58:31 +01:00
require ( ' codecompanion ' ) . last_chat ( ) : submit ( )
2025-05-05 07:25:00 +01:00
end , { buffer = true , desc = ' Use enter to send the message ' } )
2025-05-02 20:58:31 +01:00
vim.keymap . set ( ' i ' , ' <S-Enter> ' , ' <Enter> ' , { buffer = true , desc = ' Use shift enter to start a new line ' } )
vim.keymap . set ( ' n ' , ' <Enter> ' , ' G ' , { buffer = true , desc = ' Use enter in normal mode to go to the end of the chat ' } )
2025-04-29 17:22:28 +01:00
2025-11-10 09:19:30 +00:00
local models = { vim.env . DEFAULT_AI_MODEL , vim.env . REASONING_MODEL , vim.env . FAST_MODEL }
2025-04-29 17:22:28 +01:00
-- Loop through models and create keymaps for each
for i , model in ipairs ( models ) do
2025-05-07 07:58:00 +01:00
vim.keymap . set ( ' n ' , ' <C- ' .. i .. ' > ' , ' mzggj0W"_C ' .. model .. ' <Esc>`z ' , { desc = ' Switch to ' .. model } )
vim.keymap . set ( ' i ' , ' <C- ' .. i .. ' > ' , ' <Esc>mzggj0W"_C ' .. model .. ' <Esc>`za ' , { desc = ' Switch to ' .. model } )
2025-04-29 17:22:28 +01:00
end
end ,
} )
2025-04-13 22:53:08 +01:00
-- Search mappings
vim.keymap . set ( ' n ' , ' <Leader>sGb ' , ' <CMD>Telescope git_branches<CR> ' , { desc = ' Search git branches ' } )
vim.keymap . set ( ' n ' , ' <Leader>sGc ' , ' <CMD>Telescope git_commits<CR> ' , { desc = ' Search git history ' } )
vim.keymap . set ( ' n ' , ' <Leader>sGh ' , ' <CMD>Telescope git_bcommits<CR> ' , { desc = ' Search git history within current buffer/selection ' } )
vim.keymap . set ( ' n ' , ' <Leader>sGs ' , ' <CMD>Telescope git_status<CR> ' , { desc = ' Search git status ' } )
vim.keymap . set ( ' n ' , ' <Leader>sGS ' , ' <CMD>Telescope git_stash<CR> ' , { desc = ' Search git stash ' } )
-- Misc
vim.keymap . set ( ' n ' , ' <Leader>] ' , ' <CMD>cnext<CR> ' , { desc = ' Next item in quickfix list ' } )
vim.keymap . set ( ' n ' , ' <Leader>[ ' , ' <CMD>cprevious<CR> ' , { desc = ' Previous item in quickfix list ' } )
vim.keymap . set ( ' n ' , ' gd ' , ' <CMD>Telescope lsp_definitions<CR> ' , { desc = ' Go to definition ' } )
2025-04-17 08:53:20 +01:00
local function open_test ( )
require ( ' neotest ' ) . summary.open ( )
require ( ' neotest ' ) . output_panel.open ( )
end
-- Testing
local test_maps = {
{
keys = { ' <F12> ' , ' <Leader>tn ' } ,
action = function ( )
require ( ' neotest ' ) . run.run ( )
open_test ( )
end ,
desc = ' Run nearest test ' ,
} ,
{
keys = { ' <F9> ' , ' <Leader>ta ' } ,
action = function ( )
require ( ' neotest ' ) . run.run { suite = true }
open_test ( )
end ,
desc = ' Run all tests in the project ' ,
} ,
{
keys = { ' <F11> ' , ' <Leader>tp ' } ,
action = function ( )
require ( ' neotest ' ) . run.run_last ( )
open_test ( )
end ,
desc = ' Run previous test again ' ,
} ,
{
keys = { ' <F10> ' , ' <Leader>td ' } ,
action = function ( )
2025-05-07 07:58:00 +01:00
local dap = require ' dap '
if dap.session ( ) == nil then
dap.continue ( )
end
require ( ' dapui ' ) . open ( )
local neotest = require ' neotest '
local bufnr = vim.api . nvim_get_current_buf ( )
local row = vim.api . nvim_win_get_cursor ( 0 ) [ 1 ] - 1
local adapters = neotest.state . adapter_ids ( )
local found = false
for _ , adapter_id in ipairs ( adapters ) do
local tree = neotest.state . positions ( adapter_id , { buffer = bufnr } )
if tree then
local nearest = require ( ' neotest.lib.positions ' ) . nearest ( tree , row )
if nearest and nearest : data ( ) . type ~= ' file ' then
neotest.run . run ( )
found = true
break
end
end
end
if not found then
neotest.run . run_last ( )
end
2025-04-17 08:53:20 +01:00
end ,
desc = ' Run last test with debugger ' ,
} ,
}
for _ , map_info in ipairs ( test_maps ) do
for _ , key in ipairs ( map_info.keys ) do
vim.keymap . set ( ' n ' , key , map_info.action , { desc = map_info.desc } )
end
end
vim.keymap . set ( ' n ' , ' <Leader>tf ' , function ( )
require ( ' neotest ' ) . run.run ( vim.fn . expand ' % ' )
open_test ( )
end , { desc = ' Run all tests in the current file ' } )
vim.keymap . set ( ' n ' , ' <Leader>tc ' , function ( )
require ( ' neotest ' ) . summary.close ( )
require ( ' neotest ' ) . output_panel.close ( )
end , { desc = ' Close test panels ' } )
2025-08-26 18:23:14 +01:00
-- vim.keymap.set('i', '<Tab>', function()
-- local copilot = require 'copilot.suggestion'
-- local ls = require 'luasnip'
-- if copilot.is_visible() then
-- vim.api.nvim_echo({{'Accepting copilot suggestion'}}, false, {})
-- copilot.accept()
-- copilot.dismiss()
-- elseif ls.jumpable(1) then
-- vim.api.nvim_echo({{'Jumping in snippet'}}, false, {})
-- ls.jump()
-- else
-- vim.api.nvim_echo({{'Inserting tab'}}, false, {})
-- vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Tab>', true, true, true), 'n', true)
-- end
-- end, { desc = 'Luasnip accept copilot or jump forward' })
2025-04-13 22:53:08 +01:00
-- Leaving this commented out, I will try the format command instead
-- "A command to properly indent json code
-- command! FormatJSON %!python -m json.tool
2025-04-24 11:59:36 +01:00
-- Edit the snippet file for the current buffer filetype or the snippets
-- directory if the file does not exist
vim.keymap . set ( ' n ' , ' <Leader>es ' , function ( )
local ft = vim.bo . filetype
2025-08-26 18:23:14 +01:00
if ft == ' vue ' then
ft = ' javascript '
end
2025-04-24 11:59:36 +01:00
local snippets_dir = vim.fn . stdpath ' config ' .. ' /lua/snippets '
2025-08-26 18:23:14 +01:00
local snippets_file = snippets_dir .. ' / ' .. ft .. ' .lua '
2025-04-24 11:59:36 +01:00
vim.cmd ( ' tabedit ' .. snippets_file )
end , { desc = ' Edit snippets file ' } )
2025-04-12 23:49:02 +01:00
require ( ' helpers ' ) . edit_cf ( ' k ' , ' /lua/keymap.lua ' )