Cursive
GitHub概要
gyscos/cursive
A Text User Interface library for the Rust programming language
スター4,576
ウォッチ37
フォーク256
作成日:2015年5月9日
言語:Rust
ライセンス:MIT License
トピックス
ncursesrustterminaltui
スター履歴
データ取得日時: 2025/7/25 11:09
Cursive
Cursiveは、Rust向けの高レベルTUIフレームワークです。リテインドモードのアーキテクチャを採用し、ビューベースの直感的なAPIで複雑なターミナルアプリケーションを簡単に構築できます。使いやすさを重視しながらも、柔軟性を保つ設計が特徴です。
特徴
リテインドモードアーキテクチャ
- ビューシステム: 階層的なビュー構造
- イベントループ: フレームワークが管理
- 状態管理: ビューが内部状態を保持
- 自動レイアウト: 柔軟なレイアウトシステム
宣言的UI設計
- コールバック駆動: イベントに対する反応を定義
- 構造の定義: ビューの階層を明確に記述
- フォーカス管理: 自動的なフォーカス処理
- 入力処理: キーボード・マウス入力の抽象化
豊富なビューコンポーネント
- 基本ビュー: TextView、EditView、Button、Checkbox
- コンテナ: LinearLayout、StackView、Dialog
- リスト系: ListView、SelectView、MenuPopup
- 特殊ビュー: ProgressBar、SliderView、PaddedView
柔軟なバックエンド
- crossterm: クロスプラットフォーム対応
- termion: Unix系システム向け
- pancurses: ncurses/pdcursesラッパー
- ダミーバックエンド: テスト用
基本的な使用方法
インストール
[dependencies]
cursive = "0.21"
Hello World
use cursive::views::{Dialog, TextView};
fn main() {
// Cursiveルートを作成
let mut siv = cursive::default();
// ダイアログを作成
siv.add_layer(Dialog::around(TextView::new("Hello World!"))
.title("My App")
.button("Quit", |s| s.quit()));
// イベントループを実行
siv.run();
}
入力フォーム
use cursive::views::{Dialog, EditView, LinearLayout, TextView};
use cursive::traits::*;
fn main() {
let mut siv = cursive::default();
siv.add_layer(
Dialog::new()
.title("User Form")
.content(
LinearLayout::vertical()
.child(TextView::new("Name:"))
.child(EditView::new()
.on_submit(submit_name)
.with_name("name")
.fixed_width(20))
.child(TextView::new("Email:"))
.child(EditView::new()
.with_name("email")
.fixed_width(20))
)
.button("Submit", |s| {
let name = s.call_on_name("name", |view: &mut EditView| {
view.get_content()
}).unwrap();
let email = s.call_on_name("email", |view: &mut EditView| {
view.get_content()
}).unwrap();
s.add_layer(
Dialog::text(format!("Name: {}\nEmail: {}", name, email))
.title("Submitted")
.button("Ok", |s| s.pop_layer())
);
})
.button("Cancel", |s| s.quit())
);
siv.run();
}
fn submit_name(s: &mut cursive::Cursive, name: &str) {
s.add_layer(
Dialog::text(format!("Hello, {}!", name))
.button("Ok", |s| s.pop_layer())
);
}
メニューと選択
use cursive::views::{Dialog, SelectView};
use cursive::traits::*;
fn main() {
let mut siv = cursive::default();
let mut select = SelectView::new()
.h_align(cursive::align::HAlign::Center)
.autojump();
select.add_all_str(vec!["Option 1", "Option 2", "Option 3"]);
select.set_on_submit(|s, item| {
s.add_layer(
Dialog::text(format!("You selected: {}", item))
.button("Ok", |s| s.pop_layer())
);
});
siv.add_layer(
Dialog::around(select.scrollable().fixed_size((20, 10)))
.title("Select an option")
);
siv.run();
}
高度な機能
カスタムビュー
use cursive::{Printer, Vec2, View};
pub struct MyView {
content: String,
}
impl View for MyView {
fn draw(&self, printer: &Printer) {
printer.print((0, 0), &self.content);
}
fn required_size(&mut self, _constraint: Vec2) -> Vec2 {
Vec2::new(self.content.len(), 1)
}
fn on_event(&mut self, event: cursive::event::Event) -> cursive::event::EventResult {
match event {
cursive::event::Event::Key(cursive::event::Key::Enter) => {
// Handle Enter key
cursive::event::EventResult::Consumed(None)
}
_ => cursive::event::EventResult::Ignored,
}
}
}
テーマとスタイル
use cursive::theme::{BaseColor, BorderStyle, Palette, Theme};
use cursive::views::Dialog;
fn main() {
let mut siv = cursive::default();
// カスタムテーマを作成
let mut theme = Theme::default();
theme.shadow = false;
theme.borders = BorderStyle::Simple;
theme.palette[Palette::Background] = BaseColor::Blue.dark();
theme.palette[Palette::View] = BaseColor::Black.light();
theme.palette[Palette::Primary] = BaseColor::White.light();
siv.set_theme(theme);
siv.add_layer(
Dialog::text("Themed application")
.title("Custom Theme")
.button("Quit", |s| s.quit())
);
siv.run();
}
複雑なレイアウト
use cursive::views::{
Dialog, EditView, LinearLayout, ListView, Panel,
ResizedView, ScrollView, TextView
};
use cursive::traits::*;
fn main() {
let mut siv = cursive::default();
let layout = LinearLayout::vertical()
.child(Panel::new(
ScrollView::new(
TextView::new("Long text...\n".repeat(20))
).scroll_x(true)
).title("Scrollable Panel"))
.child(ListView::new()
.child("Item 1", TextView::new("Content 1"))
.child("Item 2", TextView::new("Content 2"))
.child("Item 3", EditView::new())
.delimiter()
.child("Item 4", TextView::new("Content 4"))
);
siv.add_layer(
Dialog::around(ResizedView::with_fixed_size((50, 20), layout))
.title("Complex Layout")
.button("Ok", |s| s.quit())
);
siv.run();
}
エコシステム
実例プロジェクト
- RustyChat: RustとCursiveで作られたチャットクライアント
- checkline: stdinからstdoutへのチェックボックスラインピッカー
- clock-cli: ストップウォッチとカウントダウンタイマー機能を持つ時計
- fui: JSONフォームの定義からUIを生成
拡張ライブラリ
- cursive-tabs: タブビューの実装
- cursive-tree-view: ツリービューの実装
- cursive-async-view: 非同期コンテンツ表示
- cursive-table-view: テーブルビューの実装
設計原則
- 使いやすさ: シンプルなアプリはシンプルに、複雑なアプリも管理可能に
- Linux TTY互換性: 色やUTF-8は制限されるかもしれないが、ほとんどの機能はLinux TTYで動作
- 柔軟性: シンプルなUIスクリプトから複雑なリアルタイムアプリ、ゲームまで対応
利点
- 高レベルAPI: 複雑な詳細を抽象化
- 豊富なビュー: 多様な組み込みコンポーネント
- イベントループ管理: フレームワークが処理
- テーマサポート: カスタマイズ可能な外観
- マルチバックエンド: 様々な環境に対応
制約事項
- パフォーマンス: リテインドモードのため、特定のケースでは非効率
- 学習曲線: 独自のビューシステムを理解する必要
- カスタマイズ: 高度なカスタマイズは複雑
- グラフィックス: テキストベースのみ
他のライブラリとの比較
項目 | Cursive | Ratatui | tui-realm |
---|---|---|---|
レンダリング | リテインド | イミディエート | コンポーネント |
APIレベル | 高 | 中 | 高 |
学習コスト | 低〜中 | 中 | 中〜高 |
柔軟性 | 中 | 非常に高 | 高 |
組み込み機能 | 豊富 | 中 | 中 |
まとめ
Cursiveは、使いやすさを重視したRust TUIフレームワークです。リテインドモードのアーキテクチャにより、複雑なレイアウトやインタラクションを簡単に実装できます。特に、迅速なプロトタイプ開発や、フォームやメニューを多用するアプリケーションに適しています。