Karabiner-Elements 之 介绍和使用(part 1)

什么是 Karabiner-Elements ?

Karabiner-Elements (下面我们简称为 Karabiner)官网对自己的描述是 “A powerful and stable keyboard customizer for macOS.”,我使用下来的感受是 Karabiner-Elements 是 macOS 平台上一款非常强大的键位映射工具,没有吹嘘的成分,买家秀和卖家秀是一样的。

这个介绍我会分为两个部分:

  • part1 介绍 Karabiner 的核心功能,以及我自己使用 Karabiner 帮助我高效使用键盘的一个思路,不涉及具体的配置
  • part2 根据实例详细介绍使用 Karabiner 高级映射的配置和高级用法,满足一些高级自定义的需求

下面我尽量使用通俗易懂的语言来表达,简单来划分 Karabiner 核心功能的话,Karabiner 可以分为 简单修改Simple modifications) 和 复杂修改Complex modifications),我更倾向于称之为 简单映射高级映射

简单映射

简单映射 其实就是 一对一 的键位映射关系,比如很多因为 Caps lock 键的位置非常好,但是又不经常用,所以喜欢把 Caps lock 映射到 Control 上,当按下 Caps lock 键的时候,实际触发的是 Control 键,非常方便。(这也是 HHKB 默认把 Left Control 放到 Caps lock 位置的一个原因吧)

这么简单的修改,肯定很多朋友会说,那我在 macOS 系统的 Preferences 里也可以修改啊:
Screen Shot 2021-04-07 at 10.55.27 PM

Karabiner 的简单映射能做的远不止这些,除了支持 Control/Cmd/Shift/Option 等这些修饰键,还有以下 macOS 系统不支持的功能:

  1. 支持所有的按键的映射,可以精确区分左右侧的功能键,比如 left control/ right control 可以映射到不同的键位上,支持所有字母、数字、f1-fn、媒体键、方向键
  2. 甚至支持鼠标按键以及各类侧键 (button4,button5) 的映射
  3. 支持根据不同的硬件设备(Target device)进行不同的映射,比如我的 HHKBKeyChron K6,或者 MBP 自带键盘都可以根据实际需要,使用不同的映射策略

Screen Shot 2021-04-07 at 10.44.00 PM

高级映射

简单映射是一对一的映射,那么高级映射,泛指可以支持一对多的映射,外加条件映射的高级复杂映射。我们还是拿个简单的例子,很多朋友喜欢把 Caps lock 键映射为 Hyper 键,Hyper 一般是采用 Control+Cmd+Option+Shift 四个键的组合。这样,当我按 Hyper + C 的时候,相当于按下了 Control+Cmd+Option+Shift + C,使用 Hyper 键的好处是,很难和其他的内置的 hotkey 冲突,因为基本上不会有 app 内置这么复杂的 hotkey。

PS: 我的 Hyper key 是实用 fn 键实现的,相比 Control+Cmd+Option+Shift 有诸多的好处,后面会详细解释。

另外复杂映射,不像简单映射在 UI 简单选择一下即可使用,而是需要编辑一个 json 配置文件,它有自己的配置格式,按照文档约定的属性进行配置即可。

因为本文主要是想跟大家分享一些思路,这里不会太涉及到配置文件的设置。大家看完之后,可以参考我的配置文件或者网上分享的配置文件,也可以去官网查看详细的文档。

再比如,习惯了在 Vim 中使用 hjkl 的朋友,想在其他非 Vim 环境下也使用类似功能的话,也可以使用 Karabiner 间接的实现,需要下面几步:

  1. Caps lock 键映射到 hyper 键上
  2. hyper+h 映射到 left_arrow 左方向键上
  3. 同理,把 hyper+j/k/l 分别映射到 下 / 上 / 右 方向键上

这样,当我们按下 Caps lock + h/j/k/l 时候,就相当于按下方向键了。

再举个例子,比如不同的编辑器或 app 下(比如 VSCode 和 Xcode)的 跳转到上一处修改 / 下一处的修改 是不一样的,如果希望这些体验是一致的,我们可以针对不同的 app 进行单独配置。

App / 前进后退键 前进 后退
Xcode Control + Cmd + -> Control + Cmd + <-
VSCode/Chrome Cmd + ] Cmd + [

当然还有一些其他的 IDE 或者 app 也有类似的功能,我们想把他们的体验统一起来,那么我们可以这么做:

  1. 针对 Xcode app,把 Hyper + ] 映射为 Control + Cmd + ->,把 Hyper + ] 映射为 Control + Cmd + <-
  2. 针对 VSCode/Chrome,我们把 Hyper + ] 映射为 Cmd + ],把 Hyper + ] 映射为 Cmd + [

我使用 Karabiner 解决了我的哪些困扰?

  1. Caps lock 键映射到 Hyper 键,要注意的是
    1. 为保持操作统一,HHKB 下需要把 Left Control 映射到 Hyper 键,Karabiner 支持根据不同设备,映射到不同按键上
    2. 我们需要个 Hyper 键的原因是,我们在自定义一些键位的时候,使用 Hyper 键进行修饰,不容易和系统以及 app 内置的热键冲突,这个是基础。
  2. 常用的 VIM 导航键的设置,包括:
    1. hyper + h/j/k/l 方向导航键,每次前后移动一个字符,上下移动一行
    2. hyper + y/p 向后 / 前移动一个 word,这里和 Vim 的体验并不同,只是我个人的习惯
    3. hyper + d/u 向下 / 上 移动 15 行(具体行数可以自定义)
    4. hyper + o 在下面插入一个空行
  3. 替代 Control 的一些组合键,如果我是用的 HHKB 的话,相当于把 Control 键映射到了 Hyper 键,那么之前经常使用的一些组合键,比如 Control+a/e 跳转到行首 / 行尾等就很难按出来了,所以我这里我给常用的一些 Control 作为修饰键的组合键提供了一些映射:
    1. Hyper + a/e => Control + a/e
    2. Hyper + c/b/r => Control + c/b/r (中止命令执行,tmux,iterm2 搜索)
  4. 一些方便的操作
    1. Hyper + i => delete,主要原因是我有几个不同的键盘,HHKB 和 Keychron K6 的 delete 键位置不太一样,导致我很容易按错。所以我就想着把他们统一到一个位置上,选择 i 键的原因是它在右手食指上方,很容易按。为了习惯它,我一度把 delete 键本身给映射到一个空键上,强迫自己习惯使用 hyper+i 键做删除。
    2. Hyper + w 删除当前光标所在位置的单词 / 词组,类似 Vim 里的 diw(delete in word),不管光标位置在当前单词 / 词组的哪个位置,都可以直接删掉整个单词,很多时候还是挺好用的。
  5. 输入法切换,MBP 内置键盘上 Caps Lock 键可以切换输入法,映射到 Hyper 之后就没有一个比较舒服的切换输入法的按键了。另外一个切换的时候,我还需要清楚当前是什么输入法,将要切换到什么输入法。有没有办法可以直接切换到某一个输入法呢?Karabiner 考虑到了这个问题(可能是 Karabiner 的作者是个日本人,也有在英文和本土语言输入法之间切换的烦恼),我是这么映射的:
    1. Hyper + < 切换到英文输入法
    2. Hyper + > 切换到中文输入法
      这样的话,我就不需要记录当前是什么输入法,我只需要关心我接下来希望使用什么舒服法就行了。不过这两个按键,我现在还没形成肌肉记忆
  6. 使用连续按键,打开常用的 app,比如:
    1. o,x 打开 / 唤起 Xcode
    2. o,g 打开 / 唤起 Google Chrome
    3. o,i 打开 / 唤起 iTerm2
    4. o,t 打开 / 唤起 Tower
    5. 等等。。
      所谓连续按键,比如 o,a 就是按完 o 之后马上按 a,就可以触发打开 Xcode 的命令

以上问题的思路,都会考虑到可能会使用到多个不同的键盘的 case,并保证体验是一致的,不会出现换个键盘,还需要重新熟悉键位的尴尬情况。

为什么我选择使用 fn 键作为 Hyper 键,而不是 Control+Command+Option+Shift?

在这之前,我们先聊一下什么是修饰键(modifier keys),所谓修饰键就是可以和其他按键一起按,达到一个组合键的目的。macOS 上,精确地说,有以下这些修饰键:

  • left_command, right_command
  • left_control, right_control
  • left_option, right_option
  • left_shift, right_shift
  • caps_lock
  • fn

比如,我可以按 left_command+c 进行复制,但是不能定义 6+c 来执行一个操作,因为 6 和 c 都是非修饰键,起不到同时按到达组和键的目的。

接着我们要明确我们需要 Hyper 键的目的,它主要是作为我们常用自定义按键的通用修饰键,而且这个键需要不经常使用,从而不会和内置的系统热键,或者一些 app 的内置热键冲突。所以 hyper 键只能是这里面的其中某一个,或者他们的组合。

Control+Command+Option+Shift 是一个很好的 Hyper 的候选,我搜索了一下,非常多的朋友在使用。不过他有个问题是,它直接用尽了 Control+Command+Option+Shift 四个修饰键,没有再使用这四个按键的某一个作为增补修饰键的可能。举个例子,我上面定义了 hyper+h 映射到 左方向键,那么如果我想往左边选择的时候,会下意识地会再加一个 Shift 键,但是发现没有起作用,因为 Hyper 里已经使用了 Shift,再次按下 Shift 并不会执行选择的操作。

遇到这个问题之后,我就继续找其他替代方案。开始尝试使用 fn 键作为 hyper 键,发现它还蛮好用,因为很多键盘上都没有 fn 这个键,所以它不会经常会被内置为默认热键里的修饰键,而且它还可以继续和 Shift/Option 等修饰键进行组合。

比如上面我定义的 hyper+h 映射到 左方向键,那么就有:

  • hyper+shift+h == shift+left 向左选中
  • hyper+option+h == option+left 向左跳过一个 word
  • hyper+cmd+h == cmd+ left 跳到行首

非常完美😄

另外 fn 一个优点是,它基本没有副作用,就是随便组合也不会有什么问题,比如,如果我们没定义 fn+t,按下之后就等于直接按了 t 键。但使用 Control+Command+Option+Shift 作为 hyper 键的时候,还是需要留意一下,需要把 Control+Command+Option+Shift+ , 或者 . 映射到空 key 上,不执行任何操作。因为这两个是系统内置的 hot key,用来启动系统诊断,而且这个执行的时间会长达数分钟,如果不小心按到,电脑可能会卡一会。

The command-line utility sysdiagnose can be triggered by pressing Cmd+Opt+Ctrl+Shift+Period, and it may take a few minutes to complete. When ready, the output will automatically be revealed in a Finder window (or it can be manually retrieved from /var/tmp).

OK,part 1 的部分就到这里了,如果正好你也有类似的困扰,那真心希望 Karabiner 可以帮助到你。如果你有一些好玩的想法,也可以跟我分享。

Have fun!