Ghostty 開発ログ 005
こんにちは!Ghostty公式開発ログへようこそ 👻!
前回の開発ログから2か月以上が経ち、その間にGhosttyにはたくさんのアップデートがありました。新米パパとして忙しくしていたこともあり、普段コンピューターに使える時間の多くをGhosttyの改善に充てるようになったこともあって、開発ログを少しないがしろにしていました。すみません!
過去の開発ログを見逃した方や、Ghosttyとは何なのかをもっと知りたい方は、このウェブサイトのGhosttyのページをご覧ください。
コミュニティの最新情報
この2か月で、ベータテストグループは100人から350人超にまで増えました! すごい! 2か月前のベータ参加者は50人未満でした。このターミナルプロジェクトに関心を持ってくれたこと、そして参加してくれているベータテスターには本当に感謝しています。これだけ大規模で、しかも増え続けているテスターグループがいれば、一般公開に至る頃にはGhosttyが強固で安定したプロジェクトになっていることは間違いありません。
各回のベータでこれほど多くの参加者を増やせるのは、Ghosttyが機能面でも安定性の面でも、どんどん完成に近づいているからです。以前は5人を招待すると、十数件以上のバグや機能リクエストが寄せられていました。今では、同じくらいの件数に収めるために50人を招待できます。この人数はこれからも増えていくでしょう。このプロジェクトが本当に形になり、とても安定していくのを見るのは、実に満足感があります。
ベータプログラムへの参加に関心がある方は、GhosttyのDiscordに参加して、次回のベータ募集の候補になってください。この記事を書いている時点で、Discordコミュニティのおよそ20%がベータに参加しています。
ターミナルインスペクター(#728)
ターミナルはアプリケーションプラットフォームです。「プラットフォーム」という言葉は、自分の仕事が実際以上に重要だと思いたい人(あるいは、投資家に実際以上に重要だと思わせたい人)が使いすぎているように思いますが、ターミナルは実際にテキストベースの対話操作のためのプラットフォームです1。
ターミナルは、そこで動くアプリケーションがなければ面白くありません。さらに言えば、そこで動くアプリケーションがなければ、ターミナルは無意味です。ターミナルアプリケーションの数と品質を高める方法の一つは、ターミナル向けの開発を簡単にすることです。
ウェブに目を向けると、私にとって開発のしやすさが飛躍的に向上したのは、Firebugが登場したときでした。今では一般に「ウェブインスペクター」などと呼ばれ、同様の機能は主要なブラウザーにすべて搭載されています。これと似た体験をターミナルにも持ち込みたいと思い、Ghosttyにターミナルインスペクターを追加しました。
ターミナルインスペクターはウェブインスペクターと同じように動作します。ターミナルごとに表示されるパネルで、実行中のターミナルに関する情報がリアルタイムで更新されます。キーボード入力(どのようにエンコードされるかも含む)、ターミナルモード、フォントサイズ、グリッドサイズ、セルのメタデータ、パレットカラーなど、さまざまな情報を確認できます。
ターミナルインスペクターの目標は、ターミナル開発者にとって欠かせないツールになることです。Ghosttyだけでなく、あらゆるターミナルで動くターミナルアプリケーションを、より簡単に開発・デバッグできるようにします。
ターミナルインスペクターは、まだごく初期段階の非常に実験的な機能です。現在は完全な読み取り専用インターフェースですが、将来的には読み書き可能にする予定です。セルやターミナルモードを変更したり、合成入力イベントを生成したり、その他さまざまな操作ができるようにしたいと考えています。
ターミナルインスペクターの元となるアイデアは、ベータコミュニティのメンバーから出たものでした。その後、私を含むベータコミュニティ内の小さなグループがすぐに動き出し、これを本当に実用的なアイデアへと育てました。関わってくれた皆さん、ありがとうございます!
アジア言語入力(#八百八十八)
最近のベータ募集では、より多様なタイムゾーンの人を招待することを明確に意識しました。その結果、中国語、日本語、韓国語などの言語を入力するテスターが大幅に増えました。これらのテスターから、アジア言語の入力とレンダリングに関する問題が十数件近く報告されました。その結果、Ghosttyはこれらの言語で非常によく動作するようになりました。
開発ログ003では、キーボード入力について「キーボード入力処理はあなたを嫌っている」というタイトルの節を設けました。Ghosttyではどれほどうまく動くかについて大口を叩いたわけですが、今回は、すべてがどれほどひどく複雑なのかについてさらに強調し、そしてもう一度、Ghosttyはすべてを本当にうまく処理すると言わせてください2。
より複雑な入力状態
開発ログ003では、デッドキー状態という概念を紹介しました。当時のGhosttyが処理できたデッドキー状態は、単一のコードポイントに対するものだけでした。例として、アクセント付きの英字を使いました。その例では、'(アポストロフィ)を入力してからaのような文字を入力すると、áが得られます。
日本語などの言語では、いくつかの文字を入力すると候補が表示されます(候補がドロップダウンでさらに表示されることもあります)。そしてEnterやTabなどのキーを押すと、その候補を確定できます。
Ghosttyは複数のコードポイントからなる候補を処理できず、候補が表示されている間にEnterやTabなどのキーを誤って処理していました。これらはすべて修正され、今では日本語(その他の言語も)を入力できます。
この複数コードポイントの候補状態によって、行末で入力する場合や、幅が狭すぎるウィンドウで入力する場合にも、いくつかのエッジケースが生じました。これらもGhosttyで処理できるようになっています。上の動画は別のバグが修正される前に録画されたものなので、(見つけられるなら)誤りが残っていることに気づくでしょう。しかし、それも今では解決済みです。
中国語文字の位置合わせ(#982)
複数のフォント(さらに絵文字も)を、見た目に整合性のあるきれいな形で等幅ターミナルのグリッドに描画するのは難しい課題です。中国語の文字は、あまり適切に表示されていませんでした。

草で始まる単語が少し下に表示されているのがわかります。これは、特定のフォントを混在させたときに、フォントメトリクスの計算(この場合はセルのベースライン)を誤って使っていたことが原因でした。これはGhosttyで修正済みです。

LinuxのIME入力(#919)
macOSには、入力メソッドエディター(IME)の優れたサポートがOSに組み込まれています。GTKを使うLinuxでは、IMEは任意でインストールするプラグインによって提供されます。そのためGhosttyでのテストが十分ではなく、中国語、日本語、韓国語ではまったく動作していませんでした。
幸い、Ghosttyの共有コアでIMEをサポートするために多くの作業をしていたので、Linuxで正しく動作させるために必要だったのは、適切なGTK APIとGhostty APIをつなぎ合わせるための+47/-1という差分だけでした。その結果、LinuxでもIMEが動作するようになりました。
注:この動画は上記の修正前に録画されたものなので、文字が誤って描画されている様子を確認できます。
カスタムシェーダー(#903)
ターミナルを昔ながらのCRTのように見せたいと思ったことはありませんか? あるいは、壊れたVHSテープのようにしたいと思ったことは? 何を言っているのかって? 正気を失ったのかって? とにかく、Ghosttyではカスタムシェーダーを指定して、こうしたことができるようになりました。
実用性はさておき、こういう機能はバッテリーをひどく消費しそうに見えます。現代のソフトウェアの大半が持つ一般的な非効率さは、私たち全員を馬鹿にしています! CPUもGPUも超高速で、これはその性能をほとんど使っていません。私のマシンでは、上のエフェクトが使うのはCPU約1%、GPU約2%です。この機能を使わない場合より電力を多く使うのは確かです(もちろん!)が、ファンが回り出したりするほどではありません。
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などの対象形式に変換します。これら2つのツールは、公開されているC APIを使ってコンパイルし、バインドしています。
この機能のもう一つの非常にクールな点は、GhosttyがShadertoyのインターフェースを公開していることです。そのため、多くのShadertoyシェーダーを変更なしでGhosttyに持ち込めます。さらに重要なのは、ShadertoyそのものをGhosttyのカスタムシェーダー用のライブでインタラクティブな開発ツールとして使えることです!
ご安心ください。この機能がパフォーマンスに悪影響を与えることはありません。Ghosttyはマルチスレッドの描画アーキテクチャを採用しており、フレーム間には十分なアイドル時間があります。カスタムシェーダーを使うとアイドル時間は減りますが、他のスレッド(I/OやGUI)への影響はほとんど、あるいはまったくありません。カスタムシェーダーを使わない場合、Ghosttyはこれまでと同じ描画パイプラインを使い、既存の実行に新しいリソースを追加することもありません(カスタムシェーダーの有無を確認する1回のブール値チェックと、カスタムシェーダーの空リストを表現するためのごくわずかなメモリ使用量を除きます)。
わかった。でも、これは完全に無意味なんじゃないの? 最も一般的な用途は楽しむことです。もちろん、そんなものは必要ありません(そうだ、楽しさなんてくそくらえ、ですよね?)。しかし、カスタムシェーダーの主な実用的用途はアクセシビリティです。特定の種類の色覚異常に対応したり、コントラストや明るさを調整して読みやすくしたり、「拡大鏡」のような効果を作ったりするのに、カスタムシェーダーは非常に優れた方法です。
アクセシビリティを他の人に丸投げしたいわけではありません。さまざまなアクセシビリティ機能を第一級の機能として実装することにも前向きです。ただ、Ghosttyにまだ特定の機能がない状況で、ユーザー自身が手を入れられる方法として、これはとても良いものです。
xterm互換性の監査と動作ドキュメント(#632)
ターミナルエミュレーターはエミュレーターですが、何をエミュレートしているのでしょうか? 伝統的に、ターミナルエミュレーターはVT52、VT100、VT220などの物理ターミナルをエミュレートしていました。実際には、こうしたハードウェアが広く入手でき、実用に使われていた時代からあまりにも長い時間が経ったため、現代のターミナルエミュレーターの多くは、互いの動作をなんとなく模倣しています。その結果、ターミナルエミュレーターによって動作が微妙に一致しないさまざまな問題が生じ、多くのターミナルエミュレーターにはエッジケース周辺のバグがあります3。
xtermはX Window Systemの標準ターミナルエミュレーターであり、歴史的なターミナルの動作における金字塔として、非常によく引き合いに出されます。さらに、xtermは十分に広く使われているため、歴史的なターミナルを考慮しない場合でも、xtermがサポートする機能については、その動作を事実上の標準とみなせます。
そこで、可能かつ妥当な限り、Ghosttyはxtermの動作に正確に合わせるべきだと決めました。これにより、「なぜ<feature>はこのように動くのか?」という問いに対して、プロジェクトとして一貫した答えを出せます4。
「可能かつ妥当な限り」とはどういう意味でしょうか? 機能を実装するときは、デフォルトではxtermに合わせるべきだという意味です。ある機能についてバグが報告されたら、まず「この状況でxtermはどう動くのか?」と確認します。xtermの動作から逸脱する説得力のある理由があるなら、それは例外であって、通常の方針ではありません。
そのため、xtermに記載されているすべての機能を少しずつ監査し、Ghosttyと比較し始めました。その過程で、Ghostty独自のドキュメントも整備しています。できる限り詳細にするよう努めています。このドキュメントには、期待される出力を記載したシェルスクリプトの検証ケースも含まれているため、互換性を確かめるエンドツーエンドテストを書けます。次のようなものです。

ターミナルは多くの機能をサポートしており、xtermのコードベースは複雑です。この作業はとても退屈なので、一晩で終わるものではありません。しかしここ数か月、機能を一つずつ少しずつ確認してきた結果、これまでにGhosttyで数十件のバグを修正し、他のターミナルでは数十件のバグを発見しました(報告済みのものもあれば、後で報告するものもあります。重大なものはありません)。
これは、Ghosttyがxtermのサポートするすべての機能をサポートするという意味ではありません。Ghosttyが持っていて、かつxtermもサポートしている機能について、Ghosttyはxtermとの最大限の互換性を目指すということです(十分な理由がある場合は例外を認めます)。
おわりに
開発ログでは、興味深く、共有したいと思った変更をいくつか取り上げています。開発ログは変更履歴ではありませんし、退屈な変更点の羅列だけにはしたくありません。その一方で、この2か月の間にGhosttyプロジェクトでは100件を超えるバグ修正と改善が行われ、Ghosttyは一般公開に向けて日々一歩ずつ近づいていることも、ここでお伝えしておきたいと思います。
ベータの成長に伴い、コントリビューターの数も増えました。Ghosttyにはこれまでに50人近くが貢献しています(ベータテスターのほぼ6人に1人が、バグを報告するだけでなくコードも提供しているのです!)。これは本当に素晴らしいことで、プロジェクトに時間を割き、関心を持ってくれていることに心から感謝しています。
最新情報を追いたい方は、TwitterまたはMastodonで私をフォローしてください(リンクはフッターにあります)。このブログにはRSSフィードもあります。
ばあ。👻
脚注
投資家を探しているわけではありません。この段落をそのように受け取る人はいないと思いますが、言っておく必要がある気がしました。それに、これは「探していないと言いつつ実は探している」という意味の発言でもありません。本当に関心がないのです。↩
入力処理は複雑で、まだバグが残っていることは間違いありません。ただ、今では日本語、韓国語、中国語を話すベータテスターがGhosttyを常用できる状態になっています。↩
ほぼすべてのターミナルエミュレーターは、
草のような全角文字をエスケープシーケンスが分割した場合に、正しく処理できません。ここでいう「正しく」には議論の余地があります。仕様が存在しないので、好きなようにしてよいとも言えます。別の言い方をすれば、動作はあまりにも一貫していません。↩もちろん、これはxtermが実装している機能に限った話です。Kitty Graphics Protocolのように、Kittyによって明確に定義されている機能もあります。その場合は、可能な限り正確にKittyに合わせるようにしています。↩
記事をランダムに読む