Switching keyboard layouts in insert mode


So, maybe you know that I’m Russian or maybe not, but I know that on this forum we got several posts about using Kakoune with non qwerty layouts: [1] [2], as well as some discussions on Kakoune’s GitHub issue tracker: [3]. Since for me it’s not a big deal, as I don’t really need non qwerty layout, I don’t notice the problem too much.

But sometimes I want to write Russian text in Insert mode, and still be able to use Kakoune commands in normal mode. I could use system-wide layout change, but this will cause a problem: when I go back to normal mode nothing is working until I change layout back to qwerty.

The feature to change layout within the editor for insert mode only is presented in Vim with set keymap=russian-jcukenwin and in Emacs with (setq default-input-method 'russian-computer), and I wanted to add something like this to Kakoune too.

Here’s what I got:

declare-option -hidden str langmap "us"
define-command -docstring "toggle-layout: toggle between keyboard layouts in insert mode only" \
toggle-layout %{ evaluate-commands %sh{
    perl -Mutf8 -CS -e 'use strict;
        use utf8;
        my $us_qwerty = q{`~@#$^&|qQwWeErRtTyYuUiIoOpP[{]}aAsSdDfFgGhHjJkKlL;:''"zZxXcCvVbBnNmM,<.>/?};
        my $ru_jcuken = q{ёЁ"№;:?/йЙцЦуУкКеЕнНгГшШщЩзЗхХъЪфФыЫвВаАпПрРоОлЛдДжЖэЭяЯчЧсСмМиИтТьЬбБюЮ.,};
        my $map;

        if ($ENV{kak_opt_langmap} eq "us") {
            $map = "map";
            print "set-option global langmap ru\n";
        } else {
            $map = "unmap";
            print "set-option global langmap us\n";

        for my $key (split //, $us_qwerty) {
            $_ = $key;
            eval sprintf "tr/%s/%s/", map quotemeta, $us_qwerty, $ru_jcuken;
            print "$map global insert -- %🦀$key🦀 %🦀$_🦀\n";

Basically it remaps all the keys for insert mode to insert ЙЦУКЕН characters instead of QWERTY ones. It uses Perl tr command to translate layouts. Basically this script generates such output:

set-option global layout ru
map global insert -- %🦀`🦀 %🦀ё🦀
map global insert -- %🦀~🦀 %🦀Ё🦀
map global insert -- %🦀@🦀 %🦀"🦀

I’ve mapped this command to Ctrl+\, as it is standard Emacs mapping, but Vim users may want to map it to Ctrl+^.

map global normal '' ': toggle-layout<ret>'
map global insert '' '<a-;>: toggle-layout<ret>'

I’m thinking about externalizing this to a plugin, so people could add their layouts, but I hope that Kakoune will provide such functionality OOTB, like Vim and Emacs.


Also available in a plugin format now: langmap.kak


You may create an utility to generate the language mappings on demand, so you don’t have to store the mappings in the plug-in itself.

xmodmap -pke

I’ve thought about it, but it’s not truly cross platform. Won’t work on Mac, not sure if it will work in Cygwin, or BSD. By storing those inside plugin I at least can ensure that there are layouts that are supported directly. Also I’ts just a remapping, therefore you still use your qwerty layout, and this means that for some languages some keys will not work as they do work with real keyboard layout that xmodmap returns.