現在のターミナルユーザーインターフェース(TUI)では、パネルやボタンを区切る境界線がテキスト文字として扱われるため、かなりの画面スペースが犠牲になることがよくあります。各文字がセル全体を占有するため、ネストされたレイアウトでは、装飾のためだけに垂直方向に6〜8行のスペースを簡単に失ってしまうことがあります。Ghosttyのフォークで現在実装されている新しいターミナルプロトコルは、境界線を背景色と同様のセル属性として扱うことでこの問題を解決します。これにより、境界線は文字スロットを占有することなくセルの端に配置できるようになります。

ボックス描画文字の限界

標準的なターミナル境界線はUnicodeのボックス描画ブロックに依存しています。これらはテキストグリフであるため、グリッドの行または列全体を占有する必要があります。これにより、テキストがパネルの端にぴったりと配置できない「パディング」効果が生じ、ネストされた境界線の数が増えるにつれて複雑なレイアウトが窮屈になってしまいます。

標準的なボックス描画文字を使用してレンダリングされたターミナルインターフェースのデモ
標準的なボックス描画文字を使用してレンダリングされたタイル型ウィンドウマネージャのデモ。テキストベースの境界線が空間を消費する性質を示しています。www.joshka.net

この画像は、セル全体を占有しパディングの問題を引き起こす現在の標準的なボックス描画文字の使用法を示しています。

空間の制約だけでなく、ボックス描画文字には美的および機能的な制限もあります。例えば、両方のセルにコンテンツが含まれている場合にその間に線を引くことが難しく、余分なパディングを追加せずにテキストフィールドの下線を引くことが困難です。さらに、TUIからテキストをコピーすると、これらのボックス文字がクリップボードに「ジャンク」データとして含まれてしまうことがよくあります。

「境界線は問題の一部です。それらはスペースを占有しなければならないため、人々が構築したいパネルの一部になってしまうのです。」

— Terminal borders that don't cost a cell | Joshka.net

セル境界の仕組み

新しいプロトコルでは、セル境界をセル自体のプロパティとして扱います。各セルは最大12個の線分を保持でき、これはその4つの辺のそれぞれを構成する2つの半分と、中心から伸びる4つのアームを表します。ターミナルはこれらの線分をグリッド上にレンダリングする役割を担い、特定の色、幅、および実線、二重線、破線、点線などのスタイルを適用できます。

新しいセル境界プロトコルを使用したタイル型ウィンドウマネージャのデモ
新しいセル境界プロトコルを使用して、文字空間を消費せずにペイン、タブ、ボタンをレンダリングするタイル型ウィンドウマネージャのデモ。www.joshka.net

この画像は、複雑なタイル型ウィンドウマネージャのレイアウトにおける新しいプロトコルの実用的な応用を示しています。

重なり合う線を処理するために、プロトコルは優先順位システムを使用します。隣接する2つのセルが辺を共有する場合、ターミナルは優先度スコア、次にストローク幅、最後に位置(右または下)に基づいて描画する線を選択します。これにより、フォーカスされたペインは、他のパネルに隣接している場合でも完全な外形を維持できます。

このプロトコルはDevice Control String(DCS)形式を使用します。アプリケーションは「ペン」を設定して(背景色と同様に)、その後のテキストの境界スタイルを定義するか、長方形コマンドを使用して既存のセルに境界を適用できます。ターミナルがこのプロトコルをサポートしていない場合、アプリケーションは標準的なボックス描画文字にフォールバックします。

セル境界を使用した下線付きテキストフィールドと角の丸いボタンがあるフォーム
新しいセル境界プロトコルによって可能になった、角の丸いボタンと下線付きテキストフィールドを示すフォームのクローズアップ。www.joshka.net

このビジュアルは、仕組みのセクションで言及された角の丸いコーナーや下線などの美的および機能的な改善を強調しています。

トレードオフと実装

Ghosttyターミナルエミュレータでの実装には、約1,650行のコードが含まれています。各セルには、共有の境界セットテーブルを指す16ビットの境界IDが割り当てられます。これにより効率的なレンダリングが可能になりますが、すべての可能なIDが使用された場合、テーブルは最大10〜15 MBのメモリを占有する可能性があります。ただし、ほとんどのTUIは少数の異なるセットしか必要としません。

メモリと実装規模: Ghostty コード変更 1,650 行; 最大メモリコスト 15 MB
メモリと実装規模joshka.net

HN Digestによる図(joshka.netの報告数に基づく)。数値はソースの表記のまま。

レンダリングのパフォーマンスはスタイルによって異なります。直線は効率的ですが、角の丸いコーナーはアンチエイリアスを実現するために小さなクアッドの行として描画されるため、より多くの処理を必要とします。著者は、このプロトコルが空間の問題を解決する一方で、「半セル」の塗りつぶしについてはまだ完全に解決しておらず、それは別の設計課題として残っていると述べています。

実線、破線、点線を含むさまざまな境界スタイルのギャラリー
プロトコルによってサポートされる実線、二重線、破線、点線を含むさまざまな境界スタイルのギャラリー。www.joshka.net

この画像は、プロトコルがセル属性としてレンダリングできる特定のスタイルと線種を説明しています。

Hacker Newsの読者の反応

  • 代替案: あるコメント投稿者は、既存のテキストセル上に境界線文字を描画するためのより良い方法として、より多くのターミナルエミュレータにオーバーストライクモードを実装することを提案しました。 コメント ↗
  • 懐疑的: あるコメント投稿者は、単に画面スペースを確保するためにターミナルプロトコルを修正するのではなく、より野心的な目標として、完全で情報密度の高いUIフレームワークを作成しなかったのかと疑問を呈しました。 コメント ↗
  • 懐疑的: 別のユーザーは、このプロトコルがtmuxのようなマルチプレクサ上で動作しない理由について懐疑的な見方を示し、それが標準的なセルプロパティであれば、意図通りにレンダリングされるはずだと指摘しました。 コメント ↗
  • 代替案: 一部のユーザーは、SSH経由でHTMLを配信してブラウザに適切なUIをレンダリングさせることで、ターミナルのハックから完全に脱却することを提案しました。 コメント ↗

Hacker Newsのスレッドで出た意見の要約です。事実として検証されたものではありません。 議論の全文を読む ↗