43

I want to teach myself to prefer hjkl more over the arrow keys in order to stay on the home row. (I am very aware that one should not use hjkl as the main navigation keys as there are more powerful movement commands available yet this is more about breaking my habits in regards to the arrow keys.)

In order to break that habit: How can I disable the arrow keys so that I am forced to use the hjkl or some other navigation method?

As a bonus, it would be helpful if there was a message shown Dont't use this! yet that it's not mandatory. If they don't work, it will be confusing enough for me to rethink my habits.

10
  • 6
    There's absolutely no point doing that; HJKL suck just as much as the arrows.
    – romainl
    Commented Dec 17, 2015 at 7:00
  • 11
    I think @romainl may be pointing out that it's more important to focus on using vim's powerful motions (like w for next word, } for next paragraph, n for next search result match, fz for next occurrence of z in the current line, etc.) than moving more granularly by single characters. I definitely agree with this. However, HJKL are definitely better than the arrow keys in that you don't have to move your hands from the home row. I'll frequently type something like jA, which is a lot faster than <Down>A, and not really beatable by any motion.
    – wchargin
    Commented Dec 17, 2015 at 7:45
  • 7
    @romainl: I think I had this discussion with you before. Non-vimmers are used to arrows, and not used to HJKL. Ideally you don't want to use either; but blocking arrows (and not HJKL) will make people pause and reflect on what they are doing (while still leaving HJKL open as an alternative in case it is actually the best option, or in case the user is stumped on how to do it with more powerful motions.). I.e. it is not about learning HJKL, it is about blocking the automatism learned in other editors.
    – Amadan
    Commented Dec 17, 2015 at 8:19
  • 1
    @Carpetsmoker What is definitely an upside of the hjkl keys is not having to leave the home row. For the arrow keys the hand has to move across the keyboard.
    – k0pernikus
    Commented Dec 17, 2015 at 13:12
  • 1
    @Carpetsmoker It's surely feels better to me. ;)
    – k0pernikus
    Commented Dec 17, 2015 at 13:25

8 Answers 8

32

You can install the hardmode plugin and in your .vimrc put in

let g:HardMode_level = 'wannabe'
let g:HardMode_hardmodeMsg = 'Don''t use this!'
autocmd VimEnter,BufNewFile,BufReadPost * silent! call HardMode()

If you don't want to use a plugin (which may be a better choice, as you get to customise everything yourself!), use nnoremap, vnoremap and inoremap on <Left>, <Right>, <Up>, <Down>, <PageUp> and <PageDown>, for example:

nnoremap <Left> :echo "No left for you!"<CR>
vnoremap <Left> :<C-u>echo "No left for you!"<CR>
inoremap <Left> <C-o>:echo "No left for you!"<CR>
1
  • 3
    There's also <nop> if you want to disable the keymap altogether: nnoremap h <nop>.
    – akshay
    Commented Dec 17, 2015 at 8:09
51

In case you, or someone else reading this topic, just wants to disable the key movements without the text warning enter the following lines in .vimrc

noremap <Up> <Nop>
noremap <Down> <Nop>
noremap <Left> <Nop>
noremap <Right> <Nop>

The commands will disable the key movement in normal, visual, select, and operator-pending modes. If you use inoremap the arrow movement will be removed from only insert mode; nnoremap will remove them from only normal mode, etc. See :help :map-modes.

This massively popular topic deals with the differences between noremap, nnoremap, inoremap etc: Remapping in Vim

The general idea with remapping goes like this:

Choice-of-mode-to-remap <remap this command> <to this action/command instead>

So in the other examples given you remap your left command to a text prompt which incidentally removes the action of actually moving the cursor. The example I gave above simply remaps the actions do to nothing, rather than something else. Consider it removing, rather than replacing, vim functionality.

1
  • i wasn't trying to disable arrows, but that above effectively disabled the command i was trying to thanks.
    – user8919
    Commented Apr 22, 2023 at 20:14
8

You could add this to your .vimrc to disable the arrow keys in Command, Insert, Normal and Visual Mode:

" Remove newbie crutches in Command Mode
cnoremap <Down> <Nop>
cnoremap <Left> <Nop>
cnoremap <Right> <Nop>
cnoremap <Up> <Nop>

" Remove newbie crutches in Insert Mode
inoremap <Down> <Nop>
inoremap <Left> <Nop>
inoremap <Right> <Nop>
inoremap <Up> <Nop>

" Remove newbie crutches in Normal Mode
nnoremap <Down> <Nop>
nnoremap <Left> <Nop>
nnoremap <Right> <Nop>
nnoremap <Up> <Nop>

" Remove newbie crutches in Visual Mode
vnoremap <Down> <Nop>
vnoremap <Left> <Nop>
vnoremap <Right> <Nop>
vnoremap <Up> <Nop>

Note: Checkout :help map-overview for more details on the different types of mapping

4
  • 2
    You can reduce the number of necessary commands by using noremap ... ... (for normal, visual, select and operator-pending mode) and noremap! ... ... (for insert and command-line mode). Commented Jul 10, 2019 at 6:30
  • 1
    True. I thought the more explicit noremaps would be helpful for someone wanting to customize what modes are affected Commented Jul 10, 2019 at 12:25
  • I removed command mode maps and still unable to use arrows in :
    – IC_
    Commented Apr 18, 2020 at 3:00
  • @Herrgott noremap! and lnoremap also affect command mode (if you have those). After changing your vimrc, make sure to restart vim (so that the changes load). Commented Apr 18, 2020 at 17:11
7

This is how I do it, I call it hard_ass.vim

for key in ['<Up>', '<Down>', '<Left>', '<Right>']
  exec 'noremap' key '<Nop>'
  exec 'inoremap' key '<Nop>'
  exec 'cnoremap' key '<Nop>'
endfor

It took me a few days to get used to this, however, after that I forgot it's even there.

2

For those trying to do this in their Lua configurations:

-- Shorten function name
local keymap = vim.api.nvim_set_keymap

local opts = { noremap = true, silent = true }
keymap('n', '<Up>', '<Nop>', opts)
keymap('n', '<Down>', '<Nop>', opts)
keymap('n', '<Left>', '<Nop>', opts)
keymap('n', '<Right>', '<Nop>', opts)
1
  • 1
    Welcome to Vi and Vim! Note that this only covers normal-mode arrow keys. You may want to include insert and other modes.
    – D. Ben Knoble
    Commented Aug 15, 2022 at 13:28
1

I really like all the solutions above, but I found myself using "Control" and "Shift" keys with the arrows. Therefore, I decided to extend the solution, as follows:

for mode in ['n', 'v', 'i', 'c']
  for key1 in ['<', '<c-', '<s-']
    for key2 in ['up>', 'down>', 'left>', 'right>']
      exec mode.'noremap' key1.key2 '<nop>'
    endfor
  endfor
endfor
1
1

An alternative to disabling them is remapping them to something useful and non-destructive, yet irritating if you didn't mean to do it. For example:

" Disable arrow movement; resize splits instead.
nnoremap <Up> :resize +2<CR>
nnoremap <Down> :resize -2<CR>
nnoremap <Left> :vertical resize +2<CR>
nnoremap <Right> :vertical resize -2<CR>

I almost never use splits, and when I do use them I almost never resize them. Therefore, I'll be hanged if I can remember the keystrokes to do it. These mappings mean I don't have to, and I issue my own internal warning bell if I hit the arrows in normal mode.

(I can't remember the last time I reached for the arrow keys in any other mode, so I don't remap them.)

1

Here's how you can disable arrow keys in Vim (or NeoVim) using a Lua config. Unlike the other answer here, this covers all modes.

for _, mode in pairs({ 'n', 'i', 'v', 'x' }) do
    for _, key in pairs({ '<Up>', '<Down>', '<Left>', '<Right>' }) do
        vim.keymap.set(mode, key, '<nop>')
    end
end

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.