Libghostty Is Coming

Mitchell Hashimoto

Libghostty 即将到来

两年多以前,在我关于 Ghostty 的最早几场公开分享之一中,我分享了我对 libghostty 的愿景:一个可嵌入的库,让任何应用都能嵌入属于自己的功能完备、现代且快速的终端模拟器。Libghostty 终于开始成形,我很兴奋能分享关于它的更多计划细节。

首个 libghostty 库将是 libghostty-vt:一个零依赖的库,提供用于解析终端序列并维护终端状态的 API,直接提取自 Ghostty 经现实验证的核心。它甚至不需要 libc!

免责声明:本文主要是 libghostty 的路线图更新,并宣布其首个可交付组件。Zig API 现已可供测试,但 C API 尚未就绪,很快就会推出。在这两种情况下,都属于早期测试质量,尚未达到可供一般使用的程度。


为什么需要 libghostty?

让我们先从一些背景开始,谈谈我为什么认为 libghostty 必须存在。

有数百个程序实现了某种形式的终端仿真。最明显的当然是像 Ghostty、Kitty、iTerm2 等真正的通用终端模拟器。但像 tmuxzellij 这样的终端复用器也是完整的终端模拟器!1 编辑器也会嵌入自己的终端模拟器,例如用于 JetBrains 产品的 jediterm、用于 VS Code 的 Xterm.js,或 Zed 中的 Alacritty

除了功能完备的终端模拟器外,许多网站和应用还实现了只读的终端仿真来显示日志或命令输出。例如,GitHub Actions 输出会解析简单的颜色序列(但几乎不做其他处理)。而像 Vercel 或 Render 这样的托管服务商则实现了一种简单形式的终端仿真,允许在构建日志中清行、重绘以及解析颜色。

这些实现中有许多是临时性的、一次性的解决方案。它们并未使用任何共享的库或代码库。2 终端仿真是一个经典问题,表面上看似简单,却充满了意想不到的复杂性和边缘情况。3 因此,这些实现大多是不完整、有缺陷且缓慢的。4

除了正确性之外,对大多数开发者而言,实现任何形式的终端仿真都是在浪费时间。终端仿真并非 JetBrains、Visual Studio Code、GitHub、Vercel、Render 等的核心业务。如果能拥有一个稳定、可复用且处处一致的解决方案,将对它们大有裨益。

我对此的答案就是 libghostty:一个跨平台、最小依赖的库,它通过暴露 C API,让任何应用在任何地方都能嵌入功能丰富、正确且快速的终端功能。


起点:libghostty-vt

首个 libghostty 库将是 libghostty-vt:一个零依赖(甚至不依赖 libc)的库,提供用于解析终端序列并维护终端状态(如光标位置、当前样式、文本换行等)的 API。

解析终端序列是终端模拟器最核心的功能,从像 Ghostty 这样的完整终端模拟器,到像 GitHub Actions 或 Vercel 构建输出那样简单的只读纯样式视图,都需要它。

状态图初看上去可能相对简单,但要正确实现却出乎意料地具有挑战性。例如,Jediterm 没有正确处理中间字符,导致在本文撰写时,每个 JetBrains 编辑器中被广泛支持的“改变光标形状”序列都会吞掉一个字符。

对于仅解析样式的情况,许多开发者会跳过完整的状态图。相反,他们只是在网上简单搜索一下,解析像 \e[31\e[41m 这样简单的 ANSI 序列,就声称支持了“颜色”。但纯样式序列要复杂得多,例如它们支持 RGB,而 RGB 本身就有十几种格式。而且我至今还没发现有一个网页控制台能正确渲染这个复杂的样式序列5

libghostty-vt 旨在解决所有这些问题。

libghostty-vt 提取自 Ghostty,并继承了所有经过现实检验的优势:经 SIMD 优化的解析、非常好的 Unicode 支持、高度优化的内存使用、经过模糊测试和 Valgrind 测试的健壮代码库、出色的功能兼容性(例如对 Kitty Graphics Protocol 或 Tmux Control Mode 的解析)等等。

所有这些都被打包到单一的零依赖 C API 中(甚至不依赖 libc),使其能够轻松嵌入到任何主流语言生态中。

得益于极小的体积,libghostty-vt 将具有广泛的可移植性。初期目标将是 macOS 和 Linux 的 x86_64aarch64 架构,因为这些是 Ghostty 应用的主要目标。但我计划将支持扩展到更多目标,例如 Windows、嵌入式设备以及通过 WASM 实现的网页。得益于更聚焦的范围,libghostty 将比 Ghostty 图形界面拥有更广泛的支持。


长期规划

libghostty-vt 仅仅是个开始。长期来看,我们将提供更多 libghostty-<x> 库,以暴露更多功能,例如输入处理(键盘编码是其中很重要的一项)、GPU 渲染(只需提供 OpenGL 或 Metal 平面,剩下的交给我们)、处理整个终端视图的 GTK 小部件和 Swift 框架等等。

随着基础组件趋于稳定,我们将继续提供越来越多的功能。这些功能将被组织为一系列库,以最大限度地降低依赖要求、代码体积和整体维护复杂性。


libghostty-vt 现状

我刚刚合并了libghostty-vt 作为 Zig 模块暴露的拉取请求。该 PR 还包含一个最小示例程序。如果你是 Zig 开发者,现在就可以开始尝试 libghostty-vt 了。

C API 尚未就绪,但这正是我目前正在进行的工作,很快就会可供测试。所有需要做的工作就是定义 C API,因为核心逻辑当然早已存在,并且已经被 Ghostty 使用多年。此外,Ghostty macOS 应用已经在使用一个仅供内部使用的 C API

如果你查看这个仅供内部使用的 C 头文件,请忽略其中的混乱。它并不是一个好的 C API。它仅供内部使用,存在只是为了满足 macOS 应用的需求。这并不是一个可供一般使用的 libghostty,尽管它已经被真正的商业产品用于嵌入 Ghostty。我们将以全新的方式来定义供更广泛使用的 C API。

我计划将 libghostty 与 Ghostty 应用分开进行版本管理。这篇博文标志着公开的 alpha 版本(不保证 API 稳定性),我希望能借此激励一些开发者来使用它,并在 C API 就绪后最终为其编写语言绑定。

我希望在未来 6 个月内发布 libghostty-vt 的带标签版本,但这完全取决于它是否已准备就绪。


征求反馈

我们正处于 libghostty 设计 API 的关键阶段,而设计 API 的最佳方式就是来自真实使用者的反馈。Ghostty 是一个使用者,我们也有一些社区成员正在从事其他使用 libghostty 的项目,但我们希望能获得尽可能多的反馈!

如果你在自己的项目或组织中看到了 libghostty 的用例,请加入 Ghostty Discord,与正在从事这项工作的开发者协作。如果你不想加入 Discord,请给我发邮件(邮箱在本网站页脚)。

现阶段 libghostty 的状态可以被视为alpha,因此不要期待打磨完善、稳定的体验。我们正在寻找愿意尽早参与的黑客。

“alpha”质量是就 API(函数和类型)本身而言的。核心逻辑与 Ghostty 共享,极其稳定且已在现实世界中得到验证。


下一个前沿

我非常激动,Ghostty 应用终于达到了足够的稳定性,让我们可以开始朝着 libghostty 的目标迈进。libghostty 是 Ghostty 的下一个前沿,我认为它有能力产生比 Ghostty 作为独立应用本身大得多的影响。

别担心,Ghostty 应用仍会有大量更新,这丝毫不会削弱我对它的热情或规划。更广泛地使用 libghostty 也将带来功能更丰富、更稳定的 Ghostty 应用,因为 Ghostty 本身也是 libghostty 的使用者。

Boo。👻

脚注

  1. 它们拥有其子进程的 pty,解析所有转义码,管理屏幕状态,并最终通过向父终端模拟器发送自己的转义码来“渲染”。

  2. 许多网站确实使用了 Xterm.js,GTK 生态也有 libvte。但这只覆盖了整个版图中极小的一部分,且上述每个例子在其各自的范围内都有局限。

  3. 我花了将近 3 年时间从事终端仿真工作,我们仍在发现奇怪的边缘情况

  4. 这里有几个造成实际影响的问题实例:Jediterm 没有正确处理中间字符Apple 的 Terminal.app 直接将 DCS 序列泄漏到输出中。我并非特意指责谁,只是想说明这些问题确实存在,而终端仿真很难做到完全正确。

  5. 许多通用终端模拟器也曾犯过这个错误,包括就在 9 个月前的 Ghostty

原文由 Mitchell Hashimoto 发布

本文章由 muse-spark-1.2-contributor 进行翻译