Skip to content

Latest commit

 

History

History
445 lines (333 loc) · 13.9 KB

File metadata and controls

445 lines (333 loc) · 13.9 KB

MothTerm 项目方案与开发进度

基于 Go、cgo、GTK3 和 VTE 的 Linux 优先终端模拟器项目。

本文档是项目的长期方案、架构约束和开发进度记录。开发过程中需要持续更新,代码实现与本文档不一致时,应优先修正文档或明确记录偏差。

1. 项目目标

MothTerm 首先实现一个 Linux 桌面终端应用,后续预留 macOS 和 Windows 支持能力。

1.1 Linux MVP 目标

  • GTK3 主窗口
  • VTE 终端控件
  • 启动默认 Shell
  • 启动指定命令
  • PTY 窗口大小同步
  • 输入、输出、颜色、光标和滚动
  • 复制、粘贴、全选
  • 字体、前景色和背景色配置
  • 新建、关闭和切换标签页
  • Shell 标题同步到标签页
  • Shell 退出状态处理
  • 基本菜单和快捷键
  • Linux 打包和安装

1.2 暂不实现

  • Windows/macOS 的完整实现
  • 分屏
  • 配置图形界面
  • 搜索
  • URL 检测
  • 多 Profile
  • 插件系统
  • 图片协议
  • 自己实现 ANSI/VT100 解析器
  • 自己实现 PTY
  • 自己绘制完整终端网格

2. 总体原则

  1. Linux 优先:先完成可用的 Linux 版本,再验证其他平台。
  2. 跨平台预留,不提前过度实现:公共应用层和终端抽象层保持平台无关,但具体后端先只实现 Linux。
  3. VTE 优先复用:第一版使用 VTE 提供终端模拟能力,不重复实现终端协议和 PTY。
  4. 隔离 cgo:GTK、GLib、VTE 的原始 C API 集中在 Bridge 层,不扩散到 Go 业务代码。
  5. GTK 主线程原则:所有 GTK 对象操作都在 GTK 主循环线程执行。
  6. 明确生命周期:所有 GTK/GObject/VTE 句柄必须有明确的创建、持有、释放路径。
  7. 小步验证:先验证 GTK3/VTE 环境,再接入 cgo,最后增加应用功能。

3. 技术路线

Go 应用层
  ├── App 生命周期
  ├── Window 和 Tab 管理
  ├── 配置
  ├── 快捷键和 Action
  └── TerminalSession 抽象
          │
          │ cgo
          ▼
C Bridge 层
  ├── GTK3
  ├── GLib/GObject
  ├── VTE
  ├── 回调桥接
  └── 对象生命周期管理
          │
          ▼
Linux 平台
  ├── POSIX PTY
  ├── Shell
  └── X11/Wayland

3.1 Linux 当前实现

GTK3 + VTE + Linux POSIX PTY

VTE 负责:

  • 终端转义序列解析
  • PTY 集成
  • 光标和屏幕状态
  • 颜色和字体渲染
  • 滚动历史
  • 选择、复制和粘贴
  • 鼠标事件和终端输入协议

Go 负责:

  • 应用生命周期
  • 标签页和窗口模型
  • 参数解析
  • 配置读写
  • Action 和快捷键
  • 日志和状态管理

4. 跨平台预留方案

后续目标平台和终端后端预计如下:

平台 GUI 后端 终端进程后端 当前状态
Linux GTK3 + X11/Wayland POSIX PTY 首先实现
macOS GTK3 + Quartz POSIX PTY 预留
Windows GTK3 + Win32 ConPTY 预留

Go 应用层不得直接依赖 VteTerminal*。应依赖抽象接口:

type TerminalSession interface {
    Spawn(spec CommandSpec) error
    Write(data []byte) error
    Resize(cols, rows int) error
    Close() error
}

命令描述:

type CommandSpec struct {
    Program string
    Args    []string
    Dir     string
    Env     []string
}

Linux 实现可以内部使用 VTE;未来 Windows 可以增加 ConPTY 实现,不应影响 App、Window、Tab 和 Config 层。

5. 目录规划

mothterm/
├── AGENTS.md
├── README.md
├── LICENSE
├── CONTRIBUTING.md
├── SECURITY.md
├── CODE_OF_CONDUCT.md
├── go.mod
├── Makefile
├── docs/
│   ├── README.md
│   └── PLAN.md
├── scripts/
│   └── check-deps.sh
├── examples/
│   └── m0_demo.c
│
├── cmd/
│   └── mothterm/
│       └── main.go
│
├── internal/
│   ├── app/
│   ├── window/
│   ├── tab/
│   ├── config/
│   └── terminal/
│       ├── session.go
│       ├── backend.go
│       ├── events.go
│       ├── command.go
│       └── linux_session.go
│
├── bridge/
│   ├── bridge.h
│   ├── bridge.c
│   ├── gtk_app.c
│   ├── gtk_window.c
│   ├── vte_terminal.c
│   └── callbacks.c
│
├── ui/
│   └── window.ui
│
├── data/
│   └── mothterm.desktop
│
└── packaging/
    └── linux/

暂时不创建 bridge/windowsbridge/macos,等 Linux MVP 稳定后再添加。

6. cgo/Bridge 设计约束

6.1 对外提供稳定 C API

Go 只通过 bridge.h 中的封装函数使用 GTK/VTE。

typedef void* MothAppHandle;
typedef void* MothWindowHandle;
typedef void* MothTerminalHandle;

MothAppHandle moth_app_new(const char *app_id);
int moth_app_run(MothAppHandle app);

MothTerminalHandle moth_terminal_new(void);
int moth_terminal_spawn(MothTerminalHandle terminal,
                        const char *cwd,
                        const char *program,
                        char **argv);
void moth_terminal_resize(MothTerminalHandle terminal,
                           int columns,
                           int rows);
void moth_terminal_destroy(MothTerminalHandle terminal);

6.2 回调和对象关联

C 代码不长期保存 Go 指针。回调关联使用整数 ID 或 runtime/cgo.Handle

C callback data: uint64 callback_id
Go: map[uint64]*Terminal

对象销毁时必须同时注销回调并释放关联 ID。

6.3 线程约束

  • GTK 初始化和主循环在指定的 GTK 主线程执行。
  • Go 后台 goroutine 不直接操作 GTK 对象。
  • 跨线程 UI 更新通过 GLib 主循环调度。
  • C 回调进入 Go 时不执行耗时业务,必要时投递到 Go 事件队列。

7. Linux MVP 开发阶段

M0:环境验证

状态:已完成(2026-08-19)

目标:确认系统依赖和最小 C GTK/VTE 程序可运行。

检查结果:

GTK3: 3.24.49
VTE runtime: 0.80.1
Go: go1.26.1 linux/amd64
GCC: 14.2.0
显示后端: X11(DISPLAY=:0.0)

当前开发环境没有安装 libvte-2.91-dev,但已安装 VTE runtime。由于当前用户无法通过 sudo 安装系统包,本阶段使用 apt-get download 下载开发包并解压到项目的 .deps/vte-root,通过本地头文件和系统 runtime 完成编译验证。

已创建:

examples/m0_demo.c
.deps/vte-root/

编译验证通过,Demo 能够启动 GTK3 窗口、显示 VTE、异步启动默认 Shell,并打印 Shell PID。由于终端命令环境没有主动关闭窗口,使用 timeout 4s ./examples/m0_demo 结束验证进程,退出码 124 是 timeout 的预期结果,不代表 Demo 启动失败。

已知事项:

  • 当前本地开发包是临时解压方式,后续应优先安装系统级 libvte-2.91-dev
  • 初始 Demo 仅用于环境验证,后续 M1 会重构为正式 C Bridge,不直接复用 Demo 的应用结构。

验收:纯 C Demo 可以创建 GTK3 窗口、显示 VTE,并启动 Shell。通过

M1:Go + cgo 最小窗口

状态:已完成(2026-08-19)

已创建 Go module、C Bridge 和 Go 启动程序。Bridge 封装 GTK3/VTE,启动默认 Shell 或 -e 指定命令,支持窗口创建、VTE 终端、Shell 标题/退出状态回调和基础标签页容器。

验收:运行程序后能够执行 bashvimtop 等交互式程序。

M2:终端基础能力

状态:已完成(2026-08-19)

已实现字体、前景/背景色、光标色、选区色、光标闪烁、响铃和滚动历史配置,以及 VTE 自带的输入输出、PTY、选择、复制粘贴和窗口尺寸能力;已增加 Reset、缩放和菜单 Action。

M3:标签页

状态:已完成(2026-08-19)

已实现 Notebook 标签页容器、独立 VTE Shell、标题更新、退出状态显示、Ctrl+Shift+T/W、Ctrl+PageUp/PageDown、关闭时 PTY 回收,以及独立菜单操作。最后一个标签页关闭时退出应用。

M4:配置和 Action

状态:已完成(2026-08-19)

已实现 JSON 配置默认值、读取、校验、原子保存 API,并接入启动读取;已实现新建/关闭、复制/粘贴/全选、Reset、缩放和退出菜单 Action。

M5:Linux 发布

状态:已完成(2026-08-19)

已添加 Makefile、README、desktop 文件、依赖检查脚本、Debug/Release 构建和安装目标;已完成本地构建与 smoke 验证。

7.1 当前实现补充(2026-08-19)

本轮实现新增 internal/terminal 抽象(CommandSpecSession)、配置校验和原子保存、GTK 菜单操作、标签页标题/状态和 PTY 关闭回收、依赖检查脚本以及 Debug/Release 构建目标。实际 Bridge 仍集中在单一 bridge.c 文件中,与规划中的多文件拆分存在差异,但 Go 应用层未直接使用 GTK/VTE 类型。

验收结果:go test ./...make buildmake releasemake check-deps 均通过;timeout 3s ./mothterm -e 'printf ready' 返回预期 124,stderr 为空。构建仍有 VTE deprecated API 警告,功能不受影响,后续可迁移到非 deprecated API。

7.2 完整实现补充(2026-08-19)

已补齐 GTK size-allocate 到 VTE 字符网格的同步:根据终端控件分配尺寸和字符宽高调用 vte_terminal_set_size,由 VTE 负责对应 PTY 的 rows/columns 更新。标签页销毁先清除关联数据、断开回调并解绑 PTY,避免异步 spawn/child-exited 回调访问已释放的 Tab。

CLI 启动语义现已覆盖 --cwd、重复 --env NAME=VALUE-e 与 positional arguments 互斥,以及环境变量覆盖/新增;Go 侧增加了环境合并和 CommandSpec 字段测试。字体缩放通过缩放 Action 原子保存到配置文件。

已添加真实 GTK/VTE 集成脚本 tests/gtk_vte_integration.sh,在 X11 显示服务器下验证 --cwd--empty-env--env、PTY 子进程退出、窗口出现和 Ctrl+Q 应用退出。为修复 Go cgo 指针规则,Bridge 现在由 C 分配并管理 argv/env 字符串数组。

跨平台边界:当前正式实现仍是 Linux GTK3 + VTE + POSIX PTY;macOS、Windows 仅保留 Go 抽象接口和规划,不宣称已实现。

Linux MVP 完成后再单独验证:

  • macOS GTK3 + Quartz + PTY
  • Windows GTK3 + Win32 + ConPTY
  • 是否可以继续复用 VTE
  • 如果不能,是否需要独立 TerminalView

8. 初始快捷键

功能 快捷键
新建标签页 Ctrl+Shift+T
关闭标签页 Ctrl+Shift+W
下一个标签页 Ctrl+PageDown
上一个标签页 Ctrl+PageUp
复制 Ctrl+Shift+C
粘贴 Ctrl+Shift+V
全选 Ctrl+Shift+A
放大字体 Ctrl+plus
缩小字体 Ctrl+minus
重置字体 Ctrl+0
退出 Ctrl+Q

快捷键后续应统一迁移到 GTK Action 层,不要散落在 Widget 回调中。

9. 配置初稿

推荐先使用 TOML 或 JSON,第一版暂不做配置界面。

font = "Monospace 12"
scrollback_lines = 10000
cursor_blink = true
audible_bell = false
copy_on_select = false
window_width = 1000
window_height = 700
shell = ""
foreground = "#d8dee9"
background = "#20242d"
cursor = "#ffffff"
selection_background = "#4c566a"

空的 shell 表示自动读取 $SHELL,失败后回退到 /bin/sh

10. 验收标准

M1 验收

程序能够启动 GTK3 窗口。
窗口中显示 VTE Terminal。
能够启动默认 Shell。
能够运行交互式命令。
关闭窗口后子进程不会遗留。

M3 验收

可以创建多个标签页。
每个标签页有独立 Shell。
标签页标题能够更新。
关闭标签页会正确结束对应 Shell。
关闭最后一个标签页会按照应用策略退出或创建新标签页。

M5 验收

Linux 上可以从源码构建 Release 版本。
可以通过 desktop 文件启动。
依赖缺失时能够给出明确错误。
常见终端程序可以正常使用。

11. 方案同步规则

每完成一个功能,需要同步修改本文件:

  1. 更新“开发进度”状态;
  2. 记录实际实现与原方案的差异;
  3. 添加遇到的问题和解决方式;
  4. 更新验收结果;
  5. 如果架构发生变化,修改对应章节;
  6. 重要决策追加到“决策记录”。

当前开发进度

阶段 状态 说明
M0 环境验证 已完成 GTK3/VTE/Go/GCC 检查通过;纯 C Demo 已编译并启动 Shell
M1 Go + cgo 最小窗口 已完成 Go 应用已接入集中式 C Bridge
M2 终端基础能力 已完成 配置、PTY、复制粘贴、缩放和终端尺寸同步已实现
M3 标签页 已完成 Notebook、多 Shell、标题同步和关闭回收已实现
M4 配置和 Action 已完成 JSON 配置、原子保存和 GTK Action 已实现
M5 Linux 发布 已完成 Makefile、依赖检查、desktop 文件和安装目标已实现
M6 跨平台验证 暂缓 Linux MVP 完成后进行

12. 决策记录

2026-08-19:Linux 优先

决定先实现 Linux 版本,使用 GTK3 + VTE + POSIX PTY。Windows 和 macOS 只保留抽象接口,不在 MVP 阶段实现。

2026-08-19:不暴露 VTE 类型

决定 Go 应用层不直接依赖 VteTerminal*,通过 TerminalSession 和 C Bridge 隔离 VTE。这样后续可以接入 Windows ConPTY 或其他终端渲染实现。

2026-08-19:不自行实现终端内核

决定第一版不自行实现 ANSI/VT100 解析、PTY 和终端渲染,优先复用 VTE。

13. 当前下一步

  1. 继续维护 Linux MVP 的稳定性和兼容性;
  2. 迁移 VTE deprecated API,减少编译警告;
  3. 完善 Linux 打包和发布流程;
  4. 在 Linux MVP 稳定后,单独评估 macOS 和 Windows 后端。

14. 文档维护说明

本方案文档位于 docs/PLAN.md。根目录 README.md 负责项目介绍和快速开始;贡献、安全与行为准则等仓库治理文档保留在根目录,便于 GitHub 和贡献者发现。