← 博客

用 useKeymap 设置键盘快捷键

用 useKeymap 声明一次绑定,Text.js 就会路由按键、在 ? 帮助界面中列出快捷键、在页脚显示,并将其加入 Ctrl+K 命令面板。

Adam

此前,Text.js 应用在 useInput 中处理按键,再在 <KeyHint> 页脚中手动列出一次。useKeymap 用一次声明替代这两处工作。

import { CommandPalette, KeyHelp, KeyHints, StatusBar, Text, useKeymap } from "@textjs/react";export default function Sessions() {  useKeymap(    {      "j, down": { label: "Next", run: next, hint: true },      "k, up": { label: "Previous", run: previous },      "g g": { label: "Go to top", run: top },      "ctrl+s": { label: "Save", run: save, hint: true },    },    { group: "Navigation" },  );  return (    <>      <StatusBar right={<Text color="subtle">main</Text>}>        <KeyHints />      </StatusBar>      <CommandPalette commands={commands} />      <KeyHelp />    </>  );}

按下 j 会运行 next。在 macOS 上,<KeyHints> 会在页脚显示 j/↓ Next 和 ⌃S Save,因为这些绑定设置了 hint。? 会打开帮助界面,列出全部 4 个绑定,归入 Navigation 分组;Ctrl+K 会打开可搜索这些绑定的命令面板。

按键语法

语法含义
ctrl+k修饰键:ctrl、alt、shift、meta 和 mod
mod+k⌘ 或 Ctrl,取决于按住哪个键
j, down可选按键
g g按键序列,两次按键间隔最多 1 秒
G大写表示包含 Shift
?可打印按键按字符匹配

绑定可以是处理函数,也可以是带有 label、group、hint、command、disabled 和 noRepeat 的对象。command: false 会将带标签的绑定排除在命令面板之外。不带标签的绑定仍然有效,但不会出现在帮助界面和命令面板中。

路由

每个按键映射注册一个 useInput 处理函数,因此现有的输入规则仍然适用。获得焦点的 <Input> 会先处理按键,因为编辑器以优先级 10 监听,按键映射则以优先级 0 监听。匹配到的按键会停止传播。打开的 <Modal> 会禁用其外部的绑定,除非按键映射传入了 global: true。

按键序列在该处理函数内部匹配。序列的起始按键会保持待定状态并停止传播;如果下一个按键到达时已超过 sequenceTimeout(默认为 1000 ms),序列就会重置:

if (p.events.length > 0 && now - p.at > sequenceTimeout) p.events = [];

每个根节点一个注册表

带标签的绑定会发布到控制台根节点所属的注册表。<KeyHelp>、<KeyHints> 和 <CommandPalette> 从中读取绑定,你自己的组件也可以通过 useKeymapBindings() 读取。模态框打开时,注册表只返回其内部的绑定,因此帮助界面会列出当前可用的按键。

按键映射通常以内联形式编写,每次渲染都会创建新对象。为降低开销,按键映射只在标签的可见内容发生变化时重新发布标签:

// Publish labels only when the visible shape changes (inline keymap objects are fine).const signature = compiled  .map((c) => `${c.keys}\u0000${c.binding.label ?? ""}\u0000${c.binding.group ?? ""}\u0000${c.binding.hint ? 1 : 0}${c.binding.command === false ? 0 : 1}\u0000${c.binding.disabled ? 1 : 0}`)  .join("\u0001");

按键到达时会从 ref 中读取处理函数,因此每次渲染创建的新闭包都不会过期。

帮助界面与命令面板

<KeyHelp> 在按下 ? 时打开,按分组列出所有当前有效且带标签的绑定。keys 和 title 分别用于更改触发按键和标题。

<CommandPalette> 在按下 Ctrl+K 或 Ctrl+P 时打开。它会对你的 commands 和所有带标签的绑定做模糊匹配,并高亮匹配的字母。它会在运行命令前关闭,因此命令可以打开自己的模态框。

formatKeys 将绑定渲染为显示文本。formatKeys("ctrl+shift+p") 在 macOS 上返回 ⌃⇧P,在其他平台上返回 ctrl+shift+P,而 <Kbd> 使用相同格式渲染单个按键。

useKeymap、<KeyHelp>、<KeyHints>、<StatusBar> 和 <CommandPalette> 随 Text.js 1.0 发布。参考文档见键盘。