在 Zed 0.162 中,我们发布了一些键盘快捷键的更改,使其适用于所有人,无论其键盘布局如何。

问题
您可以轻松键入哪些字符取决于您的键盘布局。 Zed 的默认绑定基于您可以仅使用 shift 修饰符轻松键入 U+0033 (!) 和 U+007A (~) 之间的所有字符(ASCII 图形范围)这一假设。
事实证明,这对三类人来说是不正确的
- 您使用西里尔字母(或其他非拉丁字母)键盘,默认情况下不提供 a-z 或 A-Z。
- 您使用日语(或其他基于 IME 的)键盘,默认情况下不键入任何内容。
- 您使用非美国拉丁字母(如法语、德语等),这些字母不提供某些 ASCII 标点符号,因为这些键需要用于像 ü 或 ß 这样的字母。
还有一个额外(完全是自我造成的)问题,即我们将一些键盘快捷键绑定到 option-X
(其中 X 是任何 ASCII 字符)。 这对于很少使用 option 修饰符生成的字符的美国英语使用者来说通常没问题,但阻止了人们在某些键盘上键入像 {
或 @
这样的基本字符。
解决方案
最后一个问题最容易解决。 我们不再将快捷方式绑定到 option-X
(其中 X 是一个字母)。 相反,我们需要 command 或 control 用于字母快捷方式。 (请参见此处了解更改列表)。
除此之外,我们希望 Zed 对于熟悉 macOS 的人来说感觉很自然。 因此,我们进行了一些更改,更紧密地模拟了操作系统级别的默认工作方式。
对于基于 IME 的输入源,我们现在在调用 IME 系统之前触发快捷方式。 因此,如果您启用了日语输入模式并键入 cmd-a
,它将选择全部。 如果 IME 系统当前处于活动状态,那么它将首先获得键盘输入。 这意味着您可以在 Vim 普通模式中使用 a
进行插入;但是如果您正在根据 あ 键入某些内容,那么我们不会妨碍您。
对于非拉丁键盘,macOS 提供了一个基于拉丁字母的布局,该布局在按住 command 键时激活。 这种布局通常只是 QWERTY,因此您可以在亚美尼亚键盘上键入 cmd-ա
,Zed 将收到 cmd-a
。 然而,我们更进一步,即使未按住 command 键,也使用此布局来设置快捷方式。 这确保了绑定到 ctrl-a
(或者在 Vim 模式下,甚至只是 a
)的快捷方式仍然有效。
对于非美国拉丁键盘,解决方案更加棘手。 尽管您可以在这些键盘上键入完整的 ASCII 范围,但您可能需要按住 option 才能访问某些字符。 不幸的是,option 在快捷方式中是有意义的:如果您需要按住 option 才能键入 [
,我们无法判断您是否打算触发 cmd-[
或 cmd-option-[
。
按键等效
自 macOS Catalina 以来,Apple 以 自动快捷键本地化的形式提供了一个解决此问题的方法。 在底层,这会将一些快捷键重新分配给无需 option 即可键入的按键等效项。 尽管如果您使用 SwiftUI 的内置菜单组件,这会自动发生,但 Zed 需要对我们使用的快捷方式进行更严格的控制。
分配按键等效项的方式似乎是考虑到了一些约束而设计的
- 如果可以键入快捷方式,则不应更改它。 因此,
cmd-+
在 QWERTZ 键盘上仍然是cmd-+
,即使 + 键在键盘上的位置不同。 - 如果快捷方式成对出现,它们会保持成对。 因此,
cmd-[
和cmd-]
在 QWERTZ 键盘上变为cmd-ö
和cmd-ä
。 - 否则,如果可能,快捷方式保持与 QWERTY 相同的键。 例如,由于它们是系统窗口切换快捷方式,因此无法使用
cmd-<
和cmd->
,在 QWERTZ 键盘上移动到cmd-;
和cmd-:
。
不幸的是,Apple 似乎没有发布按键等效项的表,也不清楚如何以编程方式提取它们。 因此,我们编写了一个 小型 Swift 应用程序来查找此类键盘布局,渲染包含每个快捷方式的 SwiftUI 菜单,并检查菜单以查看快捷方式已映射到什么。 结果规则在此处可用。
死键
最后的障碍是处理死键。 例如,在 AZERTY 键盘上,^
是一个死键 - 它不会直接生成字符,而是将 IME 置于下一个字符不同的模式。 例如,键入 ^ a
可能会输入 â。 为了允许绑定到此类键盘上的 cmd-^
,我们使用与 Chrome 相同的方法,并使用两次调用 UCKeyTranslate
- 相当于键入 ^ space
以获取键的有效字符。
死键会导致另一个问题,即与 Vim 的键盘处理存在一个小的不兼容性。 Vim 不会查看键入的键,只会查看生成的字符。 这意味着要在 Vim 中删除引号内的内容(通常在 QWERTY 键盘上是 d i "
),在巴西键盘上,您需要键入 d i " space
。 " 使您进入死键模式,而 space 生成 "
。 我们过去常常模拟这一点,但在新代码中,巴西键盘上的 d i "
会在按下空格键之前触发快捷方式。
尽管一些用户抱怨 Vim 版本令人困惑,但我认为我们可能会(在未来的版本中)恢复到更像 Vim 的行为。这部分是因为 Vim 模式的主要前提是避免重新学习如何输入,部分是因为它引入了一个恼人的不一致性。 如果你要删除到下一个引号,你仍然需要输入 d t " space
,因为 t
的参数是任何键入的字符(而 i
的参数是快捷方式...)。
下一步
以上所有内容仅适用于 macOS。我们计划对 Linux(和 Windows)进行类似的更改,但细节可能会略有不同,以保持应用程序的平台原生感觉。 在 Linux 上,我们在处理非拉丁键盘方面存在一些错误,需要解决;我们还有很多关于与各种 IME 子系统交互的内容需要学习。 在 Windows 上,我们可能会使用虚拟键码,并且不对扩展拉丁布局进行重新分配。
正如俗话所说:欢迎提交 PR!如果有什么你认为应该可以工作但目前无法工作的事情,请务必提交错误报告。