Hi I wanted to create a key map of ctrl + {hjkl}
to be able to move through the code, with these keys while I'm in insert mode.
Here is what i wrote in my keymaps.lua
file:
local function map(mode, lhs, rhs, opts)
local options = { noremap = true, silent = true }
if opts then
options = vim.tbl_extend('force', options, opts)
end
vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end
-- InsertMode movement
map('i', '<C-h>', '<Left>')
map('i', '<C-j>', '<Down>')
map('i', '<C-k>', '<Up>')
map('i', '<C-l>', '<Right>')
The problem is that and are working correctly but and do not seem to do any thing at all. I also checked if terminal is sending the correct keys when I press them and i think it was OK.
Anyone has any idea about it or any better ways to move in insert mode would be appreciated.
Update:
- I tried 4 different terminals (Ghostty - Kitty - xterm - cosmic terminal) and none worked so it is not terminal related issue
- I tried removing keymaps first and It throw an error saying the keymaps does not exist to delete them
- I tried modern way of setting the keymaps and they did not worked
- For some reason none of the mappings in insert mode were listed in
:map
commands output while two of them were working.
Hi I wanted to create a key map of ctrl + {hjkl}
to be able to move through the code, with these keys while I'm in insert mode.
Here is what i wrote in my keymaps.lua
file:
local function map(mode, lhs, rhs, opts)
local options = { noremap = true, silent = true }
if opts then
options = vim.tbl_extend('force', options, opts)
end
vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end
-- InsertMode movement
map('i', '<C-h>', '<Left>')
map('i', '<C-j>', '<Down>')
map('i', '<C-k>', '<Up>')
map('i', '<C-l>', '<Right>')
The problem is that and are working correctly but and do not seem to do any thing at all. I also checked if terminal is sending the correct keys when I press them and i think it was OK.
Anyone has any idea about it or any better ways to move in insert mode would be appreciated.
Update:
- I tried 4 different terminals (Ghostty - Kitty - xterm - cosmic terminal) and none worked so it is not terminal related issue
- I tried removing keymaps first and It throw an error saying the keymaps does not exist to delete them
- I tried modern way of setting the keymaps and they did not worked
- For some reason none of the mappings in insert mode were listed in
:map
commands output while two of them were working.
3 Answers
Reset to default 1Your Lua configuration for Neovim key mappings looks correct. However, the issue with <C-j>
and <C-k>
not working in insert mode is likely due to terminal settings or conflicts with Neovim's built-in keybindings.
Possible Issues & Fixes:
1. Check Terminal Keybindings
Some terminals (e.g., Alacritty, Kitty, or even default terminal emulators) might not send <C-j>
and <C-k>
correctly. You can check what keys are being sent using:
:imap <C-j>
:imap <C-k>
If nothing appears, your terminal might be intercepting these keybindings.
2. Disable Default <C-j>
and <C-k>
Mappings
Neovim has built-in behavior for <C-j>
and <C-k>
in insert mode (e.g., <C-j>
might trigger a snippet expansion in some setups). Try adding this to ensure they work as expected:
vim.api.nvim_del_keymap('i', '<C-j>')
vim.api.nvim_del_keymap('i', '<C-k>')
Then reapply your mappings:
map('i', '<C-h>', '<Left>')
map('i', '<C-j>', '<Down>')
map('i', '<C-k>', '<Up>')
map('i', '<C-l>', '<Right>')
3. Use vim.keymap.set
Instead
A more modern way to define key mappings in Neovim is using vim.keymap.set
. Try replacing your mapping function with:
vim.keymap.set('i', '<C-h>', '<Left>', { noremap = true, silent = true })
vim.keymap.set('i', '<C-j>', '<Down>', { noremap = true, silent = true })
vim.keymap.set('i', '<C-k>', '<Up>', { noremap = true, silent = true })
vim.keymap.set('i', '<C-l>', '<Right>', { noremap = true, silent = true })
4. Debug Terminal Input
To ensure your terminal sends the correct keys, run this inside Neovim:
:map <C-j>
:map <C-k>
If nothing appears, your terminal might not be passing <C-j>
and <C-k>
to Neovim.
5. Alternative Keybindings
If the issue persists, you can try different keybindings that are less likely to be intercepted:
map('i', '<C-n>', '<Down>') -- Alternative for <C-j>
map('i', '<C-p>', '<Up>') -- Alternative for <C-k>
Conclusion
If <C-j>
and <C-k>
still don’t work:
- Check if your terminal is capturing those keys.
- Try using
vim.keymap.set
instead ofvim.api.nvim_set_keymap
. - Use
vim.api.nvim_del_keymap('i', '<C-j>')
before remapping. - Use alternative key combinations like
<C-n>
and<C-p>
.
I think they are not applying because of the default behavior in some Neovim configurations.
-- first unset it,
vim.keymap.del('i', '<C-h>', '<Left>')
...
-- and then set it
vim.keymap.set('i', '<C-h>', '<Left>')
...
So, the use of vim.keymap.set
is preferable for your configuration.
If, the issue resides, let me know.
Try with:
local opts = { noremap = true, silent = true }
vim.keymap.set ("i", "<c-h>", "<left>", opts)
vim.keymap.set ("i", "<c-j>", "<down>", opts)
vim.keymap.set ("i", "<c-k>", "<up>", opts)
vim.keymap.set ("i", "<c-l>", "<right>", opts)
I'd recommend you to run nvim --clean
and then set each keymap manually in command mode, because they might be conflicting with plugin keymaps, for example:
:lua vim.keymap.set ("i", "<c-l>", "<right>", { noremap = true, silent = true })
or write all the keymaps in a lua file and source.