键位绑定

Zed 具有高度可定制的键位绑定系统 —— 您可以调整所有内容,使其完全按照您期望的方式工作!

预定义的键位映射

如果您习惯于特定编辑器的默认设置,您可以在设置文件中设置 base_keymap。 我们目前有

  • VSCode(默认)
  • Atom
  • Emacs(Beta)
  • JetBrains
  • SublimeText
  • TextMate
  • 无(禁用所有键位绑定)

您还可以启用 vim_mode,它也会添加 vim 绑定。

用户键位映射

Zed 从 MacOS 上的 ~/.zed/keymap.json(或 Linux 上的 ~/.config/zed/keymap.json)读取您的键位映射。 您可以使用 cmd-k cmd-s|ctrl-k ctrl-s 在 Zed 中打开该文件,或者通过命令面板中的 zed: Open Keymap 打开。

该文件包含一个带有 "bindings" 的 JSON 对象数组。 如果没有设置 "context",则绑定始终处于活动状态。 如果设置了,则绑定仅在上下文匹配时才有效。

在每个绑定部分中,按键序列映射到动作。 如果检测到冲突,则按照如下所述解决。

如果您使用的是非 QWERTY 拉丁字符键盘,您可能需要将 use_layout_keys 设置为 true。 有关更多信息,请参见非 QWERTY 键盘

例如

[
  {
    "bindings": {
      "ctrl-right": "editor::SelectLargerSyntaxNode",
      "ctrl-left": "editor::SelectSmallerSyntaxNode"
    }
  },
  {
    "context": "ProjectPanel && not_editing",
    "bindings": {
      "o": "project_panel::Open"
    }
  }
]

您可以在 MacOSLinux 的默认键位映射中查看 Zed 的所有默认绑定。

如果您想调试自定义键位映射的问题,您可以使用命令面板中的 debug: Open Key Context View。 如果您遇到您认为应该有效但无效的问题,请提交 一个 issue

键位绑定语法

Zed 能够匹配的不仅仅是单个按键,而是按顺序键入的按键序列。 "bindings" 映射中的每个键都是用空格分隔的按键序列。

每个按键都是修饰符后跟一个键的序列。 修饰符是

  • ctrl- Control 键
  • cmd-win-super-,用于平台修饰符(macOS 上的 Command 键,Windows 上的 Windows 键,Linux 上的 Super 键)。
  • alt- 用于 alt 键(macOS 上的 option 键)
  • shift- Shift 键
  • fn- Function 键
  • secondary- 在 macOS 上运行 Zed 时等同于 cmd,在 Windows 和 Linux 上运行 Zed 时等同于 ctrl

这些键可以是您的键盘生成的任何单个 unicode 码位(例如 a0£ç),或任何命名键(tabf1shiftcmd)。 如果您使用的是非拉丁布局(例如西里尔文),您可以绑定到西里尔字符,或者绑定到按下 cmd 键时该键生成的拉丁字符。

一些示例

 "bindings": {
   "cmd-k cmd-s": "zed::OpenKeymap", // matches ⌘-k then ⌘-s
   "space e": "editor::Complete", // type space then e
   "ç": "editor::Complete", // matches ⌥-c
   "shift shift": "file_finder::Toggle", // matches pressing and releasing shift twice
 }

shift- 修饰符只能与字母组合使用,以指示大写版本。 例如,shift-g 匹配键入 G。 尽管在许多键盘上,shift 用于键入标点符号,例如 (,但按键不被视为已修改,因此 shift-( 不匹配。

alt- 修饰符可以在许多布局上用于生成不同的键。 例如,在 macOS US 键盘上,组合 alt-c 键入 ç。 您可以在键位映射文件中匹配任何一个,尽管按照惯例,Zed 将此组合拼写为 alt-c

可以匹配单独键入修饰键。 例如,shift shift 可用于实现 JetBrains 随处搜索快捷方式。 在这种情况下,绑定发生在按键释放时而不是按键按下时。

上下文

如果绑定组具有 "context" 键,它将与 Zed 中当前活动的上下文匹配。

Zed 的上下文构成一棵树,根为 Workspace。 工作区包含窗格和面板,窗格包含编辑器等。 查看给定时刻哪些上下文处于活动状态的最简单方法是使用键上下文视图,您可以通过命令面板中的 debug: Open Key Context View 进入该视图。

除了名称之外,上下文还可以包含额外的属性,因此您可以(例如)仅在 "context": "Editor && extension==md" 的 markdown 文件中进行匹配。 值得注意的是,您只能在使用属性定义的级别使用属性。

例如

# in an editor, it might look like this:
Workspace os=macos keyboard_layout=com.apple.keylayout.QWERTY
  Pane
    Editor mode=full extension=md inline_completion vim_mode=insert

# in the project panel
Workspace os=macos
  Dock
    ProjectPanel not_editing

上下文表达式可以包含以下语法

  • X && Y, X || Y 用于 and/or 两个条件
  • !X 用于否定条件
  • (X) 用于分组
  • X > Y 用于匹配树中的父项是否匹配 X,并且此层是否匹配 Y。

如果您使用的是 Vim 模式,我们有关于 vim 模式如何影响上下文 的信息

动作

Zed 的几乎所有功能都作为动作公开。 尽管没有明确记录的列表,但您可以通过在命令面板中搜索、在 MacOSLinux 的默认键位映射中查找,或者在您的键位映射文件中使用 Zed 的自动完成功能来找到它们中的大多数。

大多数动作不需要任何参数,因此您可以将它们绑定为字符串:"ctrl-a": "language_selector::Toggle"。 有些需要单个参数,并且必须绑定为数组:"cmd-1": ["workspace::ActivatePane", 0]。 有些动作需要多个参数,并且绑定为字符串和对象的数组:"ctrl-a": ["pane::DeploySearch", { "replace_enabled": true }]

优先级

当多个键位绑定具有相同的按键并且同时处于活动状态时,优先级通过两种方式解决

  • 在上下文树中较低节点上匹配的绑定获胜。 这意味着如果您有一个上下文为 Editor 的绑定,它将优先于上下文为 Workspace 的绑定。 没有上下文的绑定在树中的最低级别匹配。
  • 如果在树中的同一级别有多个匹配的绑定,则稍后定义的绑定优先。 由于用户键位绑定在系统键位绑定之后加载,因此这允许用户绑定优先于内置键位绑定。

另一种出现的冲突是当您有两个绑定,其中一个绑定是另一个绑定的前缀时。 例如,如果您有 "ctrl-w":"editor::DeleteToNextWordEnd""ctrl-w left":"editor::DeleteToEndOfLine"

发生这种情况时,并且两个绑定在当前上下文中都处于活动状态,Zed 将在您键入 ctrl-w 后等待 1 秒,以查看您是否将要键入 left。 如果您不键入任何内容,或者如果您键入不同的键,则将触发 DeleteToNextWordEnd。 如果您这样做了,则将触发 DeleteToEndOfLine

非 QWERTY 键盘

从 Zed 0.162.0 开始,Zed 对 macOS 上的非 QWERTY 键盘提供了一些支持。 计划在 Linux 上更好地支持非 QWERTY 键盘。

大致有三种键盘需要考虑

支持完整 ASCII 的键盘(QWERTY、DVORAK、COLEMAK 等)。 在这些键盘上,绑定根据键生成的字符来解析。 因此,要键入 cmd-[,请找到标记为 [ 的键,然后按住 command 键按下它。

主要是非 ASCII,但在按下 command 键时支持完整 ASCII 的键盘。 例如西里尔文键盘、亚美尼亚语、希伯来语等。 在这些键盘上,绑定根据键入键和按下 command 键时生成的字符来解析。 因此,要键入 ctrl-a,请找到生成 cmd-a 的键。 对于这些键盘,键盘快捷键在其 ASCII 等效项中使用在应用程序中显示。 如果 ASCII 等效项未打印在您的键盘上,您可以使用 macOS 键盘查看器并按住 cmd 键来查找(尽管通常 ASCII 等效项位于 QWERTY 布局中)。

最后,支持扩展拉丁字母的键盘(通常是 ISO 键盘)需要最多的支持。例如,法语 AZERTY 键盘、德语 QWERTZ 键盘等。在这些键盘上,通常无法在不使用 option 键的情况下输入整个 ASCII 范围。为了确保快捷键可以在不使用 option 键的情况下输入,键盘快捷键以与 macOS 相同的方式映射到“按键等效项”。此映射是根据布局定义的,是在以下因素之间取得的折衷方案:使键盘快捷键通过与其定义的字符相同的字符触发,使快捷键与 QWERTY 布局中的位置保持一致,以及将快捷键移出系统快捷键的干扰。

例如,在德语 QWERTZ 键盘上,cmd-> 快捷键被移动到 cmd-:,因为 cmd-> 是系统窗口切换器,并且这是在 QWERTY 键盘上输入该快捷键的位置。cmd-+ 保持不变,因为 + 仍然可以在不使用 option 键的情况下输入,因此,cmd-[cmd-] 变为 cmd-öcmd-ä,移开了 + 键的干扰。

如果您正在个人键盘映射中定义快捷键,则可以通过在键盘映射中将 use_key_equivalents 设置为 true 来选择加入按键等效项映射。

[
  {
    "use_key_equivalents": true,
    "bindings": {
      "ctrl->": "editor::Indent" // parsed as ctrl-: when a German QWERTZ keyboard is active
    }
  }
]

提示和技巧

禁用绑定

如果您希望给定的绑定在给定的上下文中不执行任何操作,则可以使用 null 作为操作。如果您不小心按下了该键绑定并希望禁用它,或者如果您希望输入序列将输入的字符,或者如果您希望禁用以此键开头的多键绑定,这将非常有用。

[
  {
    "context": "Workspace",
    "bindings": {
      "cmd-r": null // cmd-r will do nothing when the Workspace context is active
    }
  }
]

null 绑定遵循与普通操作相同的优先级规则。因此,它也会禁用树中更高级别匹配的所有绑定。如果您希望树中更高级别匹配的绑定优先于较低级别的绑定,则需要在您想要的上下文中将其重新绑定到您想要的操作。

当您指定的操作是条件性的并且会传播时,这对于防止 Zed 回退到默认键绑定非常有用。例如,buffer_search::DeployReplace 仅在搜索栏不在视图中时触发。如果搜索栏在视图中,它将传播并触发为该绑定设置的默认操作,例如打开右侧的停靠栏。为了防止这种情况发生

[
  {
    "context": "Workspace",
    "bindings": {
      "cmd-r": null // cmd-r will do nothing when the search bar is in view
    }
  },
  {
    "context": "Workspace",
    "bindings": {
      "cmd-r": "buffer_search::DeployReplace" // cmd-r will deploy replace when the search bar is not in view
    }
  }
]

重新映射键

一个常见的请求是能够从单个击键映射到序列。您可以使用 workspace::SendKeystrokes 操作来实现这一点。

[
  {
    "bindings": {
      "alt-down": ["workspace::SendKeystrokes", "down down down down"],
      "cmd-alt-c": [
        "workspace::SendKeystrokes",
        "cmd-shift-p copy relative path enter"
      ],
      "cmd-alt-r": ["workspace::SendKeystrokes", "cmd-p README enter"]
    }
  },
  {
    "context": "Editor && vim_mode == insert",
    "bindings": {
      "j k": ["workspace::SendKeystrokes", "escape"]
    }
  }
]

这有一些限制,尤其是

  • 任何异步操作都将在所有键绑定都已分派之后才会发生。例如,这意味着虽然您可以使用绑定来打开文件(如 cmd-alt-r 示例中所示),但您无法发送进一步的击键,并希望它们被新视图解释。
  • 其他异步操作的示例包括:打开命令面板、与语言服务器通信、更改缓冲区的语言、任何访问网络的操作。
  • 一次最多可以模拟 100 个键。

SendKeystrokes 的参数是空格分隔的击键列表(使用与上面相同的语法)。由于击键的解析方式,任何未被识别为按键的段都将逐字发送到当前聚焦的输入字段。

如果 SendKeystrokes 的参数包含用于触发它的绑定,它将使用该绑定的下一个最高优先级的定义。这允许您扩展键绑定的默认行为。

将键转发到终端

如果您使用的是 Linux 或 Windows,您可能会发现自己希望将键组合转发到内置终端,而不是由 Zed 处理它们。

例如,ctrl-n 在 Linux 上的 Zed 中创建一个新标签页。如果您希望在内置终端聚焦时将 ctrl-n 发送到该终端,请将以下内容添加到您的键盘映射中

{
  "context": "Terminal",
  "bindings": {
    "ctrl-n": ["terminal::SendKeystroke", "ctrl-n"]
  }
}

任务键绑定

您还可以绑定键来启动在 tasks.json 中定义的 Zed 任务。有关更多信息,请参见任务文档