Ghostty Devlog 003

Mitchell Hashimoto

Ghostty 開發日誌 003

哈囉!歡迎來到 Ghostty 的第三篇官方開發日誌 👻!

如果您錯過了先前的開發日誌,或想更了解 Ghostty 是什麼,請參閱本網站上的 Ghostty 頁面


社群動態:公開 Discord!

我很興奮地跟大家分享,我們現在有了公開 Discord 伺服器!歡迎任何人加入,詢問關於 Ghostty 的問題、聊聊終端機模擬器、系統程式設計、GPU 程式設計等。我們也正透過 Discord 來擴大 Beta 測試計畫,所以如果您有興趣加入 Beta 測試,請加入 Discord 伺服器並保持一定程度的活躍。

接下來,我將在 9 月 5 日於 Zig Showtime 上發表一場關於 Ghostty 的演講。請留意 Zig Showtime 網站、Twitter、Mastodon 等管道,以獲取確切時間與連結的更新。演講內容仍在規劃中,但大致主題將會是 Ghostty 實作的旋風式導覽,並點出幾個有趣的亮點。畢竟是 Zig Showtime,所以我會更聚焦在 Ghostty 中與 Zig 相關的部分。


鍵盤輸入處理討厭你(#282)1

我不過是個笨笨的美國公民,用著笨笨的美式標準鍵盤配置。在美式標準鍵盤上,你按下 a 就得到「a」,按下 '(單引號)就得到「'」。按下 shift+a 就得到「A」。簡單,太簡單了。你正坐在謊言堆砌的王座上。

麻煩的第一個徵兆是那些非標準、但仍以英文為中心的鍵盤配置,例如 Dvorak 或 Colemak。在美式標準實體鍵盤上,Dvorak 使用者按下 s 會期待得到「o」,而按下 ctrl+i 則會期待出現 ctrl+c 的行為。

麻煩的第二個徵兆是 Unicode 序列。在 Mac 上,使用美式標準配置時,alt+a 會產生 å。最新一批 Beta 測試者中加入了一位挪威使用者,他指出這點特別重要,因為他偏好使用美式標準配置,但會利用 alt 序列來輸入挪威語單字。

麻煩的第三個徵兆是非標準鍵盤配置。你知道什麼是 dead key(死鍵) 序列嗎?我本來不知道(還記得嗎,我只是個笨笨的美式標準使用者)。在美式標準配置上,我們習慣所有的按鍵都是無狀態的。要輸入大寫字母,你會同時按下 shift+A。而如果是 dead key 序列,你會先按下 shift、放開,再按下 a,然後才會看到 A(這並不是真實世界中的 dead key 序列,只是用來說明 dead key 序列運作方式的例子)。一個真實的 dead key 序列,以美式國際配置為例:先按下 '、放開,再按下 a,就會得到 á

當一個人在鍵盤上按下按鍵時,會發生幾件事。鍵盤會送出一個 physical scancode(實體掃描碼)。軟體層的鍵盤配置處理(例如在 QWERTY 鍵盤上使用 Dvorak 配置)會將這個 scancode 轉譯為另一個 scancode(例如在 Dvorak 中,「i」會表現得像「c」)。修飾鍵(ctrl、alt 等)與其他按鍵(例如字母)的組合,接著可能會產生一個或多個字元(例如在 macOS 上 alt+p 會產生「π」,但在美式實體鍵盤上使用 Dvorak 配置時,同樣的字元則是 alt+r)。

最後,並非所有的修飾鍵都會被消耗掉,而這對按鍵綁定來說很重要。舉例來說,如果你在美式配置上綁定了 ctrl+=,在挪威配置上那會是 ctrl+shift+0,你必須知道 shift+0 產生了 =,但並未消耗 ctrl,所以最終的輸入是 ctrl+=。但如果使用者同時也綁定了 ctrl+shift+0,那你該用哪一個呢?🤔

這些說明都非常粗略且缺乏細節。我打算另外寫一篇完整的部落格文章,專門探討鍵盤配置、輸入處理、終端機鍵盤「協定」以及作業系統層級 API 這些如克蘇魯般恐怖的主題,所以在這篇開發日誌中就先跳過細節。敬請期待!

Ghostty 不僅必須處理這些使用情境(因為結果證明,非美式標準鍵盤的使用者確實存在),Ghostty 還必須跨平台做到這一點,因為 Ghostty 已經支援 macOS 和 Linux,並期望未來也能支援 Windows。😰 嗯,Ghostty 現在做到了

唯一能以視覺方式呈現的是 dead key 狀態的處理,現在會以最後一個待處理的 dead key 來算繪。至於其他部分,只能請你相信我,現在都已經能正常運作了。

除此之外,Ghostty 現在也支援可選的明確 physical key mapping(實體按鍵對應)。如果你將按鍵綁定指定為 ctrl+physical:0(請注意 physical: 前綴),那麼只有實體0 鍵才會觸發該綁定。在某些鍵盤配置上,這可能會讓該按鍵綁定無法使用。預設情況下,按鍵綁定是基於邏輯(轉譯後)的按鍵。


Kitty Keyboard Protocol(Kitty 鍵盤協定)與其他協定(#292、#295)

如果你已經對鍵盤輸入感到厭煩,可以直接跳過這一節。

除了將鍵盤按鍵對應到字元輸入外,鍵盤事件也必須對應到 escape sequences(跳脫序列),這樣在終端機中執行的程式才能知道你按了什麼鍵。

最初的終端機協定會將鍵盤按鍵產生的字元原樣傳送。你輸入「a」,就得到「a」,你輸入「A」(shift+A),就得到「A」。這有許多限制。舉例來說,終端機程式無法區分 ctrl-ictrl-shift-i 這類修飾組合,因為它們產生了相同的資料。

為了解決這些缺點,後續發展出了許多額外的鍵盤協定。xterm 發展了 modified keys 序列,Paul Evans(保羅·埃文斯)開發了 fixterms 協定,而 Kovid Goyal(科維德·戈亞爾)(Kitty 的作者)則開發了 Kitty Keyboard Protocol。這些協定的核心概念很簡單,就是定義當按鍵被按下時,終端機要傳送什麼資料給正在執行的程式。

這些並非假設性的問題。這些協定已被 tmuxneovim 等主要程式實作,能讓你綁定的按鍵組合比原本多上數百種。

Ghostty 現已實作了所有這些協定

據我所知,Ghostty 是少數幾個實作所有這些協定的終端機之一。據我了解,只有 iTerm、Foot,或許還有 WezTerm 同時實作了 xterm modified keys Kitty。我認為只有上述那些加上 Kitty 本身有實作 Kitty 協定。大多數終端機(Terminal.app、Windows Terminal、Alacritty、Warp)則完全沒有實作任何鍵盤協定。2

以下影片展示了 Kitty Keyboard Protocol 的運作情形:

以下影片則展示了 xterm modified keys 協定的運作情形:


Linux 桌面元年(GTK)

上一批 Beta 測試者讓我們的全職 Linux 使用者數量從原本的一兩位增加到大約 5 到 6 位,也因此帶來了許多 Linux 使用體驗上的改進。

首先,GTK single instance mode(GTK 單一執行個體模式)(#247)現已啟用並獲得支援。在 GTK 環境下,Ghostty 現在以單一行程執行。第二次啟動 Ghostty 時,會在既有的 Ghostty 行程中開啟新視窗。這能與標準的圖形桌面環境良好協作,也讓 Ghostty 在首次啟動後,後續的啟動速度變得超快

接下來,Ghostty 現在支援primary (selection) clipboard(主選取剪貼簿)(#266)。Linux 桌面擁有多個剪貼簿。「primary」(或「selection」)剪貼簿會在選取文字時自動複製文字,通常透過滑鼠中鍵貼上。這是一個與 ctrl+shift+cctrl+shift+v 不同的獨立剪貼簿,因此你的剪貼簿中可以同時存放多個項目。這個功能有時頗具爭議,所以別擔心,你可以透過 copy-on-select 設定將其停用。你可以在下方的影片中看到實際運作情形。請注意,我並未按下任何鍵盤綁定;這完全是使用選取剪貼簿的效果。

Linux 現在也支援automatic shell integration(自動 Shell 整合)(#245)。我在開發日誌 001 介紹的 Shell 整合中談過此功能。先前,Linux 使用者必須設定一個環境變數來指向 Ghostty 的 share 目錄。現在 Linux 版應用程式會從 ghostty 執行檔開始向上搜尋具有正確資料夾結構的 share 目錄。如果你使用標準的 FHS 目錄配置(Ghostty 打包時使用的標準配置)來安裝 Ghostty,那麼 Ghostty 就會自動找到並設定你的 Shell。

還有更多改進,Ghostty 的應用程式圖示現在能正確顯示(#251)、GTK 應用程式能處理非美式鍵盤配置(#271)、GTK 應用程式支援半透明視窗背景(#264)等等。

我真的很希望 Ghostty 能成為頂尖的 GTK Linux 終端機。我並非全職使用 GTK,因此非常依賴測試者提供回饋來讓體驗變得更好。我很高興地報告,Ghostty 在 GTK 上的表現現在感覺非常好!GTK 版應用程式在體驗上仍落後於 macOS 版,但我期待能讓兩者達到一致的水準!


結語

最近一批 Beta 測試者表現得非常出色。我要感謝 @hovsater 揭露了所有明顯的鍵盤配置與對應問題,並推動我將它們一一修復。@cryptocode 則揭露了十多個與寬字元、multi-codepoint graphemes(多碼位字素群)及其與選取和自動換行互動相關的邊界案例錯誤。還有許多新的測試者,對於 Linux 相關的改進值得感謝。謝謝大家!

如果你想掌握最新動態,請在 Twitter 或 Mastodon 上追蹤我(連結在頁尾)。這個部落格也有 RSS 訂閱來源

Boo. 👻

註腳

  1. 這是參考了優秀的部落格文章 Text Rendering Hates You(《文字算繪討厭你》),我非常推薦一讀。

  2. 我非常尊敬這些終端機模擬器的作者,希望這不會被視為任何攻擊。我只是試圖如實陳述他們支援與不支援的功能。如果我有誤,煩請告知,我會立即修正。

原文由 Mitchell Hashimoto 發布

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