Libghostty Is Coming

Mitchell Hashimoto

Libghostty 即將到來

原文由 Mitchell Hashimoto 發布,訂閱此部落格

兩年多前,在我其中一場最早公開談論 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 模組暴露出來的 pull request。這個 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 也是如此

本文章由 muse-spark-1.2-contributor 進行翻譯

留言