libghosttyがやってくる
原文は Mitchell Hashimoto により に公開されました。 このブログを購読する
2年以上前、Ghosttyについて語った初期の公開トークのひとつで、私はlibghosttyのビジョンを語りました。あらゆるアプリケーションが、完全に機能するモダンで高速なターミナルエミュレータを自らに組み込める、埋め込み可能なライブラリという構想です。libghosttyはようやく形になり始めており、その計画の詳細を共有できることを嬉しく思います。
最初のlibghosttyライブラリはlibghostty-vtになります。ターミナルシーケンスの解析とターミナル状態の維持のためのAPIを提供する、依存関係ゼロのライブラリで、Ghosttyの実戦で証明されたコアから直接抽出されたものです。libcすら必要としません!
免責事項:この投稿は主にlibghosttyのロードマップの更新であり、最初に出荷可能になるコンポーネントの発表です。Zig APIは現在テスト用に利用可能ですが、C APIはまだ準備ができておらず、間もなく公開予定です。いずれの場合も、初期のテスト段階の品質であり、一般的な利用にはまだ適していません。
なぜlibghosttyなのか
まずは、なぜ私がlibghosttyが必要だと考えているのか、その背景から始めましょう。
何百ものプログラムが、何らかの形でターミナルエミュレーションを実装しています。最もわかりやすいのは、Ghostty、Kitty、iTerm2などの汎用ターミナルエミュレータそのものです。しかし、tmuxやzellijのようなターミナルマルチプレクサも、完全なターミナルエミュレータなのです!1 エディタも独自のターミナルエミュレータを組み込んでいます。例えば、JetBrains製品向けのjediterm、VS Code向けのXterm.js、Alacrittyを組み込んだZedなどです。
完全に機能するターミナルエミュレータに加えて、多くのウェブサイトやアプリケーションが、ログやコマンド出力を表示するために読み取り専用のターミナルエミュレーションを実装しています。例えば、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はintermediatesを正しく扱えていません。そのため、この記事の執筆時点では、広くサポートされている「カーソル形状を変更する」シーケンスが、すべてのJetBrainsエディタで1文字を飲み込んでしまう原因となっています。
スタイルのみの解析については、多くの開発者が完全な状態遷移図をスキップします。代わりに軽くウェブ検索をし、\e[31や\e[41mのような単純なANSIシーケンスだけを解析して「色対応」を謳います。しかし、スタイルのみのシーケンスはそれよりもはるかに複雑で、例えばRGBをサポートしていますが、そのRGB自体が十数種類もの形式を取り得ます。そして、この複雑なスタイルシーケンスを正しくレンダリングするウェブコンソールを、私は未だに一つも見つけられていません。5
libghostty-vtは、これらすべてを解決することを目指しています。
libghostty-vtはGhosttyから抽出されたもので、実世界でのあらゆる利点を受け継いでいます。SIMD最適化された解析、非常に優れたUnicodeサポート、高度に最適化されたメモリ使用量、ファズテストとValgrindテストによって堅牢化されたコードベース、Kitty Graphics ProtocolやTmux Control Modeの解析といった優れた機能互換性などです。
これらすべてが、依存関係ゼロ(libcにすら依存しない)の単一のC APIにパッケージ化されており、あらゆる人気のある言語エコシステムに簡単に組み込めるようになっています。
フットプリントが最小限であるため、libghostty-vtは幅広い移植性を備えることになります。初期ターゲットは、Ghosttyアプリケーションの主要ターゲットであることから、macOSとLinuxのx86_64とaarch64アーキテクチャになります。しかし、Windows、組み込みデバイス、WASMによるウェブなど、さらなるターゲットへの対応拡大も計画しています。libghosttyは対象範囲がより絞られているため、GUIとしての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とは別にバージョン管理する予定です。このブログ投稿はパブリックアルファ(APIの安定性は保証しません)を示すもので、C APIの準備ができ次第、一部の開発者に使ってもらい、やがて言語バインディングを書いてもらうきっかけになることを期待しています。
今後6ヶ月以内にlibghostty-vtのタグ付きバージョンをリリースしたいと考えていますが、準備が整うかどうかにかかっています。
フィードバックを求めています
私たちは今、libghosttyのAPIを設計するという極めて重要な段階にいます。そしてAPIを設計する最良の方法は、実際の利用者からのフィードバックを得ることです。Ghosttyは一つの利用者であり、他にもコミュニティメンバーがlibghosttyを利用するプロジェクトに取り組んでいますが、できるだけ多くの声が必要です!
ご自身のプロジェクトや組織でlibghosttyのユースケースが思い浮かぶ方は、ぜひGhostty Discordに参加して、この開発に取り組む開発者たちと協力してください。Discordへの参加を希望されない場合は、私にメールでご連絡ください(メールアドレスはこのウェブサイトのフッターにあります)。
現段階のlibghosttyの状態はアルファとお考えください。そのため、洗練された安定した体験は期待しないでください。私たちは、初期段階から関わりたいハッカーを求めています。
「アルファ」品質というのは、API(関数や型)自体についての話です。コアロジックはGhosttyと共有されており、極めて安定し、実世界で証明されています。
次なるフロンティア
アプリケーションとしてのGhosttyが、ようやくlibghosttyという目標に向けて動き出せるほどの安定性に達したことを、とても嬉しく思っています。libghosttyはGhosttyにとって次なるフロンティアであり、スタンドアロンのアプリケーションとしてのGhostty自体よりも、はるかに大きなインパクトを与える可能性を秘めていると考えています。
ご安心ください。アプリケーションとしてのGhosttyにもまだたくさんの変更が控えており、これらがGhosttyに対する私の熱意や計画を損なうことはありません。libghosttyがより広く使われることで、Ghosttyアプリケーション自体もより高機能で安定したものになるのです。Ghostty自体がlibghosttyの利用者なのですから。
Boo. 👻
脚注
これらは子プロセスに対してptyを所有し、すべてのエスケープコードを解析し、画面状態を管理し、最終的には親のターミナルエミュレータに対して独自のエスケープコードを出力することで「レンダリング」します。↩
多くのウェブサイトではXterm.jsが使われており、GTKエコシステムにはlibvteがあります。しかし、これらは全体のごく一部をカバーするに過ぎず、前述の例のそれぞれも独自のスコープに限定されています。↩
私はターミナルエミュレーションに3年近く取り組んできましたが、今でも奇妙なエッジケースが見つかっています。↩
実際に影響のあった問題の例をいくつか挙げます。Jeditermはintermediatesを正しく処理できていませんでしたし、AppleのTerminal.appはDCSシーケンスをそのまま出力に漏れ出させてしまいます。特定の誰かを非難したいわけではなく、こうした問題が存在し、ターミナルエミュレーションを正しく行うことがいかに難しいかを示したいだけです。↩
多くの汎用ターミナルエミュレータもこれを誤っており、わずか9ヶ月前のGhosttyもその一つでした。↩
記事をランダムに読む
コメント
ログインしてコメントする