Auto Change Keyboard Layout in Vim

If you use multiple keyboard layouts then you may know how it's frustrating to constanly switching between them. Remember that feeling when you come to Vim's normal mode with keyboard layout different than English? After some time of hjkl-ing, you find out that it doesn't work as expected. Let's do something with this.

The most straightforward (and also the most rough) workaround is to duplicate your key mappings in different language. langmap can help here. You can explicitly specify all characters that should work in normal mode without layout switching.

For Russian layout it should look like this:

set langmap=ёйцукенгшщзхъфывапролджэячсмитьбюЁЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ;`qwertyuiop[]asdfghjkl\\;'zxcvbnm\\,.~QWERTYUIOP{}ASDFGHJKL:\\"ZXCVBNM<>

More information can be found at :h langmap.

I will not focus on this method, because there is a better way - xkb-switch.


xkb-switch is a C++ program that allows to query and change the XKB layout state.

Usage is simple:

  • xkb-switch -l - show available keyboard layouts
  • xkb-switch -s LAYOUT - change current keyboard layout to LAYOUT

How it can help us? Let's write a simple vim function, that changes layout to us (English).

function! RestoreKeyboardLayout(key)
  call system('xkb-switch -s us')
  execute 'normal! ' . a:key

Now we can map our hjkl (ролд in Russian layout) keys like this:

nnoremap <silent> р :call RestoreKeyboardLayout('h')<CR>
nnoremap <silent> о :call RestoreKeyboardLayout('j')<CR>
nnoremap <silent> л :call RestoreKeyboardLayout('k')<CR>
nnoremap <silent> д :call RestoreKeyboardLayout('l')<CR>

Pressing hjkl in different layout will implicitly switch it to English. Now you can forget about current keyboard layout when entering normal mode.

But how about insert mode?


vim-xkbswitch can be used to easily switch current keyboard layout back and forth when entering and leaving insert mode. It has a good documentation and should work out of the box. The only requirement is xkb-switch.

It also support something like langmap for insert mode. This is example of mappings for Russian layout:

let g:XkbSwitchIMappingsTr = {
      \ 'ru':
      \ {'<': 'qwertyuiop[]asdfghjkl;''zxcvbnm,.`/'.
      \       'QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?~@#$^&|',
      \  '>': 'йцукенгшщзхъфывапролджэячсмитьбюё.'.
      \ }

And that is all about switching keyboard layouts in Vim.