| Wort | Übersetzung | |--------------|-------------| | der Mond | луна | | humpeln | хромать | | stark | сильный | | die Bewegung | движение | | bewegen | двигать |Представьте, сколько нужно переключений раскладки, чтобы заполнить хотя бы десять рядов, это притом, что всегда присутствует английская раскладка, которую придется каждый раз старательно пропускать. В этой статье я покажу, как сделать, чтобы раскладка клавиатуры переключалась сама, в зависимости от положения курсора в первой или второй колонке таблицы. Разумеется, это всего лишь частный пример, и предложенный алгоритм можно использовать и в иных целях, когда синтаксический формат редактируемого файла заранее известен.
Определять положение курсора будем по синтаксическому идентификатору под курсором. Соответственно, нам понадобится определить синтаксис для словарной таблицы и написать синтаксический скрипт для этого синтаксиса. Я не стал определять собственный тип файла (filetype) для словаря, а просто решил, что его типом будет vimwiki. Vimwiki очень хорошо работает с таблицами, в частности имеет отличную поддержку для навигации внутри таблицы при нажатии на клавишу табуляции, автоматического добавления строк и форматирования столбцов. Однако vimwiki не дает того, что нам нужно: синтаксического различения первого и второго столбцов, а это значит, что мы не сможем детектировать положение курсора в таблице словаря и, в виде бонуса, не сможем подсвечивать столбцы разными цветами. Что же делать? Будем рассматривать наш словарь, как синтаксическую разновидность vimwiki. Это значит, что filetype словаря будет равен vimwiki, а синтаксические особенности мы опишем в файле $HOME/.vim/after/syntax/vimwiki.vim. Для формального различения словаря и других файлов vimwiki положим, что словарь будет иметь файловое расширение .mdict. Поэтому в .vimrc добавляем строку
autocmd BufNewFile,BufRead *.mdict setlocal filetype=vimwiki | EnableXkbSwitch(она также присутствует ниже в листинге для .vimrc). Файл $HOME/.vim/after/syntax/vimwiki.vim выглядит так:
if match(bufname('%'), '\.mdict$') == -1 finish endif syntax match mdictOriginal '\%(^\s*|\)\@<=[^|]\+\ze|[^-]' \ containedin=VimwikiTableRow contained syntax match mdictTranslated '\%([^-]|\)\@<=[^|]\+\ze|$' \ containedin=VimwikiTableRow contained hi mdictOriginalHl term=standout ctermfg=63 guifg='#d7d7ff' autocmd ColorScheme * hi mdictOriginalHl term=standout \ ctermfg=63 guifg='#d7d7ff' hi mdictTranslatedHl term=standout ctermfg=28 guifg='#d7ffd7' autocmd ColorScheme * hi mdictTranslatedHl term=standout \ ctermfg=28 guifg='#d7ffd7' hi link mdictOriginal mdictOriginalHl hi link mdictTranslated mdictTranslatedHlСодержимому первого столбца таблицы соответствует регулярное выражение mdictOriginal, второго столбца - mdictTranslated. В первых строках проверяется, что файл имеет расширение .mdict, и если это не так, то скрипт сразу заканчивает работу.
А теперь код, который следует поместить в .vimrc сразу за кодом для xkb_switch (см. здесь).
" automatic keyboard layout switching in a simple dictionary in insert mode " (filetype is a subclass of vimwiki and must have extension '.mdict'; " there must exist syntax support in dedicated script " $HOME/.vim/after/syntax/vimwiki.vim to define matches for original and " translated colums 'mdictOriginal' and 'mdictTranslated') " FIXME: currently layout will not switch correctly from within select modes fun! <SID>dict_check_lang(force) if !executable(g:XkbSwitchLib) return endif let cur_synid = synIDattr(synID(line("."), col("."), 1), "name") if !exists('b:saved_cur_synid') let b:saved_cur_synid = cur_synid endif if cur_synid != b:saved_cur_synid || a:force let cur_layout = libcall(g:XkbSwitchLib, 'Xkb_Switch_getXkbLayout', \ '') if b:saved_cur_synid == 'mdictOriginal' let b:xkb_layout_dict_orig = cur_layout endif if b:saved_cur_synid == 'mdictTranslated' let b:xkb_layout_dict_trans = cur_layout endif if cur_synid == 'mdictOriginal' if exists('b:xkb_layout_dict_orig') call libcall(g:XkbSwitchLib, 'Xkb_Switch_setXkbLayout', \ b:xkb_layout_dict_orig) else let b:xkb_layout_dict_orig = cur_layout endif endif if cur_synid == 'mdictTranslated' if exists('b:xkb_layout_dict_trans') call libcall(g:XkbSwitchLib, 'Xkb_Switch_setXkbLayout', \ b:xkb_layout_dict_trans) else let b:xkb_layout_dict_trans = cur_layout endif endif let b:saved_cur_synid = cur_synid endif endfun autocmd BufNewFile,BufRead *.mdict setlocal filetype=vimwiki | EnableXkbSwitch autocmd BufNewFile *.mdict VimwikiTable 2 2 autocmd BufNewFile *.mdict exe "normal dd" | startinsert autocmd InsertEnter *.mdict call <SID>dict_check_lang(1) autocmd CursorMovedI *.mdict call <SID>dict_check_lang(0)Теперь при открытии нового файла с расширением .mdict будет автоматически создаваться таблица размерностью 2x2. В верхней сроке нужно поместить названия столбцов. При заполнении первой строки таблицы необходимо вручную переключать требуемые раскладки клавиатуры, в дальнейшем они будут переключаться автоматически. При выходе из режима ввода будет автоматически включена английская раскладка (так как мы включили EnableXkbSwitch), при входе в режим ввода будет включена раскладка в соответствии со столбцом, в котором находится курсор. При открытии уже существующего файла словаря vim не знает о соответствии столбцов и раскладок, поэтому его придется научить снова, дважды вручную переключив раскладку в разных столбцах.
Из недостатков/недоделок нужно упомянуть неправильную работу при переключении в режим ввода из режима выделения текста (Select mode), а также отсутствие немецких дубликатов маппингов режима ввода - их можно добавить по аналогии с русскими (см. здесь) - однако, поскольку немецкая раскладка мало отличается от английской, они, скорее всего, не понадобятся вообще.