2

I use Vim with two keyboard layouts, English and Russian, and to be able to use Vim commands irrespective to the current layout, I have the following snippet in my .vimrc:

" To switch between keyboard layouts, use Control+^ or Control+Space
if     g:os ==# 'Darwin'
  set keymap=russian-jcukenmac
elseif g:os ==# 'Linux' || g:os ==# 'Windows'
  set keymap=russian-jcukenwin
endif
set iminsert=0 imsearch=-1
nnoremap <silent> <C-Space> a<C-^><Esc>
vnoremap <silent> <C-Space> <Esc>a<C-^><Esc>gv
inoremap <silent> <C-Space> <C-^>X<Esc>a<C-H>
cnoremap <silent> <C-Space> <C-^>

I want to improve it by adding an indicator in the status line, so that the status line will look as follows:

file.md                  utf-8 unix markdown [en]
file.md                  utf-8 unix markdown [ru]

How is it possible? (The question is about adding [en] and [ru] flags only.)

2 Answers 2

3
+150

The relevant part of status line should be

set statusline+=%{printf('\ [%s]\ ',&iminsert?'ru':'en')}

However, note that it may show "ru" indicator even while in Normal mode (and so using "en" layout). To deal with it (and also with arbitrary keymap) you can do something along this line

set statusline+=%(\ %{repeat(printf('[%s]',!&iminsert?'en':get(b:,'keymap_name','en')),mode()==#'i')}\ %)
2
  • Thanks a lot, this works fine. But why you think this is not a good idea to have the language indicator while being in Normal mode? For example, I have an English text with some sentences in Russian, and I want to jump to the first "ы" character on the current line by using the f command. The Cyrillic "ы" and Latin "s" are on the key on my keyboard, and so to jump to the first "ы", I need to type fs. This works fine, but unless I have a language indicator in Vim status line, I cannot be sure Vim will jump to the first "ы" and not to the first "s".
    – user90726
    Sep 7, 2022 at 3:02
  • @user90726 Just a matter of personal preference. You can do as you like.
    – Matt
    Sep 7, 2022 at 11:12
3

Use the %{ evaluation block for that:

:let &statusline .= '[%{&keymap =~# "russian" ? "ru" : "en"}]'
6
  • I have created a one-line function from this and changed the first mapping to nnoremap <silent> <C-Space> a<C-^><Esc>:call Foo()<CR>. But when I press Ctrl+Space in Normal mode, the flag is always [ru] and never [en]. What I'm doing wrong?
    – user90726
    Sep 2, 2022 at 10:54
  • @user90726 I would expect this statement to just be in your vimrc. Then when the keymap is switched (and possibly after a redraw via :redraw, C-L, or :redrawstatusline[!]) the statusline should update.
    – D. Ben Knoble
    Sep 2, 2022 at 13:43
  • No, it is still Russian, and it seems the current version of the answer miss the point. As far as I understand, your code set the flag to 'ru' if the string begins with 'russian' and set the flag to 'en' otherwise. But note that set keymap in my original snippet is not something that is turned on or off when I switch the keyboard layout by pressing Ctrl-Space. It is set only once, depending on the operating system, and so it is no surprise that the code in the answer always returns 'ru'.
    – user90726
    Sep 2, 2022 at 23:00
  • Ah, possibly @user90726 I need to double check how the keymap bit works. The idea is sound as long as you have a way to detect what’s currently active.
    – D. Ben Knoble
    Sep 3, 2022 at 0:32
  • 2
    @user90726 This answer should work if you replace &keymap =~# "russian" with &iminsert, I think.
    – Rich
    Sep 6, 2022 at 8:48

Your Answer

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

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