左上角的 Esc 键太远够不着?那就把它改到小拇指旁的 Caps Lock 键上;右下角的 Option 键几乎没用过?把它改成一键切换输入法怎么样;设置快捷键冲突了?还是键位不够分配?索性自己造个万能的 Hyper 键。让我们一起对不顺手的修饰键说,不!

长期使用电脑的朋友想必对电脑的修饰键并不陌生。修饰键是在任何系统下,使用快捷键的重要甚至是必要辅助按键,我们在键盘上通过按组合键来执行通常需要鼠标、触控板或其他输入设备才能完成的操作。

使用键盘快捷键,需要按住一个或多个修饰键,同时按快捷键的最后一个键。Mac 菜单和键盘通常使用某些按键的符号,其中包括以下修饰键:

  • ⌘ Command
  • ⇧ Shift
  • ⌥ Option
  • ⌃ Control
  • ⇪ Caps Lock
  • Fn

如果你使用的是 Windows PC (以下简称 PC)专用键盘,可以使用 Alt 键代替 Option 键,用 Windows 标志键代替 Command 键。有些 Mac 键盘在顶行中设有特殊按键,这些按键上有音量图标、显示屏亮度图标和其他功能图标。按下图标键可执行相应功能,将其与 Fn 键组合可用作 F1、F2、F3 或其他标准功能键。 所以除去 Fn 键外,其余 5 个修饰键在 Mac 专用键盘和 PC 专用键盘上基本可以互换使用。

今天的教程水猫将会带领大家通过系统设定和部分软件,来开发这几个修饰键高级用法,以实现更加高效的操作效率。教程中会使用到的软件有:

  • 系统偏好设置
  • Seil(免费)
  • Karabiner / Karabiner-Element(免费)
  • Hammerspoon(免费)
  • Keyboard Maestro(付费)

其中 Keyboard Maestro 只在最后一节中使用,如无需要可以不用购买。

系统自带的改键功能

首先我们来看看最简单的调整修饰键的默认行为。全部操作都只需在「系统偏好设置」里面完成即可。

「系统偏好设置」中允许调整以下 4 种修饰键的行为:Caps Lock、Control、Option 和 Command。如果你正在使用的键盘不是你所熟悉的键盘布局,此功能非常有用。

例如,UNIX 和 Sun 电脑键盘上的 Control 键位于 Apple 键盘上 Caps Lock 键所在的位置。对于熟练的触打式打字员来说,这将会带来极大的不便。如果将 Caps Lock 键的行为更改为 Control 键的行为,就可以解决此问题。

  1. 选取苹果菜单 -> 「系统偏好设置」,然后点按「键盘」;
    设置1
    设置1
  2. 点按「键盘」,然后点按「修饰键」;
    设置2
    设置2
  3. 点按每个要更改的修饰键的弹出式菜单,然后选取一项操作。
    设置3
    设置3

若要使键返回其原始设置,可以点按「恢复成默认」。

基础改键:换成更实用的功能

上面提到的方法通过系统的设置就可以方便的调整修饰键的默认行为了,但是有一个限制,就是只能在这 4 种修饰键之间互相替换。(注:macOS Sierra 系统中修饰键默认行为变更的弹出式菜单中除了这 4 种修饰键外,还允许选择 Escape)有些时候,我们希望彻底替换掉这些修饰键,使之变成别的功能键,比方说下面的两种场景:

  • 从来不使用 ⇪ Caps Lock 键来切换大写锁,习惯使用 ⇧ Shift 来键入大写字母的人,希望充分利用 ⇪ Caps Lock 的位置优势,可以将其更改为 Escape 键,这样左手小指就不需要大幅度移动到左上角去敲击 esc 了。这一特性在配备 Touch Bar 的最新一代 MacBook Pro 上显得十分重要,这也是为什么 macOS Sierra 新增加了允许变更修饰键为 Escape 的原因。
  • 从来不使用右下角的 ⌥ Option 或者 ⌘ Command 键,希望利用这两个按键实现 F1-F20 功能键,或者单独绑定成某快捷键的。例如我使用单击右侧 ⌥ Option 来呼出下拉式命令行;受 LaunchBar 的启发,单击右侧 ⌘ Command 来呼出当前选中文本的 Instant Send 功能等。

这种情况下,单单使用系统提供的设置已经不能够满足我们的需求了,我们就需要使用 Karabiner 来进行调教。

实际上 Karabiner 是一个非常强大的键盘自定义工具,单单这一个软件就可以做出一个系列的文章出来,找机会我会专门发文介绍,感兴趣的朋友可以在作者的 GitHub 查看到非常详尽的文档,我就不过多地赘述了。今天我们尽可能的简化 Karabiner,仅仅针对修饰键,做一些应用层面上的简单设置就好了。

① 关于 Sierra 系统的申明 ‼️

首先需要说明一点,自 macOS Sierra 之后,由于 macOS 系统的底层的变动,导致在新的系统上,Karabiner 完全失效。Karabiner 的作者 @tekezo 表示,调整 Karabiner 以支持新系统的工作量太过巨大,所以 Karabiner 将不会支持 Sierra 及以上的系统了。取而代之的是,作者启动了全新的 Karabiner-Elements 项目。现在,Karabiner-Elements 正在紧张地开发当中,作者贡献代码的速度可谓非常之高,可是整体进度却还是相当的慢,已成为水猫翘首以盼的「有生之年」系列之一,好在已发布的版本支持基本的更换按键操作,足够我们今天的教程使用。

后文中,当我提到 Karabiner 时,仅适用于 Sierra 之前的操作系统,准确点说,就是 OS X 10.9、10.10 和 10.11。

下面的每个章节我会先介绍一下整个改键的思路和操作,然后先在非 Sierra 系统下利用 Karabiner 等软件进行优雅的配置方案演示,最后对于 Sierra 系统的用户,我再单独讲解利用 Karabiner-Elements 和其他软件配合的方法来进行曲线救国。大家可以根据自己现在使用的操作系统版本进行选择性阅读,我提供了方便的目录链接导航,但是我还是推荐读者按顺序依次阅读,毕竟某些想法我是想到就提一下,不会在两套方案里面都提到。

② 非 Sierra 用户的实现方案

(Sierra 用户请移步第 ③ 小节)

言归正传,大家可以在 Karabiner 官网 下载并安装 Karabiner。

Karabiner 主界面
Karabiner 主界面

Karabiner 的主界面就是一个设置页面,第一个标签页「Change Key」下就包含了全部的预设配置,多达几百种选择,你可以尽情的浏览勾选自己需要的改键配置。当你选中某个配置后,就会被置顶显示在已激活的区域内,这时候改键就已经成功了。说起预设的改键,作者可以说思虑周全,我们以「` 反引号」键来看看:

反引号的丰富设置
反引号的丰富设置

单单这一个键的修改就非常的丰富。

  • Backquote(`) to Hashtag(#) 这个配置非常适合长期使用 Markdown 的用户,经常输入各级标题你就懂了。
  • Backquote(`) to Cmd+Space 选项可以方便使用这一快捷键来切换输入法的用户,或者使用这一快捷键来呼出 Spotlight/Alfred/LaunchBar 的用户

基本上绝大部分的按键更改需求,都可以在这里找到,大家只需要善用上方的搜索功能来过滤就好了。如何发挥创造力配置自己的键盘不是今天主要讲解的内容,我先按下不表。接下来我们来看看如果预设配置不符合需求的话,如何利用 Karabiner 自定义换键规则。我们先切换到「Misc & Uninstall」选项卡:

自定义配置和按键查看器
自定义配置和按键查看器

这里面有两个重要的东西:「Launch EventView」可以打开按键查看器,查看每次按键的实际触发行为;「Open private.xml」可以打开自定义改建设置的配置文档。

我们先看看 EventView

按键查看器
按键查看器

在按键查看器中的每一个按键动作都会被检测到,上图中我分别执行了三个按键操作:「单击左侧 ⌘ Command」、「cmd + A」、「shift + A」,我用蓝色横线把三个操作分隔开了。

  • eventType:包括 KeyDown 按下按键、KeyUp 释放按键、FlagsChanged 修饰键状态变更等;
  • code:当前按键的唯一 16 进制码;
  • name:当前按键的名字;
  • flags:当前按键所拥有的修饰键状态列表;
  • misc:KeyCode::<something> 表示 Karabiner 可以识别的按键标识符

我们使用按键查看器的作用有两个:

  1. 通过观察 name 和 flags 测试我们的改建的实际效果,这在后面会频繁的使用到,大家可以 play with it,蛮好理解的;
  2. 通过 misc 查找某个实际按键的按键标识符,我们会在修改自定义按键设置的时候使用到这个标识符。

好的,假设大家和我一样,想要把右侧的 ⌥ Option 键修改成 F12 键,我们来看看怎么操作:

  1. 首先在 EventView 中查到 ⌥ Option 和 F12 的标识符,分别为 KeyCode::OPTION_RKeyCode::F12
  2. 然后点按「Open private.xml」打开自定义改建设置的配置文档;
  3. 修改配置文档。

Karabiner 的配置文档是 XML 文档,通过树状节点进行配置:

<?xml version="1.0"?>
<root>
    <item>
    ...
    </item>

    <item>
    ...
    </item>

    ...
</root>

在根节点标签 <root></root> 下有一个个的 <item></item> 子节点标签,每个子节点就是一个配置项,我们来看看「把右侧的 ⌥ Option 键修改成 F12 键」的配置具体该怎么写:

<item>
    <name>Right option to F12</name>
    <identifier>private.right_option_to_f12</identifier>    <appendix></appendix>
    <autogen>
        __KeyToKey__
        KeyCode::OPTION_R,
        KeyCode::F12
    </autogen>
</item>
  • <name></name> 标签是配置项的名字,<appendix></appendix> 标签是配置的补充说明,会在 Karabiner 设置的主界面显示,方便你自己区别每一个配置项,你可以随意写;
  • <identifier></identifier> 标签是配置项的内部标识符,是让程序区别每一个不同的配置项的,具有唯一性,所以我命名的时候都会在前面添加 private 以防和预设配置重名撞车;
  • <autogen></autogen> 标签是配置的实际内容。

__KeyToKey__ 表示我们本项设置是简单的改键设置,把 KeyCode::OPTION_R 改为 KeyCode::F12 非常简单,很好理解。

编辑完配置文档后,保存关闭就好了。下面我们回到 Karabiner 的设置主界面,点按右上角的「Reload XML」按钮,就可以把刚才写好的配置载入了。如果配置没有写对的话,在这一步时 Karabiner 会弹出对话框提示。

自定义的配置
自定义的配置

特殊按键 ⇪ Caps Lock

需要注意的是,⇪ Caps Lock 作为一个比较特殊的修饰键,不能直接被 Karabiner 所修改,我们使用 Karabiner 作者提供的小工具 SEIL 可以先把 ⇪ Caps Lock 键修改成别的键位,再在 Karabiner 中操作就行了。(Seil 官网下载地址

Seil 主界面
Seil 主界面

例如此处,我就把 ⇪ Caps Lock 用 Seil 先修改成了 keycode 值为 62 的 Right Control 这个 Mac 内置键盘上并没有的键,然后 Karabiner 中所有对 Right Control 键进行的更改,实际上就是对 ⇪ Caps Lock 键的更改了。

③ Sierra 用户的实现方案

关于 Karabiner 不能在 Sierra 上使用的事情确实很令人沮丧,不过好在本节的内容我们使用 Karabiner-Elements 也能完成。首先 下载最新版的 Karabiner-Elements,和 Karabiner 一样,它也自带了一个「EventView」。

Karabiner-Elements 的主界面简单朴素了许多:

Karabiner-Elements 主界面
Karabiner-Elements 主界面

点按 「Add item」 然后在上面更改「From key」和「To key」就是他的全部功能了。(默哀)

④ 应用实例

有人可能会问我,为什么会把右侧的 ⌥ Option 键修改成 F12 键,其实这样的话我就可以绑定 F12 键为快捷键到我喜欢的应用上了。比方说我是一个程序猿,经常会用到命令行终端,我使用的 iTerm2 支持使用全局热键呼出一个从天而降的半透明命令行终端,我把这个热键绑定在 F12 上,任何情况下我只需要敲一下右侧 ⌥ Option,「DUANG~」,终端就掉下来了。很是方便,很是震撼。

设置 iTerm 的全局热键
设置 iTerm 的全局热键

一键呼出从天而降的命令行
一键呼出从天而降的命令行

当然,你也可以发挥自己的想象力,充分利用上各个修饰键,让它们放光发热!比如,你还可以把切换输入法的快捷键绑定在右侧 Option 上实现一键切换输入法。当然,我知道你们会问,可是这个按键原来的功能怎么办,我不就少了一个修饰键吗?不用担心,后面我会介绍更为进阶的用法,在保留修饰键原功能的情况下,为它们添加更丰富的操作逻辑。

进阶改键:把一个键当两个用

我们键盘上的按键,按照行为属性来看,主要分为以下几类:

  • 正常按键(I 类):按下时,触发一次行为;按住不放,短暂延迟后连续触发行为。键盘上大部分的按键都属于这一类,包括各个字母、标点符号、空格、回车、删除、制表、方向键等;
  • 单次响应按键(II 类):按下时,触发一次行为。这类按键的特性是单独、短按,一般不按住不放。比如 Escape 键、⇪ Caps Lock、Mac 内置键盘上的 Mission Control 键和 Launch Pad 键;
  • 组合修饰键(III 类):按下时只改变修饰状态,必须和第 I 类「正常按键」配合才能触发行为,否则释放后修饰状态退回,无效行为。

我们的键盘空间非常有限,但是需要完成的功能又有太多,增加按键显然是不可能的,我们只能在现有的按键上做文章。仔细思考一下,其实「组合修饰键」相对于「正常按键」、「单次响应按键」,操作逻辑是完全不一样的,我们可以为「组合修饰键」提供另外两种按键的特性,来提高键盘的利用率。也就是短按修饰键和组合使用修饰键实现不同的功能

如果大家使用过搜狗输入法、百度输入法之类的第三方输入法应该知道,可以单击 ⇧ Shift 来切换中英文模式。这就是一个典型的第 III 类按键活用为 I 类按键的例子。

① 非 Sierra 用户的实现方案

(Sierra 用户可以移步至第 ② 小节)

下面我通过一个 Karabiner 的配置实例来讲解如何实现双重修饰键行为

还记得我在文章开头提到过的 Unix 键盘的布局吗?在 Unix 键盘上,⇪ Caps Lock 位置放的是 ⌃ Control,这是基于效率考量的。显而易见,⇪ Caps Lock 的位置就在左手小指旁边,是一个非常好的键位,却放了大写锁这样一个使用频率极低的功能,非常不划算。倒是 ⌃ Control 的功能随时都有可能用到,因为大量的组合键,尤其是 Linux 下和命令行程序中的快捷键都会用到 ⌃ Control 键。所以把这个位置分配给 ⌃ Control 更加合理。

同时,第一节中我也提到过有一个键非常想利用 ⇪ Caps Lock 键的位置,那就是 Escape 键。因此,利用双重修饰键行为结合 ⌃ Control 键和 Escape 键的功能放置在 ⇪ Caps Lock 键位上的想法也就顺理成章了。

我们打开 Karabiner 的自定义配置文档 private.xml:

<!-- use SEIL.app to change CAPSLOCK to CONTROL_R fisrt -->
<item>
    <name>Caps to Control to ESC</name>
    <identifier>private.caps_to_control_to_esc</identifier>
    <appendix>Change Caps to Control(using SEIL.app), when click Caps only, send ESC.</appendix>
    <autogen>
        __KeyOverlaidModifier__
        KeyCode::CONTROL_R,
        KeyCode::CONTROL_R,
        KeyCode::ESCAPE
    </autogen>
</item>

在这个配置中,我们使用了 __KeyOverlaidModifier__ 来声明一个覆盖触发的修饰键。映射 KeyCode::CONTROL_R覆盖触发KeyCode::CONTROL_R 也就是保持不变,否则触发 KeyCode::ESCAPE 键。(注意, 前面说过,我先通过 Seil 把 ⇪ Caps Lock 映射成为 CONTROL_R 这个 Mac 键盘上不存在的按键了,否则 Karabiner 无法直接更改 ⇪ Caps Lock 键。)

下面我们在 EventView 里面看看 ⇪ Caps Lock 的行为:

用按键查看器检视按键行为
用按键查看器检视按键行为

第一部分是单独敲击 ⇪ Caps Lock 键的效果,可以看到 1-2 行修饰状态短暂的变化了一下,随后 3-4 行触发了一次单击 Escape 键的行为。

第二部分是组合敲击 ⇪ Caps Lock + A 键的效果,第 5 行修饰状态变化为 Ctrl,这是按下 ⇪ Caps Lock 的一瞬间的事儿,第 6 行在该修饰状态下,按下了字母 A 键,7-8 行是释放按键。综合来看就是进行了一次 Ctrl-a 的逻辑操作。

同样的道理,你可以把 ⇧ Shift、⌃ Control 等键位都进行相应的设置。

现在问题来了!如果我想使用 ⇪ Caps Lock 本身的大写锁功能怎么办?我的办法是双击左 ⌃ Control 键触发大写锁,我们来看看 Karabiner 的实现:

<item>
    <name>Control x2 to Caps</name>
    <identifier>private.control_x2_to_caps</identifier>
    <appendix>When double click on control, CAPS take effect.</appendix>
    <autogen>
        __DoublePressModifier__
        KeyCode::CONTROL_L,
        KeyCode::CONTROL_L,
        KeyCode::CAPSLOCK
    </autogen>
</item>

这次我们使用 __DoublePressModifier__ 来声明一个双击修饰键触发操作,触发的是 KeyCode::CAPSLOCK 也就是大写锁的功能。

我们在 EventView 中看一下效果:

用按键查看器检视按键行为
用按键查看器检视按键行为

1-4 行可以看出我们快速点击了左侧 ⌃ Control 两次,然后第 5 行触发了一次大写锁。同时,我们还可以观察到,键盘上 ⇪ Caps Lock 按键的指示灯亮了。再次双击左侧 ⌃ Control,灯又熄灭了。实验成功。

举一反三,大家可以为双击 ⌘ Command、⌥ Option、⇧ Shift 等等设置不同的功能,而且,左右两边还可以分开,非常的强大!

② Sierra 用户的实现方案

非常遗憾,Sierra 用户可以使用的 Karabiner-Elements 暂时还无法做到本节所说的任何一个功能。所以,我们不得不配合其他软件来曲线救国。

水猫为了找寻替代的方案,花了不少的心思。最终确立了两个软件 Keyboard Maestro(以下简称 KM)和 Hammerspoon(以下简称 HS)。

先说优缺点:

  • 不同于 Karabiner 直接作用于底层硬件,不管是 KM 还是 HS,对于键位的修改逻辑层面都比较高,利用的是 macOS 的 Carbon API,相当于接管快捷键,所以使用起来没有 Karabiner 那么高的响应速度。不过延迟也很小,基本没有感觉,误触发和不触发的情况十分少见;
  • 认真说起来,HS 还是要比 KM 更加底层一点儿,效率也要高些;
  • HS 功能相对简单,就是是通过脚本定义热键。KM 是键盘大师,而且对得起这个名字,功能包罗万象,改键只是其中的冰山一角,我们是用牛刀来杀鸡。不过换句话来说,如果你在使用着强大的 KM,可以顺带使用一下改键功能,相信 KM 的用户多少都知道怎么弄;
  • HS 涉及到编写 Lua 脚本语言;
  • 最后,HS 是开源免费应用。KM 需要 36 美元购买一个授权 License。

综上,我重点介绍利用 HS 来实现双重修饰键行为

What is Hammerspoon?

This is a tool for powerful automation of OS X. At its core, Hammerspoon is just a bridge between the operating system and a Lua scripting engine. What gives Hammerspoon its power is a set of extensions that expose specific pieces of system functionality, to the user.

You can write Lua code that interacts with OS X APIs for applications, windows, mouse pointers, filesystem objects, audio devices, batteries, screens, low-level keyboard/mouse events, clipboards, location services, wifi, and more.

通过官方的描述可以看出,其实我们主要是使用 Keyboard/mouse event 的交互功能。好了,首先在 Hammerspoon 官网下载 安装 HS。

HS 安装好之后没有任何主界面,只有一个 MenuBar 图标,所有的设置都通过 Lua 脚本来实现的,你可以在 lua.org 学习到更多关于 Lua 语言的知识。今天我主要给大家讲解几个例子就好了。

本节中,我们想要「单击 ⇪ Caps Lock 键触发 Escape 功能,长按时作为 ⌃ Control 修饰键使用」,现在我们看看如何用 HS 实现。

我们需要为 ⇪ Caps Lock 键做一点准备工作。

  • 第一,在系统偏好设置中,把 ⇪ Caps Lock 恢复成默认功能;
  • 第二,在 Karabiner-Elements 里面把 ⇪ Caps Lock 映射成 F18 键。

单击 MenuBar 上的 HS 图标,选择「Open Config」打开配置脚本 init.lua,在脚本文件里面加入如下配置:

-- Bingdings key that can be used are listed bellow
-- Handler can be defined in other applications
-- We just have to send the right key
Bindings = {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 
'z', 'x', 'c', 'v', 'b', 'n', 'm', 
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='}
-- A temporary key F13 to trigger Double Key mode
tmp = hs.hotkey.modal.new({}, 'F13')
-- Temporary key could trigger 'ctrl'
for i,key in ipairs(Bindings) do
  tmp:bind({}, key, nil, function() hs.eventtap.keyStroke({'ctrl'}, key)
    tmp.triggered = true
  end)
end
-- When caps lock pressed(using karabiner to change caps -> F18)
pressedF18 = function()
  tmp.triggered = false
  tmp:enter()
end
-- When caps lock released
releasedF18 = function()
  tmp:exit()
  if not tmp.triggered then
    hs.eventtap.keyStroke({}, 'ESCAPE')
  end
end
-- Binding F18
f18 = hs.hotkey.bind({}, 'F18', pressedF18, releasedF18)

我们来看看,脚本都做了些什么。

  • 首先,我们定义了一个列表 Bindings 用来识别组合键,这个列表其实就是整个主键盘区域,如果你还需要别的键,可以自行添加;
  • 然后,我们生成了一个临时变量 tmp,用来存储 F13 的键值,这只是一个中间键,用于触发我们长按操作的;
  • 接着,我们在 tmp 触发的情况下,定义当按下 Bindings 中的键 key 时,发送 ctrl+key
  • 然后,我们定义 pressedF18releasedF18 函数,分别用来开关 tmp 的触发,并在缺省情况下发送一次 Escape;
  • 最后,我们给 F18 键绑定上 pressedF18releasedF18 函数。

保存上面的配置脚本,然后在 MenuBar 里单击 HS 的图标,选择「Reload Config」,稍等一会儿改好的键位就生效了。用 HS 改过的键盘行为,在 EventView 里面查看不到,不过可以用 KeyCastr 这个软件检测到。你也可以直接操作快捷键来检测效果。

善用 Hyper 键,避免键位冲突

前面给大家介绍了这么多改建的工具和方法,主要是为了给大家引出 Hyper 键的概念。不知道大家有没有这样的感觉,需要用到快捷键的软件越来越多,键盘上的按键越来越不够使用,有时候自己想设置一个全局的快捷键,要么和系统或者软件的某个快捷键冲突了,要么就是实在没有什么意义特步不好记。如果你把修饰键设置多一点儿,比如同时按下 ⌃ Control + ⌥ Option + ⌘ Command 什么的,倒是不容易冲突了,可是手又特别的别扭。Hyper 键就是一个别特好的解决方案。

我们可以把键盘上的四个修饰键 ⇧ Shift + ⌃ Control + ⌥ Option + ⌘ Command 同时绑定在一个 Hyper 键上,我在按下 Hyper 键的同时,就相当于同时按下了这四个修饰键,然后你就大可以为自己喜欢的全局快捷键设置各种 Hyper+key 这种既方便又好记的键位了。在我的 Mac 上我把 Hyper 键绑定在了右侧的 ⌥ Option 键上,结合第二节中的单击触发 F12 键功能,便可以把我前几节介绍的功能全部配合起来了。

① 非 Sierra 用户的实现方案

(Sierra 用户可移步至第 ② 小节)

我们先来看看 Karabiner 如何配置 Hyper 键,其实非常简单,点按「Open private.xml」打开自定义改建设置的配置文档,然后增加如下配置:

<item>
    <name>Right option to F12</name>
    <identifier>private.right_option_to_f12</identifier>
    <appendix>When click Right Option only, send F12, otherwise using as Hyper Key.</appendix>
    <autogen>
        __KeyOverlaidModifier__
        KeyCode::OPTION_R,
        KeyCode::COMMAND_L, ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L,
        KeyCode::F12
    </autogen>
</item>

在这个配置中,我们使用了 __KeyOverlaidModifier__ 来声明一个覆盖触发的修饰键。映射 KeyCode::OPTION_R覆盖触发KeyCode::COMMAND_L,同时触发修饰状态 ModifierFlag::CONTROL_L | ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L,也就是四个修饰键 ⇧ Shift + ⌃ Control + ⌥ Option + ⌘ Command,否则触发 KeyCode::F12 键。

我们在 EventView 里面看看效果:

用按键查看器检视按键行为
用按键查看器检视按键行为

  • 第一部分是我单独按下右侧 ⌥ Option 键的效果,可以看到四个修饰状态都被短暂的触发然后释放,最后触发了一下 F12 键;
  • 第二部分我按下了 ⌥ Option+A 键,可以看到,A 键按下时,同时拥有 4 个修饰状态,释放后也不会触发 F12 键。

这样,我们就轻松的用 Karabiner 实现了 Hyper 键的功能。

② Sierra 用户的实现方案

下面就是 Sierra 用户的曲线救国时间,在没有 Karabiner 加持的情况下想要使用 Hyper 键确实要稍微麻烦一点,不过大体思路和我们在上一节中的双重修饰键行为是一致的。

因为 HS 利用的 Carbon API 无法识别左右修饰键,照例,我们得先把右侧 ⌥ Option 键改成某个特殊的键,例如 F19,然后打开 HS 的设置 init.lua 文件,添加如下配置脚本:

-- A global variable for the sub-key Hyper Mode
k = hs.hotkey.modal.new({}, 'F14')
for i,key in ipairs(Bindings) do
  k:bind({}, key, nil, function() hs.eventtap.keyStroke({'cmd','alt','shift','ctrl'}, key)
    k.triggered = true
  end)
end
-- Enter Hyper Mode when F19 (right option) is pressed
pressedF19 = function()
  k.triggered = false
  k:enter()
end
-- Leave Hyper Mode when F19 (right option) is pressed,
--   send F12 if no other keys are pressed.
releasedF19 = function()
  k:exit()
  if not k.triggered then
    hs.eventtap.keyStroke({}, 'F12')
  end
end
-- Bind the Hyper key
f19 = hs.hotkey.bind({}, 'F19', pressedF19, releasedF19)

我们来看看,脚本都做了些什么。

  • 首先,我们复用了上一节的列表 Bindings 用来识别组合键;
  • 然后,我们生成了一个临时变量 k,用来存储 F14 的键值,这只是一个中间键,用于触发 Hyper mode 的;
  • 接着,我们在 Hyper mode 触发的情况下,定义当按下 Bindings 中的键 key 时,发送 shift+ctrl+opt+command+key
  • 然后,我们定义 pressedF19releasedF19 函数,分别用来开关 Hyper mode 的触发,并在缺省情况下发送一次 F12;
  • 最后,我们给 F19 键绑定上 pressedF19releasedF19 函数。

保存上面的配置脚本,然后在 MenuBar 里单击 HS 的图标,选择「Reload Config」,稍等一会儿改好的键位就生效了。

实例:Hyper 键与 Keyboard Maestro 的联动

Hyper 键为我们操作快捷键拓宽了道路,而各种各样的效率软件为我们指明了道路可以通达的方向。KM 的使用教学我不想在这里赘述,我派已经有了很多优秀的文章,水猫特别推荐一下 @Oscar Gong 的 Keyboard Maestro 入门指南,深入浅出,非常具有学习的价值。

善加利用 KM,可以让我们把快捷键玩得很溜,这其中不得不说的是 KM 的快捷键冲突 palette 功能,当 KM 绑定的快捷键冲突的时候,可以弹出一个很小的 palette 让你选择进一步的操作,利用这特性我们可以绑定一些万用的快捷键。

我经常遇到这样的一种情况,突然想新建一样东西,可能是一个 Note,一张截图,一个屏幕录像,一篇日记,一个 Bear 文档或者一篇 Markdown 等等,这些 New 操作都有相似的逻辑,所以我把他们统统绑定在了一个快捷键 Hyper+N 下,然后冲突 palette 会进一步询问我到底需要执行什么「新建操作」。

Keyboard Maestro 示意
Keyboard Maestro 示意

通过 Hyper 键和 KM 的联动,任何情况下,我想新建一篇 Bear 文档都变得非常的优雅:

 Hyper 键演示
Hyper 键演示

番外篇:如何使用粘滞键

最后,我想以一个小技巧作为这篇玩转修饰键教程的结束——粘滞键。

粘滞键设计来帮助用户轻松输入修饰键的辅助功能,特别是针对一些残障人士或者是当你不方便使用多根手指同时按下好几个修饰键时候。

开启的方式非常简单:

  • 「系统偏好设置」-> 点按「辅助功能」-> 然后点按「键盘」
  • 勾选「启用粘滞键」

启用粘滞键
启用粘滞键

激活之后,你可以听到清脆的提示音,现在多键的修饰键你可以通过依次键入的方式,而非同时按下的方式来激活了。每次缓冲一个修饰键,都会有提示音,并在右上角显示出来,非常的方便。比方说如果我想用快捷键 Shift+Ctrl+(Opt)+Cmd+C 来激活中文文本的简繁转换,我可以依次按下这几个键来触发:

粘滞键示意图
粘滞键示意图


好了,今天的「玩转修饰键」就介绍到这里。文中的很多用法只是我一些粗浅的尝试,我想希望通过这样的介绍达到抛砖引玉的效果,也希望大家在评论区给出更多精彩的可能!