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 ' } )
2025-12-08 16:33:11 +00:00
vim.keymap . set ( ' n ' , ' <Leader>c ' , function ( )
2025-12-09 22:10:16 +00:00
vim.treesitter . inspect_tree ( )
end , { desc = ' Treesitter ' } )
vim.keymap . set ( ' n ' , ' <C-S-D> ' , function ( )
local node = vim.treesitter . get_node { }
local range = { vim.treesitter . get_node_range ( node ) }
vim.api . nvim_win_set_cursor ( 0 , { range [ 3 ] + 1 , range [ 4 ] - 1 } )
vim.fn . setpos ( " 'x " , { 0 , range [ 1 ] + 1 , range [ 2 ] + 1 , 0 } )
vim.cmd . normal ' v`x '
end , { desc = ' Select surrounding treesitter node ' } )
vim.keymap . set ( ' v ' , ' <C-S-D> ' , function ( )
2025-12-09 22:49:24 +00:00
local start = vim.api . nvim_win_get_cursor ( 0 )
local start_row , start_column
if start [ 2 ] == 0 then
start_row = start [ 1 ] - 1
start_column = 0
else
start_row = start [ 1 ]
start_column = start [ 2 ] - 1
2025-12-08 16:33:11 +00:00
end
2025-12-09 22:49:24 +00:00
vim.api . nvim_win_set_cursor ( 0 , { start_row , start_column } )
local node = vim.treesitter . get_node { }
local range = { vim.treesitter . get_node_range ( node ) }
2025-12-09 22:10:16 +00:00
vim.api . nvim_win_set_cursor ( 0 , { range [ 3 ] + 1 , range [ 4 ] - 1 } )
vim.fn . setpos ( " 'x " , { 0 , range [ 1 ] + 1 , range [ 2 ] + 1 , 0 } )
vim.cmd . normal ' i '
vim.cmd . normal ' v`x '
end , { desc = ' Select surrounding treesitter node ' } )
2025-12-09 22:49:24 +00:00
local swappable_nodes = { ' argument ' , ' array_element_initializer ' , ' simple_parameter ' , ' string ' , ' integer ' , ' member_call_expression ' , ' method_declaration ' }
local function closest_swappable_node ( node )
2025-12-09 23:07:24 +00:00
while node and not vim.list_contains ( swappable_nodes , node : type ( ) ) and ( not node : next_named_sibling ( ) or not node : prev_named_sibling ( ) ) do
2025-12-09 22:49:24 +00:00
node = node : parent ( )
end
return node
end
2025-12-09 22:10:16 +00:00
vim.keymap . set ( { ' n ' } , ' <C-S-h> ' , function ( )
2025-12-09 22:49:24 +00:00
local node = closest_swappable_node ( vim.treesitter . get_node ( ) )
if not node then
return
end
local prev_node = node : prev_named_sibling ( )
while prev_node and not vim.list_contains ( swappable_nodes , prev_node : type ( ) ) do
prev_node = prev_node : prev_named_sibling ( )
end
2025-12-09 22:10:16 +00:00
if prev_node == nil then
return
end
2025-12-09 22:49:24 +00:00
require ( ' nvim-treesitter.ts_utils ' ) . swap_nodes ( node , prev_node , 0 , true )
2025-12-09 22:10:16 +00:00
end , { desc = ' Swap with node to the left ' } )
vim.keymap . set ( { ' n ' } , ' <C-S-l> ' , function ( )
2025-12-09 22:49:24 +00:00
local node = closest_swappable_node ( vim.treesitter . get_node ( ) )
if not node then
return
end
local next_node = node : next_named_sibling ( )
while next_node and not vim.list_contains ( swappable_nodes , next_node : type ( ) ) do
next_node = next_node : next_named_sibling ( )
end
2025-12-09 22:10:16 +00:00
if next_node == nil then
return
end
2025-12-09 22:49:24 +00:00
require ( ' nvim-treesitter.ts_utils ' ) . swap_nodes ( node , next_node , 0 , true )
2025-12-09 22:10:16 +00:00
end , { desc = ' Swap with node to the right ' } )
2025-12-09 22:49:24 +00:00
vim.keymap . set ( ' n ' , ' <C-S-j> ' , ' ddp ' , { desc = ' Move line down ' } )
vim.keymap . set ( ' n ' , ' <C-S-k> ' , ' ddkP ' , { desc = ' Move line up ' } )
vim.keymap . set ( ' v ' , ' <C-S-j> ' , ' do<Esc>p`[v`] ' , { desc = ' Move selection down ' } )
vim.keymap . set ( ' v ' , ' <C-S-k> ' , ' dkO<Esc>p`[v`] ' , { desc = ' Move selection up ' } )
2025-12-08 16:33:11 +00:00
2025-04-12 23:49:02 +01:00
-- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows
--
-- See `:help wincmd` for a list of all window commands
2025-12-09 16:24:08 +00:00
local function win_or_treesj ( dir_cmd , desc )
return function ( )
local cur = vim.api . nvim_get_current_win ( )
vim.cmd ( ' wincmd ' .. dir_cmd )
if vim.api . nvim_get_current_win ( ) == cur then
local ok , treesj = pcall ( require , ' treesj ' )
if ok and type ( treesj.toggle ) == ' function ' then
treesj.toggle ( )
end
end
end , { desc = desc }
end
2025-04-12 23:49:02 +01:00
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 ' } )
2025-12-09 16:24:08 +00:00
vim.keymap . set ( ' n ' , ' <C-j> ' , ( win_or_treesj ) ( ' j ' , ' Move focus to the lower window or treesj.toggle() ' ) )
vim.keymap . set ( ' n ' , ' <C-k> ' , ( win_or_treesj ) ( ' k ' , ' Move focus to the upper window or treesj.toggle() ' ) )
2025-04-12 23:49:02 +01:00
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
2025-12-09 16:24:08 +00:00
end , { desc = ' Toggle snippet choice ' , silent = true } )
2025-12-08 00:52:01 +00:00
vim.keymap . set ( { ' i ' } , ' <C-k> ' , function ( )
local ls = require ' luasnip '
if ls.choice_active ( ) then
ls.change_choice ( - 1 )
end
2025-12-09 16:24:08 +00:00
end , { desc = ' Toggle snippet choice ' , silent = true } )
2025-12-08 00:52:01 +00:00
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
2025-12-09 16:24:08 +00:00
end , { desc = ' Expand snippet ' , silent = true } )
2025-12-08 00:52:01 +00:00
vim.keymap . set ( { ' i ' , ' s ' } , ' <C-H> ' , function ( )
local ls = require ' luasnip '
if ls.in_snippet ( ) then
ls.jump ( - 1 )
end
2025-12-09 16:24:08 +00:00
end , { desc = ' Go back a snippet slot ' , silent = true } )
2025-12-08 00:52:01 +00:00
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
2025-12-09 22:10:16 +00:00
-- 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()
-- 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
-- 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-04-17 08:53:20 +01:00
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 ' )