RustでFlexboxとHooksを使ってターミナル向けReact風UIを作る
Rustでコンソールインターフェースを作成したことがあるなら、おそらくRatatuiを使ったことがあるでしょう。優れたライブラリで、多くの有用なユーティリティを支えています。しかし、プロジェクトが数個のボタンを超えると、慣れ親しんだ骨の折れる作業が始まります。rectを使って画面を矩形に手動で分割し、パーセンテージやマージンを計算し、大規模なmatch構文を通じてイベントをスレッドする必要があります。Web開発では、コンポーネントアプローチとFlexboxにすっかり慣れ親しんでいますが、ターミナルではまだ1998年のような書き方をしていることが多いです。
最近、iocraftクレートを発見しました。作者はこの問題を根本的に解決しました。React、SwiftUI、Inkの経験をRustのシステムプログラミングに直接もたらしたのです。
おなじみのコンポーネントモデル
このライブラリはview!マクロを中心に構築されています。JSXや宣言的Swiftに似た構文で要素ツリーを構築します。手動の座標計算は不要です。レイアウトはRustのFlexbox仕様を忠実に実装したtaffyエンジンによって処理されます。
クラシックなHello Worldはこのようになります:
use iocraft::prelude::*;
fn main() {
element! {
View(
border_style: BorderStyle::Round,
border_color: Color::Blue,
) {
Text(content: "Hello, world!")
}
}
.print();
}
TextをBoxコンテナでラップし、青い角丸ボーダーを適用してrender!を呼び出すだけです。結果を標準出力に送信するため、ターミナルをフルスクリーンキャプチャする必要がありません。これはインタラクティブなダッシュボードではなく、整形されたコンソールコマンド出力やログが必要な場合に便利です。
ターミナル内のHooksと状態管理
フロントエンド開発との類似は静的なレイアウトだけではありません。動的インターフェースのために、作者はview!マクロと familiar なライフサイクルフックを追加しました。
以下のコードでは、Counterコンポーネントはuse_state!でローカル状態を保持し、use_effect!でバックグラウンド非同期タイマーを開始します:
use iocraft::prelude::*;
use std::time::Duration;
#[component]
fn Counter(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
let mut count = hooks.use_state(|| 0);
hooks.use_future(async move {
loop {
smol::Timer::after(Duration::from_millis(100)).await;
count += 1;
}
});
element! {
Text(color: Color::Blue, content: format!("counter: {}", count))
}
}
fn main() {
smol::block_on(element!(Counter).render_loop()).unwrap();
}
use_stateの値が変化すると、iocraftは画面の影響を受けた部分を再描画します。エンジン оптимизирует propの受け渡しを最適化します:コンテキストとパラメータは参照渡しされるため、不要なメモリ割り当てや重い構造体のクローン作成は行われません。
ライブラリが実際にできること
組み込みのプリミティブは任意の複雑さのインターフェースを構築するのに十分です。リポジトリの例には、最も一般的なタスクの準備されたレシピが含まれています:
- テキスト入力とフォーカス処理を持つフルスクリーンアプリケーション
- マルチカラム適応テーブル
- バリデーション付きインタラクティブフォーム
- フローティングモーダルウィンドウ付き電卓とオーバーレイ
複雑な要素レイアウトが実際にどのように見えるか見てみましょう:
スタイリングはクロスプラットフォームです。アプリケーションは標準的なLinux/macOSターミナルとWindows PowerShellの両方で同様に正しくレンダリングされます。
Ratatuiから乗り換える価値はあるか
Ratatuiで書かれた複雑なターミナルクライアントがすでにあれば、ゼロから書き直す理由はあまりありません。Ratatuiはより成熟しており、大きなコミュニティと多くのサードパーティウィジェットが存在します。
ただし、新しいCLIユーティリティを作成する場合や、チーム向けの内部ツールを書く場合、またはターミナル行と列を手動でカウントすることに疲れている場合は、iocraftが多くの時間を節約できます。宣言的構文はコードをよりコンパクトにし、Flexboxはウィンドウサイズ変更の頭痛を取り除くことができます。
プロジェクトはMIT / Apache-2.0の二重ライセンスで配布されています。docs.rsのドキュメントは十分に詳細で、リポジトリの例示ソースコードは独自のコンポーネントを構築する方法を示しています。
関連プロジェクト