内置 keymap 插件
@opentui/keymap 保持引擎精简。内置插件包在公共注册 API 之上安装解析器阶段、字段编译器、诊断、消歧义和宿主特定的辅助函数。
如果您想构建自己的插件,请参阅自定义插件。
每个插件都返回一个 disposer。
import * as addons from "@opentui/keymap/addons"
import * as opentuiAddons from "@opentui/keymap/addons/opentui"
通用插件
默认值
| 导出 | 描述 |
|---|---|
defaultBindingParser | 字符串按键语法的共享解析器 |
defaultEventMatchResolver | 规范化击键的共享事件匹配器 |
registerDefaultBindingParser() | 追加 defaultBindingParser |
registerDefaultEventMatchResolver() | 追加 defaultEventMatchResolver |
registerDefaultKeys() | 同时安装两个默认阶段 |
共享的默认解析器接受单按键命名键、修饰键组合、字面标点符号、" " 表示空格、"+" 作为字面加号键、<token> 别名和 {pattern} 运行时捕获。它解析连接的多按键序列,如 dd、<leader>s 或 {count}j。
如果解析的序列引用了未知令牌,该扩展绑定会被跳过直到令牌注册。这是一种失败关闭行为:没有注册的 leader 令牌时,<leader>s 不会变成普通 s。
识别的修饰键前缀(不区分大小写,用 + 连接):
| 修饰键 | 别名 |
|---|---|
ctrl | control |
shift | - |
meta | alt, option |
super | - |
hyper | - |
字段插件
| 导出 | 添加的功能 |
|---|---|
registerBindingOverrides() | 层本地 bindingOverrides 字段,用于按字符串命令名替换绑定 |
registerEnabledFields() | 层和命令的 enabled 字段 |
registerMetadataFields() | 绑定 desc / group 和命令 desc / title / category 元数据 |
registerAliasesField() | 层本地 aliases 字段,用于重新映射单按键绑定名称 |
registerBindingOverrides() 期望 bindingOverrides 已经是一个 Binding[] 数组。它在注册时一次性重写该层的绑定数组。匹配的字符串命令会被覆盖绑定替换,未匹配的绑定保持不变。
registerEnabledFields() 接受 boolean、() => boolean 或 ReactiveMatcher 值。它适用于层和命令,而不适用于绑定。它仅控制激活;不发布 attr。
registerMetadataFields() 在暴露到投影之前验证和修剪元数据字段。绑定 desc / group 成为绑定元数据。命令 desc / title / category 成为 commandAttrs 中的命令元数据。
层元数据是应用特定的。直接使用 registerLayerFields() 注册层字段,并在图/调试可视化需要层标签或分组元数据时调用 ctx.attr(...)。
registerAliasesField() 添加绑定而不是替换原始绑定,别名保留在声明它们的层本地。
语法和序列插件
| 导出 | 描述 |
|---|---|
registerCommaBindings() | 将 x, y 展开为多个绑定 |
registerEmacsBindings() | 解析 Emacs 风格的间隔组合,如 ctrl+x ctrl+s |
registerLeader() | 定义令牌(如 leader),<leader> 语法通过它展开 |
registerModBindings() | 使用宿主元数据添加平台感知的 mod+... 绑定 |
registerTimedLeader() | 定义 leader 令牌并在超时后清除 |
registerBackspacePopsPendingSequence() | 允许 Backspace 在当前待处理序列中后退 |
registerEscapeClearsPendingSequence() | 允许 Escape 取消当前待处理序列 |
registerNeovimDisambiguation() | 基于超时的精确与前缀消歧义 |
选项:
| API | 选项 |
|---|---|
registerLeader() | LeaderOptions: trigger,可选语义 name(默认 "leader") |
registerTimedLeader() | TimedLeaderOptions: LeaderOptions 加上 timeoutMs、onArm、onDisarm |
registerBackspacePopsPendingSequence() | BackspacePopsPendingSequenceOptions: preventDefault(默认 true),priority |
registerEscapeClearsPendingSequence() | EscapeClearsPendingSequenceOptions: preventDefault(默认 true),priority |
registerNeovimDisambiguation() | NeovimDisambiguationOptions: timeoutMs(默认 300) |
在注册同层精确/前缀绑定(如 g 和 gg)之前注册消歧义插件。
Leader trigger 接受按键字符串、按键对象、类绑定的 { key },或来自 createBindingLookup().get(...) 的单个绑定查找结果。空查找结果被视为禁用并返回空操作 disposer;包含多个绑定的查找结果会被拒绝。
支持禁用 leader 键的应用可以省略 leader 插件或传递空查找结果。任何 <leader>... 绑定将保持休眠,因为未解析的令牌会被跳过。
诊断
| 导出 | 描述 |
|---|---|
registerDeadBindingWarnings() | 当绑定没有命令且没有可达的继续时发出警告 |
registerUnresolvedCommandWarnings() | 当字符串命令无法解析时发出警告 |
Ex 命令
registerExCommands() 安装 ex 命令字段编译器、命令转换器和 :name ...args 字符串的解析器。通过使用冒号前缀的命令名称或 namespace: "excommands" 在正常 keymap 层中注册 ex 命令。
import { registerExCommands } from "@opentui/keymap/addons"
registerExCommands(keymap)
keymap.registerLayer({
commands: [
{
name: "write",
namespace: "excommands",
aliases: ["w"],
nargs: "1",
desc: "Write file",
run({ payload }) {
// payload.raw === ":write session.log"
// payload.args === ["session.log"]
},
},
],
})
ExCommand 字段:
| 字段 | 类型 | 必需 | 描述 |
|---|---|---|---|
name | string | 是 | 命令名称。:name 和 name 都规范化为 :name |
aliases | string[] | 否 | 额外名称 |
nargs | "0"、"1"、"?"、"*"、"+" | 否 | 参数数量验证 |
run | (ctx: CommandContext<TTarget, TEvent, ExCommandPayload>) => CommandResult | 是 | ctx.payload 包含修剪后的 raw 输入和解析后的 args |
| 额外字段 | unknown | 否 | 作为已注册命令的顶层字段添加 |
- 已注册的 ex 命令默认
namespace为excommands。 - 别名产生额外的已注册命令,例如
:write和:w。 - 额外字段保留在
getCommands()/getCommandEntries()结果中,并通过命令字段插件编译。 runCommand(":write file.txt")和dispatchCommand(":write file.txt")都通过已安装的解析器。
OpenTUI 插件
@opentui/keymap/addons/opentui 重新导出所有通用插件并添加以下 OpenTUI 特定的辅助函数。
registerBaseLayoutFallback()
添加一个事件匹配解析器,回退到 KeyEvent.baseCode,使绑定在 Kitty 基础布局报告可用时可以忽略活动键盘布局更改。直接击键匹配优先于基础布局回退匹配,即使跨越活跃层也是如此。
编辑缓冲区辅助函数
| 导出 | 描述 |
|---|---|
createTextareaBindings() | 返回在默认值之前前置覆盖的生成 textarea 绑定 |
registerEditBufferCommands() | 向 renderer.currentFocusedEditor 注册共享编辑缓冲区命令集 |
registerTextareaMappingSuspension() | 挂起聚焦的 TextareaRenderable 的映射快捷键,同时保持普通输入完好 |
registerManagedTextareaLayer() | 高级 textarea 集成:命令、挂起、默认绑定和覆盖 |
registerManagedTextareaLayer() 接受全局 Layer 形状加上可选的 bindings,但它有意排除了 target 和 targetMode。该辅助函数是全局的,跟随 renderer.currentFocusedEditor。
EditBufferCommandOptions:
| 字段 | 类型 | 描述 |
|---|---|---|
category | string | 覆盖生成的命令分类,默认为 Text Editing |
group | string | 覆盖生成的绑定分组,默认为 Text Editing |
includeFineGroup | boolean | 包含硬编码的绑定 fineGroup 字段,用于注册该字段的应用 |
commandNames | Partial<Record<EditBufferCommandName, string>> | 覆盖生成的命令名称 |
descriptions | Partial<Record<EditBufferCommandName, string>> | 覆盖生成的命令描述 |
registerEditBufferCommands() 和 registerTextareaMappingSuspension() 在每个 keymap 上是引用计数的,因此多个集成可以安全地共享它们。
EditBufferCommandName
| 操作 | 默认命令 | 默认描述 |
|---|---|---|
move-left | input.move.left | 光标向左 |
move-right | input.move.right | 光标向右 |
move-up | input.move.up | 光标向上 |
move-down | input.move.down | 光标向下 |
select-left | input.select.left | 选中向左 |
select-right | input.select.right | 选中向右 |
select-up | input.select.up | 选中向上 |
select-down | input.select.down | 选中向下 |
line-home | input.line.home | 行首 |
line-end | input.line.end | 行尾 |
select-line-home | input.select.line.home | 选中到行首 |
select-line-end | input.select.line.end | 选中到行尾 |
visual-line-home | input.visual.line.home | 可视行首 |
visual-line-end | input.visual.line.end | 可视行尾 |
select-visual-line-home | input.select.visual.line.home | 选中到可视行首 |
select-visual-line-end | input.select.visual.line.end | 选中到可视行尾 |
buffer-home | input.buffer.home | 缓冲区开头 |
buffer-end | input.buffer.end | 缓冲区结尾 |
select-buffer-home | input.select.buffer.home | 选中到缓冲区开头 |
select-buffer-end | input.select.buffer.end | 选中到缓冲区结尾 |
delete-line | input.delete.line | 删除行 |
delete-to-line-end | input.delete.to.line.end | 删除到行尾 |
delete-to-line-start | input.delete.to.line.start | 删除到行首 |
backspace | input.backspace | 向后删除 |
delete | input.delete | 向前删除 |
newline | input.newline | 新行 |
undo | input.undo | 撤销 |
redo | input.redo | 重做 |
word-forward | input.word.forward | 下一个单词 |
word-backward | input.word.backward | 上一个单词 |
select-word-forward | input.select.word.forward | 选中下一个单词 |
select-word-backward | input.select.word.backward | 选中上一个单词 |
delete-word-forward | input.delete.word.forward | 删除下一个单词 |
delete-word-backward | input.delete.word.backward | 删除上一个单词 |
select-all | input.select.all | 全选 |
submit | input.submit | 提交 |
生成的 textarea 绑定来自 @opentui/core 中的共享 defaultTextareaKeyBindings。createTextareaBindings() 在这些默认值之前前置覆盖,因此自定义绑定按顺序优先。
请参阅自定义插件了解公共插件编写 API、生命周期规则、回调上下文和扩展点特性。