Ghostty 開發日誌 005
原文由 Mitchell Hashimoto 于 發布,訂閱此部落格
哈囉!歡迎來到 Ghostty 👻 的官方開發日誌!
距離上次的開發日誌已經過了兩個多月,Ghostty 也多了非常多的更新。這段時間我忙著當新手爸爸,也把大部分的電腦空閒時間都花在改進 Ghostty 上,所以有點疏於更新開發日誌。抱歉!
如果你錯過了之前的開發日誌,或想更了解 Ghostty 是什麼,請參考本站上的 Ghostty 介紹頁面。
社群近況
過去兩個月,Beta 測試群組從 100 人成長到超過 350 人!哇!兩個月前 Beta 測試人數還不到 50 人。非常感謝大家對這個終端機專案的關注,也感謝所有的 Beta 測試者。這群龐大且持續成長的測試者,將確保 Ghostty 在正式公開發布時,成為一個強大而穩定的專案。
我之所以能每一波都大幅增加 Beta 名額,唯一的原因就是 Ghostty 正變得越來越功能完整、越來越穩定。以前每一波 Beta 只邀 5 個人,就會產生十幾個錯誤回報或功能需求。現在要邀 50 個人才會得到同樣數量的回報。而且這個數字只會越來越高。看到這個專案變得越來越真實、越來越穩定,真的很有成就感。
如果你有興趣加入 Beta 測試計畫,請加入 Ghostty Discord以取得下一波 Beta 的候選資格。在撰寫本文時,約有 20% 的 Discord 社群成員已是 Beta 成員。
終端機檢測器 (#728)
終端機是一個應用程式平台。我覺得「平台」這個詞被太多人過度濫用了,好像想讓自己的工作聽起來比實際上更重要(或者至少想讓投資人覺得更重要),但終端機確實是一個文字互動的平台1。
沒有在上面跑的應用程式,終端機就一點也不有趣。更進一步說,沒有應用程式,終端機根本就毫無意義。要增加終端機應用程式的數量與品質,其中一個方法就是讓為終端機開發變得更容易。
如果回顧網頁開發,對我來說開發容易度的一次巨大躍進,就是 Firebug 的出現,現在更常被稱為「網頁檢測器」,類似的功能在每個主流瀏覽器中都能看到。我想把類似的體驗帶到終端機中,所以 Ghostty 現在有了終端機檢測器。
終端機檢測器的運作方式類似網頁檢測器:它是每個終端機各自獨立的面板,會即時更新並顯示正在運行的終端機資訊。你可以看到鍵盤輸入(以及它們如何編碼)、終端機模式、字體大小、網格尺寸、儲存格詮釋資料、調色盤顏色等等。
目標是讓終端機檢測器成為終端機開發者不可或缺的工具,讓開發與除錯終端機應用程式變得更容易(而且是在任何終端機上都能運作的應用程式,不只限於 Ghostty)。
終端機檢測器目前還非常早期、非常實驗性。現在它還只是純唯讀的介面,但我計畫未來讓它支援讀寫,這樣你就能修改儲存格、終端機模式、建立合成輸入事件等等。
最初的終端機檢測器點子來自一位 Beta 社群成員,包含我在內的一小群 Beta 社群成員很快集結起來,把它發展成一個非常具體的想法。感謝所有參與的人!
亞洲語系輸入 (#八百八十八)
在最近幾波 Beta 中,我刻意邀請了來自更多不同時區的人。這帶來了更多使用中文、日文、韓文等語言的測試者。這些測試者回報了近十個與亞洲語系輸入與渲染相關的問題。也因此,Ghostty 現在對這些語言的支援已經非常好了。
在devlog 003 裡,我有一個專門講鍵盤輸入的章節,標題是「Keyboard Input Handling Hates You」。我在那裡大肆宣揚 Ghostty 把這些處理得多好,現在我要延續那個說法,再次強調這一切有多麼複雜,並再次說 Ghostty 全都處理得很好2。
更複雜的輸入狀態
在devlog 003 中,我介紹了死鍵狀態的概念。當時的 Ghostty 只處理單一碼點的死鍵狀態。我用了帶重音的英文字母當例子。在那個例子裡,你會先輸入像 '(撇號)這樣的字元,再輸入像 a 這樣的字母,就會得到 á。
在日文這類語言中,你會輸入一些字元,得到一個建議輸入(可能還會附帶更多建議的下拉選單),然後你可以按下像是 Enter 或 Tab 這類按鍵來完成選字。
Ghostty 當時無法處理多碼點的建議輸入,而且在顯示建議時也會錯誤地處理 Enter 或 Tab 這類字元。這些現在都已修正,你可以正常輸入日文(以及其他語言)了。
這種多碼點的建議狀態也帶來了幾個邊界情況:在行尾輸入,以及在過窄的視窗中輸入。這兩種情況現在 Ghostty 也都能處理了。順帶一提,上面的影片是在另一個錯誤被修正前錄製的(如果你能發現的話),但那個問題現在也已經解決了。
中文字元對齊 (#982)
要在等寬的終端機網格中,以乾淨、一致的方式渲染多種字體(加上 Emoji)是一大挑戰,而中文字元看起來就不太對勁:

可以注意到以 草 開頭的詞彙渲染得有點偏低。這是因為在混用某些字體時,使用了錯誤的字體度量計算(在這個案例中是儲存格的基線)所導致。這個問題在 Ghostty 中現在已經修正。

Linux 輸入法輸入 (#919)
macOS 在作業系統層面就對輸入法編輯器(IMEs)有很好的內建支援。在 Linux 搭配 GTK 的環境下,IME 是由可選擇安裝的外掛程式提供的。正因如此,它們在 Ghostty 上沒有得到充分測試,中文、日文、韓文的輸入完全無法運作。
好在我在 Ghostty 的共用核心中已經為支援 IME 做了很多工作,所以要讓它在 Linux 上正常運作,只需要一個 +47/-1 的差異就能把正確的 GTK 與 Ghostty API 串接起來。結果就是,IME 在 Linux 上也能運作了:
註:這段影片是在上述修正完成前錄製的,所以你還能看到渲染錯誤的字元。
自訂著色器 (#903)
你是否曾想讓你的終端機看起來像一台經典的 CRT 顯示器?或者像一卷壞掉的 VHS 錄影帶?我他媽到底在說什麼?我是不是瘋了?總之,現在你在 Ghostty 中只要指定自訂著色器,就能做到這一切,甚至更多。
先不論實不實用,這種功能看起來好像會很耗電。現代大多數軟體普遍沒效率,把我們都當傻子了!CPU 和 GPU 其實超快的,這點運算根本不算什麼。在我的電腦上,上面的效果只用了約 1% 的 CPU 和約 2% 的 GPU。它當然會比完全不使用這個功能時更耗電(這還用說!),但也不至於讓風扇狂轉。
Ghostty 是一個由 GPU 驅動的終端機模擬器。它在 macOS 上使用原生的 Metal,在 Linux 上使用 OpenGL。GPU 是透過呼叫著色器來渲染畫面。著色器就是揮揮手在 GPU 上執行的程式。
著色器通常是用特定技術的程式語言撰寫的。舉例來說,macOS 上的 Metal 使用 MSL(Metal Shading Language),OpenGL 則使用 GLSL(GL Shading Language)等等。Ghostty 接受以 GLSL 撰寫的著色器,並會在 macOS 上即時將其轉換為 MSL。為了做到這點,Ghostty 使用 glslang 將 GLSL 轉換為 SPIR-V(大致上是一種中介表示法),再使用 SPIRV-Cross 將 SPIR-V 轉換為目標格式,例如 MSL。我們透過它們提供的 C API 來編譯並綁定這兩個工具。
這個功能另一個超酷的細節是,Ghostty 暴露了 Shadertoy 介面,所以你可以把許多 Shadertoy 上的著色器直接丟進 Ghostty 而無需任何修改。更重要的是,你可以把 Shadertoy 本身當作 Ghostty 自訂著色器的即時、互動式開發工具來使用!
別擔心,這個功能不會對效能造成負面影響。Ghostty 使用多執行緒的渲染架構,在影格之間有大量的閒置時間。啟用自訂著色器時,閒置時間會變少,但對其他執行緒(IO 和 GUI)幾乎沒有影響。未使用自訂著色器時,Ghostty 使用與以往相同的渲染管線,不會為現有執行增加任何新資源(除了對自訂著色器的一次布林值檢查,以及用來表示空著色器清單的極小記憶體佔用)。
好吧,但這一切難道不是完全毫無意義嗎?最常見的用途就是好玩,而那當然不是必要的(對啊,去他的樂趣,對吧?)。不過,自訂著色器最主要的實用用途是無障礙輔助。自訂著色器是針對特定類型的色盲、調整對比或亮度以提高可讀性、創造「放大鏡」效果等的絕佳方式。
我並不是想把無障礙的責任推給別人,我也樂於將各種無障礙功能做成內建的一等功能,但在 Ghostty 尚未具備某些功能的情況下,這是讓使用者自己掌握主導權的好方法。
Xterm 相容性稽核與行為文件 (#632)
終端機模擬器雖然是模擬器,但它們到底在模擬什麼?傳統上,終端機模擬器模擬的是像 VT52、VT100、VT220 等實體終端機。但實際上,這些硬體已經太久沒有普及或被實際使用了,以至於大多數現代終端機模擬器只是大致上互相模仿彼此的行為。這導致不同終端機模擬器之間的行為有許多不一致的地方,而且許多終端機模擬器在邊界情況上都有錯誤3。
xterm 是 X 視窗系統的標準終端機模擬器,經常被譽為歷史終端機行為的黃金標準。此外,xterm 的使用非常廣泛,即使不考慮歷史終端機,它的行為對於其所支援的功能來說,也可以被視為事實上的標準。
我已決定,在可行且合理的範圍內,Ghostty 應該完全仿照 xterm 的行為。這讓專案對於「為什麼 <feature> 會這樣運作?」這個問題,能有一致的答案4
我所謂的「在可行且合理的範圍內」是什麼意思?意思是預設在實作某個功能時,我們應該與 xterm 保持一致。如果某個功能被回報有錯誤,我們總是會問「xterm 在這種情況下會怎麼做?」如果有充分的理由可以偏離該行為,那麼那就是例外,而非常態。
為了做到這點,我已開始慢慢稽核 xterm 的每一項有文件記載的功能,並與 Ghostty 進行比較。在這個過程中,我也一直在建立我們自己的文件,並盡量讓它越詳細越好。文件中還包含了帶有預期輸出的 shell 腳本驗證案例,以便撰寫端對端測試來確保相容性。看起來像這樣:

終端機支援的功能很多,xterm 的程式碼庫很複雜,而這項工作非常繁瑣,所以我不可能一夜之間完成。但在過去幾個月裡,我已經慢慢地逐項勾選功能,到目前為止,這已經讓 Ghostty 修復了數十個錯誤,也在其他終端機中發現了數十個錯誤(有些已經回報,有些之後會回報,沒有一個是嚴重的)。
這並不代表 Ghostty 會支援 xterm 支援的所有功能。而是說,對於 Ghostty 已有且 xterm 也有支援的功能,Ghostty 將力求與 xterm 達到最大程度的相容(在有充分理由的情況下允許例外)。
結語
在開發日誌中,我會聚焦於我覺得有趣、想分享的少數幾項變更。開發日誌不是更新日誌,我也不希望它們讀起來只是枯燥的變更清單。話雖如此,我想指出,在過去兩個月裡,Ghostty 專案也有超過 100 項錯誤修正與改進,Ghostty 每天都越來越接近可以公開發布的狀態。
隨著 Beta 規模的擴大,貢獻者的人數也跟著成長。已有將近 50 人為 Ghostty 做出貢獻(幾乎每 6 位 Beta 測試者中就有 1 位不只是回報錯誤,還貢獻了程式碼!)。這真的非常了不起,我非常感謝大家投入的時間與對專案的關注。
如果你想掌握最新動態,請在 Twitter 或 Mastodon 上追蹤我(頁尾有連結)。這個部落格也有 RSS 摘要。
Boo. 👻
註腳
我沒有在找投資人。希望沒有人會那樣解讀這段話,但我覺得還是得說清楚。而且這不是那種「眨眨眼說沒在找」的場面話,我是真的沒興趣。 ↩
處理輸入是很複雜的,我相信還有更多錯誤存在,但現在的狀態已經讓使用日文、韓文和中文的 Beta 測試者能夠全職使用 Ghostty 了。 ↩
幾乎沒有任何終端機模擬器能正確處理將像
草這樣的寬字元切開的逸出序列。這裡的「正確」是有爭議的,因為沒有規範,所以我想它們愛怎麼做就怎麼做。換句話說,行為極度不一致。 ↩當然,這只適用於 xterm 有實作的功能。有些功能例如 Kitty Graphics Protocol 是由 Kitty 明確定義的,在那種情況下我們會盡可能完全仿照 Kitty。 ↩
隨機一篇部落格
留言
登入後參與討論