lazydocker 快捷键速查表:全量按键指南与速查文档生成机制源码剖析
本篇基于 lazydocker 仓库中的官方快捷键速查文档(cheatsheet),完整梳理项目、容器、服务等各面板的全部快捷键及其触发场景,并结合 pkg/gui/keybindings.go 的按键注册源码与 pkg/cheatsheet 生成管线,讲清楚这张速查表“从哪来、为何长这样、哪些键没有出现在表里”。读完后你既能把快捷键当日常操作手册直接使用,也能理解速查文档的自动生成与校验机制,方便在多语言环境下维护与扩展。
一、速查文档的性质:它是自动生成的产物
docs/keybindings/Keybindings_en.md 开头明确声明:
This file is auto-generated. To update, make the changes in the pkg/i18n directory and then run
go run scripts/cheatsheet/main.go generatefrom the project root.
也就是说,这份英文速查表并非手工维护,而是由 生成脚本入口 从源码中的按键绑定定义实时渲染出来的。docs/keybindings/ 目录下共存在 9 个语言版本(Keybindings_en.md、Keybindings_zh.md、Keybindings_de.md 等),分别对应 pkg/i18n/ 中 9 套翻译集。因此阅读这张表时应理解两点:
- 按键与行为的映射以源码为准,速查表只是它的“文档化投影”;
- 只有携带
Description字段的绑定才会被收录进速查表,一部分同样有效的导航类按键(如j/k/h/l、方向键)并不会出现在文档中。
二、全局快捷键(Global)
以下按键的 ViewName 为空字符串,即在任意视图聚焦时都生效(见 keybindings.go#L500-L511):
| 按键 | 作用 |
|---|---|
+ |
切换下一个屏幕模式(normal / half / fullscreen 循环) |
_ |
切换上一个屏幕模式 |
1 |
聚焦 Projects 面板 |
2 |
聚焦 Services 面板 |
3 |
聚焦 Containers 面板 |
4 |
聚焦 Images 面板 |
5 |
聚焦 Volumes 面板 |
6 |
聚焦 Networks 面板 |
几点源码级补充:
- 数字键
1~6的注册方式是遍历六个面板并统一绑定到gui.handleGoTo(view)(keybindings.go#L537-L544),是“跳面板”而非“切换面板类型”; - 屏幕模式在
gui.State.ScreenMode中循环,取值为SCREEN_NORMAL、SCREEN_HALF、SCREEN_FULL三态。一个容易踩坑的细节在 view_helpers.go#L288-L309:当焦点位于main主面板时,+与_的实际方向是反转的(+走 prev 循环、_走 next 循环),这是为了让主面板放大时按+能“退回到”小窗,符合操作直觉。
此外,全局注册中还有一批未进入速查表的按键(因为它们没有 Description 字段,会被生成器跳过):
| 按键 | 作用(源码行为) |
|---|---|
q、Ctrl+C |
退出 lazydocker(gui.quit) |
esc |
全局 escape 处理 |
x、? |
打开选项菜单(handleCreateOptionsMenu) |
X |
执行自定义命令(handleCustomCommand) |
J/K、H/L |
主面板下/上、左/右滚动 |
PgUp/PgDn、Ctrl+U/Ctrl+D |
主面板翻页滚动 |
Home/End |
跳顶 / 自动滚动跟随 |
这些绑定与速查表中的条目出自同一个函数 GetInitialKeybindings()(keybindings.go#L57-L591),所以文档没列 ≠ 按键无效。
三、Project 面板快捷键
聚焦 Projects 面板(ViewName: "project")时生效:
| 按键 | 作用 |
|---|---|
e |
编辑 lazydocker 配置文件(handleEditConfig) |
o |
打开(查看)lazydocker 配置文件(handleOpenConfig) |
m |
查看全部日志(handleViewAllLogs) |
enter |
聚焦主面板 |
[ |
切换上一个 tab(上一个上下文) |
] |
切换下一个 tab(下一个上下文) |
/ |
过滤列表 |
其中 enter/[/] 三条并不是为 project 单独写死的,而是对所有侧边面板统一循环注册的结果(keybindings.go#L552-L576),因此你会在下面每个面板的速查段里看到同样三行——这是循环注入而非重复定义。
四、Containers 面板快捷键
聚焦 Containers 面板时,可执行最完整的容器生命周期操作(绑定定义见 keybindings.go#L188-L264):
| 按键 | 作用 | 对应处理器 |
|---|---|---|
d |
删除容器(运行中会询问是否强制删除) | handleContainersRemoveMenu |
e |
隐藏/显示已停止的容器 | handleHideStoppedContainers |
p |
暂停容器 | handleContainerPause |
s |
停止容器 | handleContainerStop |
r |
重启容器 | handleContainerRestart |
a |
attach 进入容器 | handleContainerAttach |
m |
查看日志 | handleContainerViewLogs |
E |
在容器内执行 shell | handleContainersExecShell |
c |
执行预定义自定义命令 | handleContainersCustomCommand |
b |
查看批量命令 | handleContainersBulkCommand |
w |
在浏览器中打开(映射的第一个端口按 http 处理) | handleContainersOpenInBrowserCommand |
enter |
聚焦主面板 | handleEnterMain |
[ / ] |
上一个 / 下一个 tab | panel.HandlePrevMainTab / HandleNextMainTab |
/ |
过滤列表 | handleOpenFilter |
注意大小写差异是刻意的:小写 s 是 stop、大写 S 在 Services 面板里才是 start;容器面板里大写 E 是 exec shell。这些按键在速查表中的文案(如 "remove"、"hide/show stopped containers")来自 pkg/i18n/english.go 中 TranslationSet 的 Remove、HideStopped 等字段——速查表与界面提示共用同一套翻译源,改一处所有语言版速查表同步变化。
五、Services 面板快捷键
聚焦 Services 面板(docker compose 服务视角)时(绑定定义见 keybindings.go#L265-L369):
| 按键 | 作用 | 对应处理器 |
|---|---|---|
u |
up 当前服务(docker compose up 单服务) |
handleServiceUp |
d |
删除该服务的容器 | handleServiceRemoveMenu |
s |
停止服务 | handleServiceStop |
p |
暂停服务 | handleServicePause |
r |
重启服务 | handleServiceRestart |
S |
启动服务 | handleServiceStart |
a |
attach 进入服务容器 | handleServiceAttach |
m |
查看日志 | handleServiceRenderLogsToMain |
U |
up 整个 compose 项目 | handleProjectUp |
D |
down 整个 compose 项目 | handleProjectDown |
R |
查看重启选项(rebuild / recreate 等) | handleServiceRestartMenu |
c |
执行预定义自定义命令 | handleServicesCustomCommand |
b |
查看批量命令 | handleServicesBulkCommand |
E |
在容器内执行 shell | handleServicesExecShell |
w |
在浏览器中打开(第一个端口按 http) | handleServicesOpenInBrowserCommand |
enter |
聚焦主面板 | handleEnterMain |
[ / ] |
上一个 / 下一个 tab | panel.HandlePrevMainTab / HandleNextMainTab |
/ |
过滤列表 | handleOpenFilter |
小写 u/s/r/p 针对单个服务,大写 U/D 针对整个项目,大写 R 则是打开重启选项菜单——这一大写/小写分层约定是 Services 面板与 Containers 面板最大的语义差异。
六、Images / Volumes / Networks 面板快捷键
这三个面板的操作集一致且更精简(绑定定义见 keybindings.go#L370-L432):
| 按键 | Images | Volumes | Networks |
|---|---|---|---|
c |
执行预定义自定义命令 | 同左 | 同左 |
d |
删除镜像 | 删除卷 | 删除网络 |
b |
查看批量命令 | 同左 | 同左 |
enter |
聚焦主面板 | 同左 | 同左 |
[ / ] |
上一个 / 下一个 tab | 同左 | 同左 |
/ |
过滤列表 | 同左 | 同左 |
对应的处理器分别是 handleImagesRemoveMenu、handleVolumesRemoveMenu、handleNetworksRemoveMenu 等。删除镜像/卷/网络时会弹出确认菜单,其中包含 prune(清理未使用资源)等选项,相关文案(如 "prune unused images")同样来自 pkg/i18n/english.go 的 PruneImages、PruneVolumes 等字段。
七、Main 主面板快捷键
聚焦 Main 主面板(日志、统计等右侧大区域)时(keybindings.go#L433-L463):
| 按键 | 作用 |
|---|---|
esc |
返回(handleExitMain),从主面板切回左侧列表焦点 |
h / ← |
主面板内容左移滚动 |
l / → |
主面板内容右移滚动 |
速查表只列出了 esc,因为滚动类按键没有 Description 字段;j/k(上下滚动)则通过统一的 setUpDownClickBindings 注入(keybindings.go#L525-L550)。
八、所有面板通用的列表导航与过滤
速查表没有专门列出、但实际生效的按键(均出自 GetInitialKeybindings() 的循环注册段):
- 列表移动:
j/↓/ 鼠标滚轮下移 → 下一行;k/↑/ 滚轮上移 → 上一行;h/l、←/→与Tab/Shift+Tab在侧边面板间左右切换焦点(keybindings.go#L514-L550); - 鼠标:左键点击列表行即选中该项(
MouseLeft绑定到各面板的HandleClick); - 过滤:
/打开过滤输入框,输入后Enter提交(commitFilter)、esc取消。注意/绑定有一个条件:只有panel.IsFilterDisabled()为 false 的面板才会注册过滤键(keybindings.go#L578-L588); - 按键注册落点:
keybindings()函数把上述全部绑定逐条调用 gocui 的g.SetKeybinding(viewName, key, modifier, handler)注册到 GUI 实例上(keybindings.go#L593-L607),ViewName为空即全局生效,非空则仅当该视图持有焦点时生效。
九、速查表是如何生成的:从源码到 Markdown
速查文档的生成管线由三部分构成,值得完整走读一遍:
1. 入口脚本
scripts/cheatsheet/main.go 接受两个子命令:
# 在项目根目录执行,重新生成 docs/keybindings/ 下全部语言的速查表
go run scripts/cheatsheet/main.go generate
# 校验已提交的速查表是否为最新(不一致时打印 diff 并退出码 1)
go run scripts/cheatsheet/main.go check
2. 生成逻辑
pkg/cheatsheet/generate.go 的 generateAtDir 流程(generate.go#L35-L61):
- 初始化一份默认应用配置并创建 App;
- 遍历
i18n.GetTranslationSets()返回的每一种语言,通过os.Setenv("LC_ALL", lang)切换语言环境; - 调用
mApp.Gui.SetupFakeGui()建立假 GUI,使GetInitialKeybindings()可以在无终端环境下被调用; - 对每个绑定按
ViewName归组:空串归入 “Global”,其余映射到 Project/Services/Containers/Images/Volumes/Networks/Main 八个标题(generate.go#L78-L106); - 用
<kbd>key</kbd>: description的<pre>块渲染每一节,输出到docs/keybindings/Keybindings_<lang>.md。
其中“哪些按键进表”的过滤规则是 if binding.Description == "" { continue }(generate.go#L81-L84)——这正是第二、七节中那些“没出现在文档里”的导航键缺席的原因。按键显示名由 Binding.GetKey() 负责:rune 直接格式化,特殊键码则映射为 esc(27)、enter(13)、space(32)、方向箭头、PgUp/PgDn 等友好字样(keybindings.go#L20-L54)。
3. 一致性校验
pkg/cheatsheet/validate.go 的 Check() 把生成过程重放到系统临时目录(validate.go#L15-L30),再与仓库中已提交的 docs/keybindings/Keybindings_*.md 全量比对;不一致时用 unified diff 输出差异并提示 “Cheatsheets are out of date”。这意味着修改了按键绑定或 i18n 文案而没有重新运行 generate,校验就会失败——这是维护该仓库时的一条硬性约定。
4. 数据源:Binding 结构体
一切速查内容的“单一事实来源”是 pkg/gui/keybindings.go#L12-L18 的 Binding 结构:
type Binding struct {
ViewName string // 生效视图;"" 表示全局
Handler func(*gocui.Gui, *gocui.View) error
Key interface{} // rune 或 gocui.Key
Modifier gocui.Modifier
Description string // 非空才会被收录进速查表
}
速查表中的每条描述(如 "hide/show stopped containers")直接取自 Description 字段,而该字段填的是 gui.Tr.XXX 翻译指针(如 gui.Tr.HideStopped),实际字符串定义在 pkg/i18n/english.go 等 9 个语言文件中。因此“改按键说明”的正确姿势是改 pkg/i18n 下的翻译项再跑 generate,而不是手改 Markdown——文档首行的自动生成声明正是为此而设。
十、日常操作速记
综合以上内容,一组高频操作的推荐肌肉记忆:
| 场景 | 按键 |
|---|---|
| 在六个面板间快速跳转 | 1~6,或 h/l、Tab 左右切换 |
| 选中容器后看日志 / 进 shell | m / E |
| 重启 / 停止 / 删除容器 | r / s / d |
| 过滤当前列表 | / + 关键字 + Enter(esc 取消) |
| compose 项目 up / down | Services 面板 U / D;单服务用 u |
| 查看某容器映射端口的 Web 界面 | w(浏览器打开第一个 http 端口) |
| 界面太挤 / 想看更多日志 | + / _ 循环 normal → half → fullscreen |
| 主面板里回到左侧焦点 | esc |
| 退出程序 | q 或 Ctrl+C |
十一、小结
- docs/keybindings/Keybindings_en.md 是 lazydocker 快捷键的完整速查视图,覆盖 Global、Project、Containers、Services、Images、Volumes、Networks、Main 八个作用域,且与 9 个语言版本文档同源生成;
- 速查表背后的单一事实来源是 pkg/gui/keybindings.go 中
GetInitialKeybindings()返回的Binding列表:ViewName决定作用域,Description决定是否入表; - 文档再生成与一致性校验分别由 scripts/cheatsheet/main.go 的
generate与check子命令完成,文案改动须落在 pkg/i18n/ 翻译集中,再重新生成,避免提交“过期”的速查表。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00