# Keyboard Maestro 中的“开关”

> 本文公开全文。

原文：https://utgd.net/article/20184

快捷键就像私家车，只有一个的时候很方便，但如果满大街都是，反而会造成拥堵。

设计糟糕的键位多矣，有些软件干脆把控制权交给用户，爱怎么改怎么改；而 Keyboard Maestro 和 Karabiner Elements 等第三方改键工具也在进阶用户的工具箱中占有一席之地。不过，一般的简化思路限于改动键位，并不能简化设计不当的开关型快捷键。

典型例子就是 DEVONthink 中的预览开关。如果我想查看 Markdown 文档的预览效果，快捷键是 ⌃Control\-⌘Command\-P；如果想回到 Markdown 源码，则是 ⌃Control\-⌘Command\-X。分明是一组互逆操作，难道就不能用一个开关型快捷键来控制吗？

理想的做法应当是这样的：按下某个快捷键，显示预览；再按一下同一个快捷键，退出预览，如此循环。再如开启、关闭编辑器的专注模式，或显示、关闭软件的侧边栏，都应当由一个快捷键控制，而不是两个。在“ON”和“OFF”之间切换，才是“开关”（Switch）的应有之意。本文介绍用 Keyboard Maestro 制作“开关”的方案，希望给读者另一种设计快捷键的思路。

## 快捷键中的开关

一个开关控制“开”和“关”两个操作，实属司空见惯。门边的电灯开关，圆珠笔的按动开关，都是用一个机关控制开和关两个操作。很难想象哪个电灯有两颗开关，一个负责开，一个负责关——如果真的有这种设计，那么两颗按钮一起按下去会发生什么？也无法想象圆珠笔上有两颗按钮——怎么塞得下呢——分别用于伸出和缩回笔尖。

在软件交互设计中，常常看到开、关两个操作，分别由一个快捷键控制。这样的设计，显然是先列出软件可能用到的所有功能，再一个萝卜一个坑地匹配快捷键，却忽视了实际场景。一如唐纳德·诺曼所说，忽视使用场景就会带来复杂，为一组互逆操作设置不同的快捷键，其实就是增加用户负担。稍微想一下就知道，“打开电灯”和“关闭电灯”的按钮不可能同时可用——除非这是在量子世界，一只猫可以又活又死——必然有一个按钮是无意义的，因此，互逆操作的快捷键可以、也应当设置为同一个。

## 在 Keyboard Maestro 中实现开关

可以改键的软件不少，而 Calibre 和 Obsidian 等本身也可以改键，但它们不一定可以制作“开关”。开关型快捷键的本质是两个互逆操作共用一个快捷键，而在多数软件里，这偏偏意味着键位冲突。和家电控制需要焊接线路一样，开关型快捷键也需要一点逻辑控制，而不是简单的键位更改，所以我使用了兼具改键和逻辑判断两大功能的 Keyboard Maestro。

### 简单方案：适用于交互简单的软件

一般的软件，如果有一组互逆功能，通常不会同时显示，要么一次只显示一个，要么保持其中一个为灰色。对于这些软件，Keyboard Maestro 可以较为轻松地模拟出开关效果。对于这些软件，制作开关的逻辑是：按下同一个快捷键，Keyboard Maestro 先检查当前菜单栏功能选项的状态，再执行相应操作。

以 iA Writer 中的预览功能为例，如果菜单栏中有“Hide Preview”，则说明现在已经处于预览模式，此时可供执行的操作是点击“Hide Preview”以退出预览模式；反之，则说明目前正处于编辑状态，可以通过“Show Preview”进入预览模式。菜单栏选项状态充当了 Keyboard Maestro 的逻辑电路。

这些年，双栏式 Markdown 编辑器似乎又不如最初（Mou 那会儿）那么流行了，从 Byword、iA Writer 到 Obsidian 都只有一个界面，而不是左右对开的布局。写作的人因此需要常常在预览模式和编辑模式之间切换，这时候，统一的开关快捷键就可以减少一些操作量。诚然不是什么大事，只是让交互回归正轨罢了。

### 兜底方案：适用于几乎所有软件

Keyboard Maestro 中的触发条件非常丰富，就菜单栏状态这一项，就能够组合出两打的条件。上一节中，我们正是利用了这些条件，在按下同一个快捷键后自动判断启动何种操作。

不过完全依靠软件的菜单栏状态，似乎也不是万金油——文章开头提到的 DEVONthink 就不能沿用现有思路。在技术上，要么（1）软件的菜单栏非常复杂，层层嵌套、命名诡异，以至于 Keyboard Maestro 无法监测出部分项目的状态，比如 DEVONthink；（2）软件根本没有菜单栏，或者我们所需的功能没有被列入菜单栏。这个问题常见于跨平台软件或网页套壳的软件，比如 Obsidian，绝大部分功能就没有放在菜单栏里。

一句话，信息传递出了问题，外界的条件改变不能传递到内部。好在控制论的一个基本原则仍然适用：系统内部的复杂度，应当能够抵消环境的多变。换句话说，如果不能改变外界，那就改变自己——在 Keyboard Maestro 内部制作一个开关。

与上一节类似，这次也要使用 If 判断模块，但是判断的依据有所改变：不是菜单栏的状况，而是在 Keyboard Maestro 内部设置一个变量，考察它的状态。整个思路是这样的：

- 在 Keyboard Maestro 中设置一个变量（第一次运行时就会自动设置），值为0；

- 运行时，如果值是0，就启用软件的A功能，随后将变量改为1；

- 如果运行时发现变量是1，则弃用与A功能互斥的B功能，并随后把变量更改为0。

整个过程中，变量相当于一个内部指标，Keyboard Maestro 不考虑外部发生了什么，只是根据上一次做了什么来指导下一次操作。实际使用时有两种情况，第一种就是非常凑巧，内部变量状态对应了外部可用的功能，这时候运行过程与上一节别无二致；另一种情况则是变量与真实情况不对应，明明不能执行某个操作，但变量却显示可以这么干——这才是美妙之处，错位意味着事实上执行无效，但变量仍然会被改变，从而回到正确的数值，此时又可以正常使用了。你只会发现第一次按键什么都没有触发，而之后的操作又一帆风顺。

只要掌握了内置变量的思路以及判断逻辑，就好像懂得了基本的电路设计原理以及焊接技术，进而拼凑出——尽管不敢说精致——可用的自动化小玩意儿。例如，DEVONthink 中的文档显出效果其实有三种（渲染、源码以及前两者并排显示），那能不能制作一个三种相位的开关，在三个状态之间切换呢？这类练习就交给有兴趣的读者吧。

## 小结，兼谈快捷键设计的思路

简化快捷键的第一步是统一各个软件，比如同样都支持 Markdown，DEVONthink、iA Writer、Byword 和 nvALT 的预览快捷键全都不一样，这就很糟糕，因此首要任务便是自定义统一键位，贯通于不同软件。

即便如此，仍然有大量的快捷键需要背诵，而很多功能过于相像，似乎没有必要设置一大堆近似的快捷键。例如，Ulysses 可以将选中的文本拷贝成普通文本、Markdown 或 HTML 格式，但为此记忆三个快捷键，似乎不值得。在快捷键日益增长的情况下，一部分人发现了 Keyboard Maestro 的 Palette 特性，从而将快捷键归类分组，用一个快捷键呼出 Palette（调色盘，类似一个悬浮工具栏），内置用户自定义的常用功能。前述的文本拷贝格式问题就很适合用 Palette 解决，我制作过一个文本格式转换 Palette，里面有七八种格式转换功能。光是想想要背八组键位，就感到可怕，使用电脑毕竟不是练钢琴，何苦搞那么多组合花样呢；而使用 Palette 之后，需要记忆的键位组合就成倍减少了。关于 Palette 的更多信息，可以阅读 《Keyboard Maestro Palette：macOS 上的全能工具箱》。

走到 Palette 这一步，简化快捷键的主要工作已经完成，剩下的近乎于最后 20% 的努力，乍看上去并不符合二八定律，似乎接下来就是事倍功半的穷折腾。其实并非如此，正所谓百里之行半九十，剩下的操作中也有一些高频操作，比如启用、禁用某个功能，或者开启、关闭某个视图，干嘛要设置两个快捷键？

不够懒的 Keyboard Maestro 用户称不上 Maestro，我想再消灭一个快捷键，遂有此文。说到底，我不是解决了某个迫在媒介的问题，而是也提供了一个零件；如果说 Keyboard Maestro 是一家五金铺，我在这篇文章里所做的工作就是制造进一步的配件，我没办法告诉你一颗空气开关或半打膨胀螺丝应该怎么用，因为它们很可能成为最终工作流中习而不察的部分。

---

[前往标准阅读页](https://utgd.net/article/20184?audience=web)
