Emacs 里使用 pyim 输入中文还是挺方便的,尤其是可以根据不同状态自动切换输入法,非常方便。但平常工作中经常遇到需要中英文混合输入的情况,这时就只能不断的按 Ctrl-\切换,而这个组合键按起来就不是很方便了。如果能像外部输入法那样用 Shift 切换就好了,但是在 Emacs 里是不能把 Shift 键设成快捷键的,所以这个问题就一直放着了。

后来有人提出,可以把 Shift 映射成一个 Fn(比如 F19),再在 Emacs 里绑定切换输入法的快捷键,以此达到可以快捷切换的效果。我想,既然可以把 Shift 映射到 F,那干嘛不干脆把 Shift 映射到 Ctrl-\岂不是更好,还省得多占一个快捷键。

说干就干,达到目标是单独按 Shift 键,系统输出 Ctrl-\快捷键,而 Shift 和其它键一起按时,还是输出 Shift 本身,另外最好这个映射只在 Emacs 里有效,这样就不会影响其它程序,避免出现意想不到的问题。

基于这样的原则,在键盘层面进行编程映射就不合适了,因为它无法区分不同程序。MacOS 里有一款软件堪称神器,这就是 Karabiner-Elements,用它可以实现各种各样的键盘映射,而且完全免费。Karabiner-Elements 的安装使用此处省略,请自行搜索安装,这里只介绍一下如何自定义映射规则。

映射规则理论上可以直接写 json 文件直接使用,比如我自己的 json 文件是:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
  "title": "Change shift key (YH)",
  "rules": [
    {
      "description": "Change left_shift to Ctrl-\\ if pressed alone in Emacs",
      "manipulators": [
        {
          "type": "basic",
          "from": {
            "key_code": "left_shift",
            "modifiers": {
              "optional": ["any"]
            }
          },
          "to": [
            {
              "key_code": "left_shift"
            }
          ],
          "to_if_alone": [
            {
              "key_code": "backslash",
              "modifiers": ["left_control"]
            }
          ],
          "conditions": [
            {
              "type": "frontmost_application_if",
              "bundle_identifiers": ["^org\\.gnu\\.Emacs$"]
            }
          ]
        }
      ]
    }
  ]
}

但我多次尝试直接编写 json 文件都无法成功添加,最后发现是文件换行格式的问题,因此实际的作法是编写 erb 文件,然后用 KE-complex_modifications 进行生成,这样生成的 json 文件格式就完全没问题了。

先从 github 下 clone 下来 KE-complex_modifications 代码:

1
git clone https://github.com/pqrs-org/KE-complex_modifications

然后进入 KE-complex_modifications 目录,并在 src/json 目录下新建一个后缀为.json.erb 的文件,如 yh-shift.json.erb,内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
    "title": "Change shift key (YH)",
    "rules": [
        {
            "description": "Change left_shift to Ctrl-\\ if pressed alone in Emacs",
            "manipulators": [
                {
                    "type": "basic",
                    "from": <%= from("left_shift", [], ["any"]) %>,
                    "to": <%= to([["left_shift"]]) %>,
                    "to_if_alone": [
                        {
                            "key_code": "backslash",
                            "modifiers": [
                              "left_control"
                            ]
                        }
                    ],
                    "conditions": [
                        {
                            "type": "frontmost_application_if",
                            "bundle_identifiers": [
                                "^org\\.gnu\\.Emacs$"
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

然后编辑 docs/groups.json 文件,里面在比照已有代码在任意一个组内增加一段代码,指定 json 文件名称(注意后面没有.erb 后缀,注意前后的逗号分隔):

1
2
3
{
  "path": "json/yh-shift.json"
}

这时执行 make,如果文件没有错误的话,就会在 docs/json/目录下生成 yh-shift.json。把这个文件拷贝到 Karabiner-Elements 的配置目录下:

1
cp docs/json/yh-shift.json ~/.config/karabiner/assets/complex_modifications/

这时就可以在 karabiner-Elements 设置里导入这项规则了。菜单项是:Karabiner-Elements Preferences > Complex Modifications > Rules > Add rule

大功告成。