配置文件
Capslox 的按键方案定义在一个文件中:keymap.jsonc。
JSONC = JSON with Comments,支持 // 行注释和 /* */ 块注释(不熟悉 JSON?看 MDN 上的简介)。
文件位置
| 平台 | 路径 |
|---|---|
| macOS | ~/.config/capslox/keymap.jsonc |
| Windows | %USERPROFILE%\.config\capslox\keymap.jsonc |
热重载: 保存文件后配置立即生效,无需重启。如果文件有语法错误,Capslox 会弹出错误提示并保留之前的配置。
跨平台覆盖文件
如果你在 macOS 和 Windows 之间需要不同的按键绑定,可以在配置目录下放置平台专属文件:
| 平台 | 覆盖文件 |
|---|---|
| macOS | keymap.macos.jsonc |
| Windows | keymap.windows.jsonc |
Capslox 启动时,若平台专属文件存在则优先使用,否则回退到 keymap.jsonc。常见场景:通过 iCloud Drive、Dropbox、GNU Stow、chezmoi 等工具跨平台同步 dotfiles。
加载优先级:
keymap.macos.jsonc/keymap.windows.jsonc>keymap.jsonc
结构概览
顶层结构:
{
"version": "1.0",
"custom_modifiers": { "caps": { "alias": "cx", "tap": "esc" } },
"vars": {
"apps_emacs_keybindings": ["com.apple.Terminal", "com.googlecode.iterm2"]
},
"layers": [
{
"id": "base",
"on_miss": "pass_to_os",
"bindings": {
"cx-e": "up",
"cx-d": "down",
"cx-s": "left",
"cx-f": "right",
"cx-a": {
"action": "send_keys",
"keys": "opt-left",
"when": { "apps": { "$ref": "/vars/apps_emacs_keybindings" }, "action": "ctrl-[ b" }
}
}
}
]
}
配置包含:
version:配置结构版本(如"1.0")。custom_modifiers:可选。将物理按键映射为修饰键别名。默认配置使用"cx"(取自 Capslox 的首尾字母)。详见自定义修饰键。vars:可选。定义可复用的值(数组、字符串),在其他位置通过{ "$ref": "/vars/名称" }引用。适合在多个绑定间共享应用 ID 列表。layers:层数组。每层包含id、可选的name、可选的activation、on_miss和bindings。
层
层是一组绑定的集合。多个层按顺序排列为栈结构,按下按键时从栈顶向下逐层查找:第一个匹配的绑定会被执行。当某一层没有匹配时,由该层的 on_miss 字段决定是继续向下查找、拦截按键还是直接发送给操作系统。
每个层是一个对象,包含以下字段:
id(必需):层的唯一标识符。bindings(必需):按键 → 动作的映射对象。on_miss(必需):未命中行为,详见未命中行为。activation:激活方式。基础层不需要;手动层用{ "type": "manual" };自动应用层用{ "type": "auto_app", "bundle_ids": [...] }。详见下方对应小节。name:可读标签,会在偏好设置(Preferences → Keymap)等 UI 中显示。enabled:布尔值,默认true。设为false时引擎跳过此层,等同于该层不存在。适合临时禁用某层而不删除其配置。
层有三种类型:
基础层
基础层始终处于活跃状态,不能在运行时推入或弹出。通过 "id": "base" 标识,无需显式设置 activation 字段。
{
"id": "base",
"on_miss": "pass_to_os",
"bindings": {
"cx-h": "left",
"cx-j": "down",
"cx-k": "up",
"cx-l": "right"
}
}
手动层
通过绑定中的 layer_push、layer_toggle 或 layer_swap 动作激活,通过 layer_pop 或对应的释放事件停用。
{
"id": "vim_normal",
"activation": { "type": "manual" },
"on_miss": "block",
"bindings": {
"h": "left",
"j": "down",
"k": "up",
"l": "right",
"i": { "action": "layer_pop", "target": "vim_normal" },
"esc": "continue"
}
}
此例中 on_miss 设为 "block" — 未绑定的按键被拦截,类似 Vim 普通模式。"esc": "continue" 让 esc 穿透到下一层(绕过了 block 的拦截效果)。
自动应用层
当匹配的应用获得焦点时自动激活,失去焦点时自动停用。
{
"id": "terminal",
"name": "Terminal Overrides",
"activation": {
"type": "auto_app",
"bundle_ids": ["com.apple.Terminal", "com.googlecode.iterm2"]
},
"on_miss": "continue",
"bindings": {
"cx-a": "ctrl-a",
"cx-e": "ctrl-e"
}
}
应用标识符
| 平台 | 格式 | 示例 |
|---|---|---|
| macOS | Bundle ID | com.apple.Terminal |
| Windows | 可执行文件名 | WindowsTerminal.exe |
通配符匹配规则: 应用标识符里的 * 匹配一个或多个以点分隔的路径段。例如 "com.jetbrains.*" 匹配 com.jetbrains.intellij 和 com.jetbrains.pycharm,但不匹配 com.jetbrainsxyz。这条规则适用于所有出现 apps 列表的位置,包括 binding 上的 when 子句。
绑定
绑定将按键和动作关联起来。绑定位于层的 bindings 对象中。键是触发键(使用按键语法),值是动作或绑定类型。
"bindings": {
"cx-h": "left",
"cx-j": "down",
"space": {
"type": "long_press",
"short": "space",
"long": { "action": "layer_push", "target": "space_layer" },
"threshold_ms": 500
}
}
绑定值的 "type" 字段声明绑定类型(如 "type": "mod_tap"、"type": "long_press")。当绑定类型是 "action"(直接动作,最常见)时,再用 "action" 字段指明要执行的具体动作(如 "action": "send_keys"、"action": "layer_push")。
绑定值的写法
绑定值的完整形式是一个对象。当绑定类型为 "action" 时,对象里还有 "action" 字段指明动作类型。
三种等价写法
"type": "action" 和 "action": "send_keys" 这两个字段在配置时高频出现。为了方便,Capslox 支持省略——下面三种写法效果完全相同:
"cx-h": { "type": "action", "action": "send_keys", "keys": "left" } // 完整形式
"cx-h": { "action": "send_keys", "keys": "left" } // 省略 type(默认按 action 绑定)
"cx-h": "left" // 省略整个对象(默认动作就是 send_keys),推荐写法
Mod Tap 与 Long Press
根据按压方式触发不同动作。必须显式写 "type" 字段:
"caps": { "type": "mod_tap", "tap": "esc" }
"space": { "type": "long_press", "short": "space", "long": { "action": "layer_push", "target": "space_layer" } }
详见 Mod Tap 和 Long Press。
指令关键字
三个特殊字符串不是按键语法,而是控制单个按键在层中的未命中行为:
"continue":继续查找下一层(忽略该按键在当前层的on_miss设置)"block":吞掉按键"pass_to_os":跳过剩余层,直接发送给操作系统
// 在 on_miss: "block" 的层中,让 Escape 穿透到下一层
"esc": "continue"
什么时候写什么
| 场景 | 形式 |
|---|---|
| 发送按键 | "left"(字符串简写) |
| 穿透/拦截/透传 | "continue" / "block" / "pass_to_os"(指令关键字) |
| 控制层、剪贴板、窗口等 | { "action": "layer_toggle", ... }(动作对象) |
需要 when 条件 |
动作对象 + when |
| 按住修饰键、短按发 Esc | { "type": "mod_tap", ... }(按键模式) |
| 长按时推入层 | { "type": "long_press", ... }(按键模式) |
Mod Tap
按住时充当修饰键,短按时执行动作。
参数:
tap:任意动作(字符串简写或对象形式)。timeout_ms:短按判定时长(毫秒),默认 200。
示例:
"caps": { "type": "mod_tap", "tap": "esc", "timeout_ms": 200 }
判定逻辑: 基于中断而非时长。
| 条件 | 结果 |
|---|---|
| 在超时内释放,期间无其他按键按下 | Tap — 触发 tap 动作 |
| 按住期间有其他按键按下(任何时间) | Hold — 激活为修饰键 |
| 超时后释放,期间无其他按键按下 | 无操作 — 防止误触 |
Hold 修饰键的身份通过推断确定:如果该键在 custom_modifiers 中有条目,则使用该别名;否则使用物理键名本身作为修饰键。
Long Press
短按执行一个动作,长按(超过阈值)执行另一个动作。纯时长判定——无需与其他按键交互。
参数:
short:在阈值前释放时的动作。long:超过阈值时的动作。threshold_ms:时长阈值(毫秒),默认 500。
示例:
"space": {
"type": "long_press",
"short": "space",
"long": { "action": "layer_push", "target": "space_layer" },
"threshold_ms": 500
}
When 子句
让绑定根据前台应用的不同执行不同动作。在任意直接绑定上添加 when 字段。
// 单条件
"cx-a": {
"action": "send_keys",
"keys": "opt-left",
"when": {
"apps": ["com.apple.Terminal", "com.googlecode.iterm2"],
"action": "ctrl-[ b"
}
}
当前台应用匹配 apps 中的某个 Bundle ID 时,使用 when 中的动作代替默认动作。
使用 $ref 共享应用列表
"cx-a": {
"action": "send_keys",
"keys": "opt-left",
"when": {
"apps": { "$ref": "/vars/apps_emacs_keybindings" },
"action": "ctrl-[ b"
}
}
这引用了顶层 vars 对象中定义的 apps_emacs_keybindings 数组。
多条件
按顺序检查,首次匹配生效:
"cx-cmd-a": {
"action": "send_keys",
"keys": "opt-left*5",
"when": [
{
"apps": { "$ref": "/vars/apps_emacs_keybindings" },
"action": "(ctrl-[ b)*5"
},
{
"apps": ["com.jetbrains.*"],
"action": "alt-left*5"
}
]
}
apps 中的通配符使用自动应用层中定义的点号边界匹配规则。
如果没有 when 条件匹配,则使用绑定的默认动作。
特殊 when 动作
使用 "noop" 作为 when 动作,在特定应用中屏蔽按键而不让其穿透:
"cx-i": {
"action": "send_keys",
"keys": "shift-up",
"when": {
"apps": { "$ref": "/vars/apps_emacs_keybindings" },
"action": "noop"
}
}
与 AutoApp 层的关系: when 用于"同一触发键,不同应用不同输出"。AutoApp 层用于"特定应用中完全不同的绑定集"。两者可以共存。
未命中行为
每层的 on_miss 字段控制当某个按键在该层没有匹配绑定时的行为。
| 值 | 行为 | 适用场景 |
|---|---|---|
"continue" |
检查栈中的下一层(默认) | 叠加层(如某 App 专属覆盖层),只处理部分按键,其余按键交给下一层 |
"block" |
拦截按键 — 不做任何事 | 手动激活的临时层(如游戏地图、IDE 命令模式),避免误触 |
"pass_to_os" |
跳过剩余层,将原始按键发送给操作系统 | 基础层,让未绑定的按键正常发给系统 |
{
"id": "vim_normal",
"activation": { "type": "manual" },
"on_miss": "block",
"bindings": { ... }
}
单个绑定可以通过指令关键字忽略该按键所在层的 on_miss 设置:
// 即使 on_miss 为 "block",Escape 也会穿透到下一层
"esc": "continue"
// 强制某个按键直接传递给操作系统,跳过所有剩余层
"f5": "pass_to_os"
完整指令关键字列表见上方绑定值的三种形式章节。
动作
每个绑定都会触发一个动作。动作使用 "action" 字段作为类型标识。动作出现在绑定的值一侧,以及按键模式的字段中(tap、short、long)。
可用动作
Capslox 通用
| 动作 | 说明 |
|---|---|
show_preferences |
打开 Capslox 偏好设置 |
edit_keymap |
打开内置的 keymap 编辑器 |
层切换
| 动作 | 说明 |
|---|---|
layer_push |
推入层(触发键释放时停用) |
layer_pop |
弹出层(或栈顶层) |
layer_toggle |
切换层的开关状态 |
layer_swap |
用目标层替换栈顶非 base 层 |
组合与控制
| 动作 | 说明 |
|---|---|
shell_action |
执行 shell 命令 |
action_sequence |
按顺序执行多个动作 |
noop |
屏蔽按键(不做任何事) |
输入与状态
| 动作 | 说明 |
|---|---|
send_keys |
发送按键 |
toggle_caps_lock |
切换 Caps Lock 开关 |
窗口
| 动作 | 说明 |
|---|---|
bind_window |
将当前窗口绑定到槽位 |
activate_window |
激活或最小化绑定到槽位的窗口 |
剪贴板
| 动作 | 说明 |
|---|---|
clipboard_copy |
复制到命名剪贴板槽位 |
clipboard_cut |
剪切到命名剪贴板槽位 |
clipboard_paste |
从命名剪贴板槽位粘贴 |
clipboard_paste_plain |
从剪贴板槽位粘贴纯文本 |
show_preferences
打开 Capslox 偏好设置窗口。
示例:
"cx-shift-,": { "action": "show_preferences" }
edit_keymap
打开内置的 keymap 编辑器。
示例:
"cx-shift-/": { "action": "edit_keymap" }
layer_push
将一层推入栈。该层在触发键释放时自动停用。
参数:
target(string):要推入的层id。
示例:
"cx-v": { "action": "layer_push", "target": "vim_normal" }
layer_pop
从栈中弹出一层。
参数:
target(string,可选):要移除的层id。省略则弹出栈顶;指定时从栈中任意位置移除该 id 的层。
示例:
"i": { "action": "layer_pop", "target": "vim_normal" }
"esc": { "action": "layer_pop" }
layer_toggle
切换一层:未激活则激活,已激活则停用。
参数:
target(string):要切换的层id。
示例:
"cx-t": { "action": "layer_toggle", "target": "symbols" }
layer_swap
原子地移除栈顶非 base 层,并将 target 层推入其位置。如果当前只有 base 层活跃,swap 会将 target 作为新的栈顶推入。
参数:
target(string):要推入为新栈顶的层id。
示例:
"cx-s": { "action": "layer_swap", "target": "numbers" }
shell_action
执行 shell 命令。发后即忘——命令在后台运行,不捕获输出。
参数:
command(string):要执行的 shell 命令。
示例:
// ───── macOS(POSIX shell, /bin/sh)─────
// 启动应用、URL、文件夹
"cx-cmd-t": { "action": "shell_action", "command": "open -a Terminal" }
"cx-shift-c": { "action": "shell_action", "command": "open -a 'Google Chrome'" }
"cx-shift-g": { "action": "shell_action", "command": "open https://github.com" }
"cx-shift-h": { "action": "shell_action", "command": "open ~" }
"cx-shift-p": { "action": "shell_action", "command": "code ~/path/to/your/repo" }
// 读 / 写剪贴板
"cx-shift-s": { "action": "shell_action", "command": "open \"https://www.google.com/search?q=$(pbpaste)\"" }
"cx-shift-i": { "action": "shell_action", "command": "open \"$(pbpaste)\"" }
"cx-shift-d": { "action": "shell_action", "command": "date | pbcopy" }
// 截图、休眠、通知
"cx-shift-4": { "action": "shell_action", "command": "screencapture -i ~/Desktop/screen-$(date +%Y%m%d-%H%M%S).png" }
"cx-shift-l": { "action": "shell_action", "command": "pmset displaysleepnow" }
"cx-shift-b": { "action": "shell_action", "command": "osascript -e 'display notification \"Build done\" with title \"Capslox\"'" }
// 切换 macOS 暗黑模式
"cx-shift-m": {
"action": "shell_action",
"command": "osascript -e 'tell app \"System Events\" to tell appearance preferences to set dark mode to not dark mode'"
}
// ───── Windows(cmd.exe)— JSON 字符串里反斜杠要写成 \\ ─────
// 打开 URL、文件夹、文件(`start` 用默认应用打开目标)
"cx-shift-g": { "action": "shell_action", "command": "start \"\" https://github.com" }
"cx-shift-h": { "action": "shell_action", "command": "explorer \"%USERPROFILE%\"" }
"cx-shift-i": { "action": "shell_action", "command": "start \"\" \"%USERPROFILE%\\Documents\\notes.md\"" }
"cx-shift-p": { "action": "shell_action", "command": "code \"%USERPROFILE%\\projects\\myrepo\"" }
// 把字面字符串写入剪贴板(`clip` 是 Windows 内置命令)
"cx-shift-c": { "action": "shell_action", "command": "echo Hello from Capslox| clip" }
// 锁屏
"cx-shift-l": { "action": "shell_action", "command": "rundll32.exe user32.dll,LockWorkStation" }
工作方式
| 系统 | Shell | 命令 |
|---|---|---|
| macOS | /bin/sh(登录 shell) |
/bin/sh -l -c "{command}" |
| Windows | cmd.exe |
cmd /C {command} |
- 在用户主目录下运行(macOS 为
$HOME,Windows 为%USERPROFILE%)。 - 在 macOS 上,
/bin/sh是 POSIX shell(大多数系统上为 bash 的 sh 兼容模式)。它不使用默认 shell(如 fish、zsh)——始终调用/bin/sh。 - 在 Windows 上,
cmd.exe不是 bash —— 不支持 bash 的$(...)命令替换、POSIX glob 通配,也不能用单引号字符串。如果需要把动态值(比如剪贴板内容)传入管道,请显式调用 PowerShell:powershell -NoProfile -Command "<pipeline>"。 - PATH 与环境变量:
- macOS:
/bin/sh -l会读取.profile/.bash_profile。如果你日常用 fish 或 zsh 并在其中设置 PATH,npm、cargo、code等命令可能不会被shell_action找到,除非它们也在/bin/sh的 PATH 中。 - Windows:
cmd.exe不读取任何 shell rc 文件。PATH 来自系统与用户环境变量(设置 → "编辑系统环境变量")。添加新工具到 PATH 后需要重启 Capslox 才能生效。
- macOS:
- 不捕获输出。如果命令失败,退出码会被内部记录(
ShellAction exited with code N)。 - 一次性:命令被 spawn 后即被遗忘。无法从 Capslox 中终止或等待它。
不适用于 交互式命令、长时间运行的监视工具,或依赖特定 shell 环境的命令。
action_sequence
按顺序执行多个动作。当单一动作类型无法满足需求时使用。
参数:
actions(array):非空动作列表。每个元素可以是字符串简写(解析为send_keys)或完整动作对象。
示例:
// 把当前日期写入剪贴板,然后粘贴。
"cx-shift-d": {
"action": "action_sequence",
"actions": [
{ "action": "shell_action", "command": "date | pbcopy" },
"cmd-v"
]
}
noop
抑制按键,不执行任何操作。
示例:
"cx-q": "noop"
在叠加层中用于屏蔽特定按键,防止其传递到下层。也常用于 when 子句中,在特定应用中屏蔽某个绑定(默认动作在那些应用里没有意义)。
send_keys
发送一个或多个按键事件。最常用的动作类型。
参数:
keys(string):按键语法字符串,一个或多个组合键,可选地带重复和分组。详见下方按键语法。
示例:
// 字符串简写(推荐——因为 send_keys 是默认动作,可省略整个对象)
"cx-h": "left"
"cx-cmd-a": "alt-left*5"
// 需要 when 子句时必须用对象形式
"cx-a": {
"action": "send_keys",
"keys": "opt-left",
"when": { "apps": { "$ref": "/vars/apps_emacs_keybindings" }, "action": "ctrl-[ b" }
}
按键语法
- 单个组合键:left、super-shift-4。
- 多组合键(空格分隔,顺序执行):super-shift-left backspace。
- 重复(组合键后加
*N):alt-left*5。 - 分组重复(
(组合键)*N):(ctrl-[ b)*5。
规则:
- 不带括号的
*N只重复紧前面的单个组合键。 (组合键)*N将组合键分组并重复整组。- 不支持嵌套:
((...)...)*N无效。 - 最大重复次数:100。
常用组合键
节选自默认方案,可直接复制。
macOS:
// 光标移动
"cx-e": "up" // 上
"cx-d": "down" // 下
"cx-s": "left" // 左
"cx-f": "right" // 右
"cx-a": "opt-left" // 按词向左
"cx-g": "opt-right" // 按词向右
"cx-p": "cmd-left" // 跳到行首
"cx-;": "cmd-right" // 跳到行尾
"cx-cmd-p": "cmd-up" // 跳到文档开头
"cx-cmd-;": "cmd-down" // 跳到文档结尾
// 文本选择
"cx-i": "shift-up" // 选中上一行
"cx-k": "shift-down" // 选中下一行
"cx-j": "shift-left" // 选中左一字符
"cx-l": "shift-right" // 选中右一字符
"cx-h": "shift-opt-left" // 选中左一词
"cx-.": "shift-opt-right"// 选中右一词
"cx-u": "shift-cmd-left" // 选中至行首
"cx-o": "shift-cmd-right"// 选中至行尾
// 删除
"cx-w": "backspace" // 向前删除一个字符
"cx-r": "delete" // 向后删除一个字符
"cx-cmd-w": "opt-backspace" // 向前删除一个词
"cx-cmd-r": "opt-delete" // 向后删除一个词
Windows:
// 光标移动
"cx-e": "up"
"cx-d": "down"
"cx-s": "left"
"cx-f": "right"
"cx-a": "ctrl-left" // 按词向左
"cx-g": "ctrl-right" // 按词向右
"cx-p": "home" // 跳到行首
"cx-;": "end" // 跳到行尾
"cx-alt-p": "ctrl-home" // 跳到文档开头
"cx-alt-;": "ctrl-end" // 跳到文档结尾
// 文本选择
"cx-i": "shift-up"
"cx-k": "shift-down"
"cx-j": "shift-left"
"cx-l": "shift-right"
"cx-h": "shift-ctrl-left" // 选中左一词
"cx-.": "shift-ctrl-right" // 选中右一词
"cx-u": "shift-home" // 选中至行首
"cx-o": "shift-end" // 选中至行尾
// 删除
"cx-w": "backspace"
"cx-r": "delete"
"cx-alt-w": "ctrl-backspace" // 向前删除一个词
"cx-alt-r": "ctrl-delete" // 向后删除一个词
toggle_caps_lock
切换操作系统的 Caps Lock 状态。
示例:
"cx-shift-c": { "action": "toggle_caps_lock" }
将窗口绑定到命名槽位,便于瞬时切换或最小化。
bind_window
将当前窗口绑定到命名槽位。
参数:
slot(string):窗口槽位名称。
示例:
"cx-cmd-1": { "action": "bind_window", "slot": "1" }
activate_window
激活绑定到命名槽位的窗口。如果该窗口已是最前窗口,则最小化它(toggle 行为)。
参数:
slot(string):窗口槽位名称。
示例:
"cx-1": { "action": "activate_window", "slot": "1" }
Capslox 提供独立于系统剪贴板的命名剪贴板槽位。槽位名是任意字符串。
clipboard_copy
将当前选区复制到命名剪贴板槽位。
参数:
slot(string):剪贴板槽位名称。
示例:
"cx-c": { "action": "clipboard_copy", "slot": "1" }
clipboard_cut
将当前选区剪切到命名剪贴板槽位。
参数:
slot(string):剪贴板槽位名称。
示例:
"cx-x": { "action": "clipboard_cut", "slot": "1" }
clipboard_paste
从命名剪贴板槽位粘贴,保留格式。
参数:
slot(string):剪贴板槽位名称。
示例:
"cx-v": { "action": "clipboard_paste", "slot": "1" }
clipboard_paste_plain
从命名剪贴板槽位粘贴纯文本,去除格式。
参数:
slot(string):剪贴板槽位名称。
示例:
"cx-shift-v": { "action": "clipboard_paste_plain", "slot": "1" }
按键词汇表
完整按键词汇表。所有名称均为小写。用于绑定键、按键序列字符串和 custom_modifiers。
字母: a b c d e f g h i j k l m n o p q r s t u v w x y z
数字: 0 1 2 3 4 5 6 7 8 9
方向键: up down left right
导航键: home end pageup pagedown
功能键: f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12
控制键
| 键名 | 说明 |
|---|---|
| space | 空格键 |
| enter | 回车键 |
| tab | Tab 键 |
| esc | Escape 键 |
| backspace | 向后删除(macOS 的 Delete 键) |
| delete | 向前删除(macOS 的 Fn+Delete) |
| caps | Caps Lock 键 |
安全符号键
直接使用字面字符。
| 键名 | 字符 |
|---|---|
| [ | 左方括号 |
| ] | 右方括号 |
| / | 斜杠 |
| = | 等号 |
| , | 逗号 |
| . | 句点 |
| ; | 分号 |
| ' | 撇号 |
命名符号键
这三个字符在按键语法中有特殊含义,对应物理键用单词形式。
| 键名 | 物理按键 | 原因 |
|---|---|---|
| minus | - |
组合键分隔符 |
| backslash | \ |
JSON 转义符 |
| backtick | ` |
视觉容易混淆 |
小键盘
| 键名 | 说明 |
|---|---|
| kp_0 到 kp_9 | 小键盘数字 |
| kp_enter | 小键盘回车 |
| kp_plus | 小键盘 + |
| kp_minus | 小键盘 - |
| kp_multiply | 小键盘 * |
| kp_divide | 小键盘 / |
| kp_decimal | 小键盘 . |
| kp_equal | 小键盘 = |
| kp_clear | 小键盘 Clear |
按键语法: 用 - 组合修饰键和按键:
"ctrl-shift-a" // Ctrl + Shift + A
"cmd-left" // Command + 左箭头
"shift-/" // Shift + /
"cmd-minus" // Command + -
修饰键顺序: 修饰键可以任意顺序书写——ctrl-shift-a 和 shift-ctrl-a 等价。建议的书写顺序为:自定义修饰键 → caps → ctrl → alt → shift → cmd(参考 Apple HIG)。
修饰键
修饰键在按键语法中作为前缀使用:修饰键-按键。各平台习惯不同的命名,两种写法都接受,建议使用对应平台的名称,配置在该平台读起来更自然:
| 修饰键 | macOS | Windows |
|---|---|---|
| Control | ctrl | ctrl |
| Shift | shift | shift |
| Option / Alt | opt | alt |
| Command / Win | cmd | win |
任意修饰键加 _left / _right 后缀即指定侧别,例如 opt_left、cmd_right、ctrl_left。不加后缀表示任意一侧。
"ctrl_right-a" // 仅右 Ctrl + A
"ctrl-a" // 任意一侧 Ctrl + A
跨平台别名 super 同时匹配 macOS 的 cmd 和 Windows 的 win,便于在跨平台 keymap 中使用统一的修饰键名。
Windows 用户注意: Windows 系统保留 Win 键组合(如 Win+R、Win+D)作为系统级快捷键。根据 Microsoft 官方文档,涉及 Win 键的键盘快捷键保留给操作系统使用。所以建议 Windows 上的快捷键尽量避免使用 win,改用 alt 等不冲突的修饰键组合。
自定义修饰键
任何物理按键都可以通过 custom_modifiers 成为修饰键。
字段:
alias:在绑定中使用的修饰键名(如 cx-h)。tap:短按释放时触发的动作。接受任意动作:字符串简写(解析为send_keys,例如"esc")或完整动作对象(引擎原生动作如toggle_caps_lock必须用对象形式)。默认值是按键本身。timeout_ms:短按判定时长(毫秒),默认 200。
三种写法
为减少书写量,custom_modifiers 支持逐层省略——下面三种写法引擎都接受:
// 完整形式
"custom_modifiers": {
"caps": { "alias": "cx", "tap": { "action": "toggle_caps_lock" }, "timeout_ms": 300 }
}
// 省略默认值(等价于 { "alias": "cx", "tap": "caps", "timeout_ms": 200 },短按 Caps Lock 发送 Caps Lock)
"custom_modifiers": {
"caps": { "alias": "cx" }
}
// 字符串简写(只需别名时的最简形式,短按保持原按键行为)—— 推荐
"custom_modifiers": {
"caps": "cx"
}
自动 mod_tap 回退
在 custom_modifiers 中声明的按键自动获得 mod_tap 行为——按住时充当修饰键,短按时执行 tap 动作。换句话说,配置 custom_modifiers 之后不需要再单独写一条 mod_tap 绑定,省去重复:
{
"custom_modifiers": { "caps": { "alias": "cx", "tap": "esc" } },
"layers": [{
"id": "base",
"on_miss": "pass_to_os",
"bindings": {
// 不需要 "caps": { "type": "mod_tap", ... }!
// 按住 Caps = cx 修饰键,短按 Caps = Escape(来自 custom_modifiers)
"cx-h": "left",
"cx-j": "down"
}
}]
}
如果某层为该键设置了显式绑定,显式绑定优先于回退行为。
多对一别名
多个物理按键可以共享同一个别名。最实用的场景:默认方案用 caps 作为 cx 修饰键,但 HHKB 等紧凑键盘没有 Caps Lock 键。把 tab 也设为 cx,就能瞬间继承所有现有绑定,不必为新键盘重做配置:
"custom_modifiers": {
"caps": "cx",
"tab": "cx"
}
现在 caps 和 tab 都激活 cx 修饰键。无论按住哪个,cx-h 都会触发。
别名可以使用任何符合按键命名规范的名称(小写字母、数字、下划线)。cx 是默认惯例,取自 Capslox 的缩写。
常见错误
绑定不符合预期时的快速排查清单:
- 物理按键名 vs Shift 后字符:写 shift-/ 而不是
?,写 shift-[ 而不是{,写 shift-1 而不是!。按键以 US QWERTY 物理位置命名(参见按键词汇表)。 - 三个键必须用单词形式:minus(不是
-)、backslash(不是\)、backtick(不是`)——它们分别与组合键分隔符、JSON 转义、TS 模板字面量冲突。 - 连接方式:修饰键与按键之间用
-,例如 cx-h 是 cx + h 的组合键。 - 引擎原生动作必须用对象形式:
toggle_caps_lock、layer_push、shell_action、剪贴板与窗口类动作都不支持字符串简写,必须写{ "action": "..." }。字符串简写仅限send_keys(任意按键语法)、"noop",以及三个指令关键字"continue"/"block"/"pass_to_os"。