Hunk 键盘快捷键重映射完全指南:`[keybindings]` 配置、命令 ID 与 Chord 文法解析
开发工具代码评审CLIAI 应用【免费下载链接】hunkReview-first terminal diff viewer for agentic coders项目地址https://gitcode.com/gh_mirrors/hu/hunk点击查看免费下载Hunk 是一款面向 Agent 化开发者的 review-first 终端 diff 查看器其所有键盘操作都被抽象为命名命令named command。本文围绕 Hunk 用户配置中的[keybindings]表系统讲解如何把内置命令与扩展命令重映射到自己习惯的按键上包括配置语法、绑定规则、chord按键组合文法、命令 ID 的查找方式以及底层 keymap 解析与排他性规则的源码实现。读完本文你将掌握 Hunk 快捷键体系的全貌能写出无冲突、可复用的个人键位配置。核心模型每个快捷键都是一个命名命令Hunk 的快捷键体系建立在一条总原则之上任何键盘快捷键背后都是一个命名命令named command。命令拥有稳定的 ID、标题与默认按键而[keybindings]表把命令 ID 映射到你想使用的按键组合上[keybindings] hunk.app.quit ctrlx # 单个 chord hunk.review.nextHunk [], ctrln] # 一个命令多个 chord hunk.review.focusFilter / # 把 / 从内容搜索手里拿回来 hunk.history.nextCommit ctrln # 历史浏览有自己的一套命令 ID hunk.view.toggleMenuBar false # 彻底解绑 myext.toggle ctrlg # 扩展命令也可以重映射命名空间hunk.与扩展 ID每一个命令 ID 都以所有者的名字开头Hunk 自己的命令统一放在hunk.命名空间下如hunk.app.quit、hunk.review.nextHunk、hunk.view.openThemeSelector扩展命令的 ID 格式为扩展ID.命令ID如myext.toggle可参考 docs/extensions.md 中关于扩展命令的说明。这种划分是结构性的hunk是一个保留的扩展 ID因此任何扩展都无法注册一个会遮蔽内置命令的 ID——无论 Hunk 未来新增多少内置命令扩展都不可能与之冲突。commandCatalog.ts中每个内置命令的 ID 都以hunk.category.name形式定义例如 commandCatalog.ts 中的hunk.review.jumpToBottom、hunk.review.jumpToTop与hunk.app.quit。交互式历史浏览hunk log使用hunk.history.*前缀承载与 commit 相关的专属行为而真正跨界面共享的命令如hunk.app.quit、hunk.app.toggleHelp、hunk.view.openThemeSelector在两个界面保持相同 ID。扩展命令目前运行在 review 界面上历史浏览解析其内置命令集时不会占用 review-only 的扩展 chord。绑定规则四条必须牢记的行为约定[keybindings]的行为由四条规则决定理解它们才能写出可预期的配置用户绑定整体替换默认值。你在[keybindings]中列出的 chord 就是该命令响应的完整按键集合而不是在出厂键位上的增量追加。被你绑定的键就归你所有。任何仅以默认值持有同一 chord 的其他命令都会让出该键但仍保留其余按键。例如上文把/绑定给hunk.review.focusFilter后hunk.search.find失去/而原本无键绑定的文件过滤器获得/同时n/N仍然可以跳转搜索匹配项。false或[]表示解绑命令解绑后该命令的按键不做任何事。两个条目抢占同一 chord 属于冲突文件中先出现的那条生效会话会报告被让出的另一条。未知命令 ID 和无法使用的 chord 也以同样方式报告且其余配置仍然生效——一条坏配置不会拖垮整张表。未绑定命令一行配置即可激活部分命令出厂时不带任何键但它们仍然可以通过命令 ID 被调用也出现在菜单中。文件过滤器hunk.review.focusFilter默认无键通过 Tabhunk.app.toggleFocusArea和 File 菜单可达hunk.review.nextNote/hunk.review.previousNote同样默认无键}/{用于在带注解的 hunk 之间跳转。在 commandCatalog.ts 中可以看到hunk.review.focusFilter的defaultKeys: []注释明确说明/属于内容搜索Tab 与菜单仍可到达过滤器而[keybindings]一行即可把/还给它。对这类命令你只需要在[keybindings]中加一行即可赋予 chord。冲突与错误的处理方式keymap 的解析实现 keymap.ts 展示了这些规则在源码中的落地用户绑定按配置顺序逐条处理同一 chord 的先到先得通过claimed映射记录Keybinding x for id ignored • already bound to ...未知命令、不可解析 chord 都会进入issues列表返回给上层而不是抛出异常。特别地如果某个 ID 指向未加载的扩展常见于跨机器共享配置会以软性方式报告扩展可能未加载而hunk.前缀下的未知 ID 则被视为纯粹的拼写错误。Chord 文法如何书写按键组合chord 由修饰键ctrl、alt/option、cmd/meta、shift用连接一个基础键构成。基础键可以是一个字符y、[大写字母表示其移位形式G即 shiftg命名键tab、pageup、left、f2。几个容易踩坑的要点移位后的符号或数字直接写移位产生的字符写!而不是shift1。因为终端上报的就是移位后的字符本身且不同键盘布局下shift1的产物并不一致。ctrl字母同时匹配未命名的裸控制字节C0 控制字符而命名后的 Tab、Enter 事件保持独立ctrli绑定不会吞掉 Tab。alt/option同时匹配显式 Alt 事件与旧式终端使用的 Escape 前缀形式。传统终端无法区分 Alt 与 Meta因此altn与metan在旧式终端上可能重叠Kitty 键盘协议kitty keyboard下两者保持可区分。修饰键同义写法可用controlctrl、cmd/commandmeta、optionalt解析逻辑见 keys.ts。源码级文法校验chord 的解析与匹配实现位于 keys.ts它被发布为hunkdiff/extension的一部分因此 Hunk 内置快捷键、扩展registerCommand绑定与用户[keybindings]配置共享同一套文法多字符基础键必须是已知的命名键集合escape、tab、up、f1…f12等拼写错误如ctlrs、f13会在注册阶段被拒绝而不是静默永不触发shift只允许作用于字母与命名键——对符号或数字使用 shift 会被解析器拒绝并提示请直接绑定移位后的字符本身keys.ts匹配层处理了终端命名差异enter/return视为同一键、space同时接受name: space与裸空格字符详见 keys.ts。查找命令 ID菜单、帮助与完整命令表菜单与应用内帮助按?打开会展示它们所呈现命令的按键因此重映射后菜单和帮助会同步显示新键。解绑某个菜单命令时菜单项仍然保留只是不再显示按键。内置命令 ID 与默认按键的完整清单存放在仓库根目录的 docs/keybindings.md。标记为(none)的命令出厂不带键它们仍可通过命令 ID 调用部分也出现在菜单中并可在[keybindings]中分配快捷键诸如当前行对齐hunk.review.alignCurrentLineTop/Center/Bottom这类语义命令则不需要菜单条目。菜单与帮助中的按键标签如CtrlM、PageUp并非手工书写而是由解析结果实时格式化生成的见 keymap.ts这正是重映射后菜单即更新的机制保证。格式化规则为裸字母按输入显示q带修饰键的字母以命名键形式显示CtrlM命名键取规范标题形式pageup→PageUpf2→F2。内置命令速查表历史浏览命令hunk log在终端中运行hunk log会自动打开只读历史浏览器。其hunk.history.*命令与 review 使用同一套可配置的 keybinding 解析器但保留历史专属效果命令 ID作用默认键hunk.history.openSelection打开选中的 commit(s)enterhunk.history.copyRevision复制焦点 commit 的完整 IDyhunk.history.refresh刷新仓库历史rhunk.history.previousCommit移动到上一个 commitup、khunk.history.nextCommit移动到下一个 commitdown、jhunk.history.startVisualSelection开始视觉选择vhunk.history.clearSelection清除视觉选择escapehunk.history.extendPrevious向上扩展选择shiftup、Khunk.history.extendNext向下扩展选择shiftdown、Jhunk.history.pageUp上翻一页pageup、b、shiftspacehunk.history.pageDown下翻一页pagedown、space、fhunk.history.halfPageUp上翻半页u、ctrluhunk.history.halfPageDown下翻半页d、ctrldhunk.history.jumpToFirst跳到第一个 commithome、ghunk.history.jumpToLast跳到最后一个 commitend、Ghunk.history.search搜索历史/hunk.history.nextMatch选择下一个匹配nhunk.history.previousMatch选择上一个匹配Nhunk.history.toggleGraph切换拓扑图graph呈现(none)hunk.history.toggleUnicode切换 Unicode 图线(none)hunk.history.toggleAuthor切换作者元数据(none)hunk.history.toggleDate切换日期元数据(none)hunk.history.toggleDecorations切换 ref 装饰(none)hunk.history.openFirstParent与第一个父提交对比(none)hunk.history.openParent选择父提交进行对比(none)hunk.history.showAbout显示应用信息(none)历史浏览的补充说明F10打开 File、View、Navigate、Commit、Help 菜单View 菜单包含共享主题选择器与可选的Graph view用提交拓扑图替代默认的按日分组时间线。Graph view 下用Up/Down或j/k移动先按v再用同样的键扩展连续提交选择ShiftUp/ShiftDown或大写K/J直接扩展Escape折叠选择。PageUp/PageDown、b/f、ShiftSpace/Space翻页u/d或Ctrl-U/Ctrl-D半页移动g/G或Home/End跳转/搜索、n/N匹配、t选择主题、r刷新、y复制焦点 commit 的完整 ID、Enter在普通 Hunk review 中打开选择、q或Ctrl-C退出。鼠标可用 Shift-click 扩展选择终端转发修饰键时、单击 commit ID 立即打开、单击复制图标复制其完整不可变 ID、双击行打开。--all或按作者/消息/日期/路径过滤时范围选择不可用因为这类遍历会交错无关 commit 或隐藏中间 commit。从打开的 review 退出后会回到保留的历史选择与视口。Review 与共享命令命令 ID作用默认键hunk.app.openAgentSkill显示 agent skill(none)hunk.app.quit退出qhunk.app.refresh刷新 reviewrhunk.app.toggleFocusArea在文件与过滤器之间切换焦点tabhunk.app.toggleHelp开关帮助?hunk.review.alignCurrentLineBottom将当前行对齐到视口底部(none)hunk.review.alignCurrentLineCenter将当前行居中(none)hunk.review.alignCurrentLineTop将当前行对齐到视口顶部(none)hunk.review.clearSelection清除活动的视觉选择(none)hunk.review.copySelection复制活动的视觉选择yhunk.review.deleteActiveNote删除活动 review 笔记Dhunk.review.editActiveNote编辑活动 review 笔记Ehunk.review.editSelectedFile在编辑器中打开选中文件ehunk.review.focusFilter聚焦文件过滤器(none)hunk.review.halfPageDown下滚半页d、ctrldhunk.review.halfPageUp上滚半页u、ctrluhunk.review.jumpToBottom跳到末尾G、endhunk.review.jumpToTop跳到开头g、homehunk.review.nextAnnotatedFile下一个带注解的文件(none)hunk.review.nextAnnotatedHunk下一个带注解的 hunk}hunk.review.nextFile下一个文件.hunk.review.nextHunk下一个 hunk]hunk.review.nextNote下一条 review 笔记(none)hunk.review.pageDown下翻一页pagedown、space、fhunk.review.pageUp上翻一页pageup、b、shiftspacehunk.review.previousAnnotatedFile上一个带注解的文件(none)hunk.review.previousAnnotatedHunk上一个带注解的 hunk{hunk.review.previousFile上一个文件,hunk.review.previousHunk上一个 hunk[hunk.review.previousNote上一条 review 笔记(none)hunk.review.replyToActiveNote回复活动 review 笔记Rhunk.review.scrollCodeLeft代码左滚加 Shift 快速滚动left、shiftlefthunk.review.scrollCodeRight代码右滚加 Shift 快速滚动right、shiftrighthunk.review.startNote添加 review 笔记chunk.review.startVisualSelection开始视觉行选择vhunk.review.stepDown下移一行或一条笔记down、jhunk.review.stepUp上移一行或一条笔记up、khunk.review.toggleHunkGap展开或折叠选中上下文zhunk.search.find搜索 diff 内容/hunk.search.next下一个搜索匹配nhunk.search.previous上一个搜索匹配Nhunk.view.applyFilePresentationToAllMatching将当前文件呈现应用到所有匹配文件(none)hunk.view.cursorLineNumber标记当前行号(none)hunk.view.cursorLineOff隐藏当前行标记(none)hunk.view.cursorLineRow高亮当前行(none)hunk.view.layoutAuto自动布局0hunk.view.layoutSplit分栏布局2hunk.view.layoutUnified统一布局1hunk.view.openThemeSelector选择主题thunk.view.toggleAgentNotes切换 agent 笔记ahunk.view.toggleCopyDecorations切换复制装饰(none)hunk.view.toggleFilesPane切换文件面板shunk.view.toggleHunkHeaders切换 hunk 头部mhunk.view.toggleLineNumbers切换行号lhunk.view.toggleLineWrap切换换行whunk.view.toggleMenuBar切换菜单栏M笔记交互补充内联已保存笔记暴露可点击的Edit、Reply与针对无回复的用户笔记Delete操作E编辑所选 hunk 中第一条可编辑的用户笔记R回复其第一条可见的已存储笔记。回复继承代码锚点可无限嵌套无产品层面的深度限制静态 sidecar 注解不是回复目标父笔记在移除其所有回复之前不可删除。别名与兼容 IDhunk.view.toggleFilesPane遵循命名的hunk:files角色。若某扩展替换了该角色则此命令与View → Files pane会在任意终端边缘切换已解析的替代物而不改变无关面板。重映射或解绑hunk.view.toggleFilesPane改变的是这个角色感知动作而非扩展面板自己的命令。旧的hunk.view.toggleSidebarID 保留为兼容别名见 commandCatalog.ts 中aliases: [hunk.view.toggleSidebar]。同理hunk.view.layoutStack是hunk.view.layoutUnified的废弃别名commandCatalog.ts既有 keybinding 与扩展命令调用仍会选择规范的统一布局。源码中所有兼容别名都会在 keymap 解析后镜像到解析结果上keymap.ts确保别名查找与规范 ID 得到同一套按键。键盘路由优先级与不可重映射的键键盘事件的路由优先级为宿主提示与对话框 → 菜单/遮罩层 → 聚焦的文本输入 → 交互式文件视图模式 → 会话扩展键盘模式 → 命令表与聚焦的 review 组件。因此属于对话框、菜单或聚焦文本输入的键——如Esc、Enter、写笔记时的Ctrl-S——属于这些组件自身不可重映射。Esc同时是每个激活扩展模式的保留退出键扩展因此无法困住键盘。扩展键盘模式是一个路由层而非第二张命令表它可以消费某个键、把它传递给这些已解析的绑定或消费后退出。其多键文法与计数由扩展所有但解析后的动作应调用同样的公开hunk.*命令。关于 Escape 的补充语义Escape会在遮罩层与扩展模式正常享有所有权之后按上下文清除活动的视觉选择在没有选择的情况下由于 clear-selection 未绑定Esc仍可供扩展命令使用。为什么[keybindings]只读用户配置[keybindings]只从用户配置读取绝不会从仓库的.hunk/config.toml读取。这是因为哪个键做什么属于你的键盘与习惯被 review 的 checkout 不应该能够重排你的键位。Hunk 的配置分层中用户文件~/.config/hunk/config.toml或平台/XDG 配置位置与仓库文件.hunk/config.toml的完整优先级规则可参考 configuration.md仓库设置覆盖用户设置命令小节覆盖其层的顶层值而[keybindings]是唯一的例外——它始终只取用户层。在实现上config.ts 将每个[keybindings]条目的值类型定义为UserKeyBinding string | readonly string[] | false即单个 chord / 多个 chord / 解绑三种形态该类型与resolveCommandKeys的输入严格对应配置层读取后按此类型校验config.ts不支持的值如数字或嵌套对象会被单独收集并报告为不可用的 [keybindings] 条目而不会导致整份配置加载失败。底层解析流程从配置到按键响应理解[keybindings]的完整链路有助于排查重映射不生效的问题声明内置命令在 commandCatalog.ts 中以数据形式声明 ID、标题与defaultKeys部分命令defaultKeys: []即出厂无键。命令目录按类别 名称组织顺序本身就是多命令匹配同一键时的决胜项大写形式排在小写之前。折叠keymap.ts 的resolveCommandKeys把用户[keybindings]折叠到默认值上用户条目整体替换该命令默认值false/空列表解绑用户声明的每个 chord 从仅以默认值持有它的其他命令中剥离排他性规则坏输入绝不抛异常而是生成issues报告其余配置照常生效。调度appCommands.ts 用解析结果构造可派发命令——匹配器与按键标签都来自解析后的 chord所以重映射的命令既响应新键也在菜单/帮助中宣传新键解绑的命令解析为无 chord永不匹配。appCommands.ts 的dispatchAppCommand按第一个启用的匹配命令执行first match wins与命令目录顺序一致。这一声明式、非累加式的设计意味着配置文件里写了什么命令就响应什么不需要去清除旧的默认键。这是 Hunk 快捷键体系最核心、也最容易忽略的语义。赞分享开发工具代码评审CLIAI 应用【免费下载链接】hunkReview-first terminal diff viewer for agentic coders项目地址https://gitcode.com/gh_mirrors/hu/hunk点击查看免费下载相关推荐告别快捷键冲突TranslationPlugin高级键盘映射配置指南告别快捷键冲突TranslationPlugin高级键盘映射配置指南 你是否曾在编码时遭遇过这样的窘境按下自定义的翻译快捷键却触发了完全无关的功能作为每天开发工具插件系统SumatraPDF 自定义键盘快捷键完全指南命令、按键语法、带参命令与全局热键SumatraPDF 自定义键盘快捷键完全指南命令、按键语法、带参命令与全局热键 本篇指南以 SumatraPDF 官方文档《Customize keyboa桌面应用文档IntelliJ IDEA 键盘快捷键全解Windows / Linux 键盘映射速查与实战指南IntelliJ IDEA 键盘快捷键全解Windows / Linux 键盘映射速查与实战指南 本篇基于 Quick Reference 速查清单仓库中的文档教程上一篇智能资源狩猎指南5分钟攻克Oracle ARM服务器容量难题下一篇解决Android文本两端对齐难题TextJustify-Android全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考