Pull to refresh

Vim в Windows и переключение раскладки клавиатуры

VIM *
UPD: Это «историческая» версия топика. Новое решение проблемы смотреть здесь.

Проблема русской раскладки в Vim поднималась много раз. Одно из решений можно увидеть здесь, однако оно заставляет привыкать к новой горячей клавише для переключения раскладки. Также существует множество решений с вызовом системной утилиты для смены раскладки, но под Windows подобной утилиты не нашел, так что пришлось реализовать её самостоятельно.

По сути получился консольный интерфейс для WinAPI-функций. Для установки новой раскладки для окна программа получает имя класса данного окна и двухбуквенный код языка. Если есть такое окно и найден соответствующий языковой код, то программа посылает сообщение WM_INPUTLANGCHANGEREQUEST данному окну.

Для создания связи программы с Vim'ом опирался на запись из блога Тех-Детали. Чтобы переключение работало в Windows нужно в _vimrc добавить следующие строки:

fun! <SID>xkb_switch(mode)
    let cur_layout = system('dxlsw.exe -get VIM')
    if a:mode == 0
        if cur_layout != 'en'
            call system('dxlsw.exe -set VIM en')
        endif
        let b:xkb_layout = cur_layout
    elseif a:mode == 1
        if exists('b:xkb_layout') && b:xkb_layout != cur_layout
            call system('dxlsw.exe -set VIM '.b:xkb_layout)
        endif
    endif
endfun

if executable('dxlsw.exe')
    autocmd InsertEnter * call <SID>xkb_switch(1)
    autocmd InsertLeave * call <SID>xkb_switch(0)
endif


Также не забудьте положить dxlsw.exe (3.5 KB) куда-нибудь в %PATH, например, в C:\Windows\System32. Если кому-нибудь нужно, то есть и 64х-битная версия (5 KB). Исходный код (6.8 KB) доступен под лицензией LGPL2.

Преимущества: работает, переключает раскладку только в окне Vim'a.
Недостатки: при вызове функции system из GVim на краткий промежуток времени открывается окно cmd.exe и окно GVim'a ненадолго теряет фокус.

UPD:
По совету хабраюзера ivnik собрал DLL-версию переключателя языка. Окно cmd не появляется, тормозов нет.

_vimrc изменился до:
fun! <SID>lib_kb_switch(mode)
    let cur_layout = libcallnr('libdxlsw', 'dxGetLayout', 0)
    if a:mode == 0
        if cur_layout != 1033
            call libcallnr('libdxlsw', 'dxSetLayout', 1033)
        endif
        let b:lib_kb_layout = cur_layout
    elseif a:mode == 1
        if exists('b:lib_kb_layout') && b:lib_kb_layout != cur_layout
            call libcallnr('libdxlsw', 'dxSetLayout', b:lib_kb_layout)
        endif
    endif
endfun

autocmd InsertEnter * call <SID>lib_kb_switch(1)
autocmd InsertLeave * call <SID>lib_kb_switch(0)


DLL-файл класть в директорию с ЕХЕ-файлом Gvim'a. Если сборка Vim'a 64х-битная, то использовать соответствующую библиотеку.
Tags:
Hubs:
Total votes 11: ↑7 and ↓4 +3
Views 8.8K
Comments Comments 9