Crossterm

TerminalCross-platformLow-levelBackendAsync

GitHub概要

crossterm-rs/crossterm

Cross platform terminal library rust

スター3,649
ウォッチ23
フォーク307
作成日:2018年1月3日
言語:Rust
ライセンス:MIT License

トピックス

colorconsolecross-platformcursorinputterminaltui

スター履歴

crossterm-rs/crossterm Star History
データ取得日時: 2025/7/25 11:09

Crossterm

Crosstermは、Rustで最も人気のあるクロスプラットフォーム対応ターミナル操作ライブラリです。Windows、macOS、Linuxで一貫したAPIを提供し、ターミナルの制御、カーソル移動、色付け、キー入力の取得などの低レベル操作を簡単に実行できます。多くのTUIライブラリのバックエンドとして採用されています。

特徴

クロスプラットフォーム対応

  • Windows: Windows Console API使用
  • Unix系: ANSI エスケープシーケンス使用
  • 統一API: プラットフォーム差異を吸収
  • 自動検出: 環境に応じた最適な実装選択

豊富な機能

  • カーソル制御: 移動、表示/非表示、スタイル変更
  • スタイリング: 色、属性(太字、斜体、下線など)
  • 端末制御: クリア、スクロール、サイズ変更
  • イベント処理: キーボード、マウス、リサイズイベント
  • 画面バッファ: 代替画面バッファのサポート

非同期サポート

  • async/await: 非同期イベント読み取り
  • ノンブロッキング: イベントポーリング
  • タイムアウト: イベント待機のタイムアウト設定
  • 統合: Tokio、async-stdとの互換性

パフォーマンス

  • 効率的: 最小限のオーバーヘッド
  • バッファリング: 出力のバッチ処理
  • 最適化: プラットフォーム固有の最適化
  • 軽量: 小さなバイナリサイズ

基本的な使用方法

インストール

[dependencies]
crossterm = "0.27"

基本的な出力

use std::io::{stdout, Write};
use crossterm::{
    execute,
    style::{Color, Print, ResetColor, SetBackgroundColor, SetForegroundColor},
    ExecutableCommand, Result,
};

fn main() -> Result<()> {
    // 色付きテキストの出力
    execute!(
        stdout(),
        SetForegroundColor(Color::Red),
        SetBackgroundColor(Color::Blue),
        Print("Hello, Crossterm!"),
        ResetColor
    )?;
    
    Ok(())
}

カーソル操作

use crossterm::{
    cursor::{Hide, MoveTo, Show},
    execute,
    terminal::{Clear, ClearType},
    Result,
};
use std::io::stdout;

fn main() -> Result<()> {
    let mut stdout = stdout();
    
    // カーソルを非表示にして移動
    execute!(
        stdout,
        Hide,
        Clear(ClearType::All),
        MoveTo(10, 5),
        Print("Cursor at (10, 5)"),
        Show
    )?;
    
    Ok(())
}

イベント処理

use crossterm::{
    event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
    Result,
};
use std::io;

fn main() -> Result<()> {
    // ターミナルをrawモードに設定
    enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    
    loop {
        // イベントを読み取る
        if event::poll(std::time::Duration::from_millis(100))? {
            match event::read()? {
                Event::Key(key) => {
                    match key.code {
                        KeyCode::Char('q') => break,
                        KeyCode::Char(c) => println!("Pressed: {}", c),
                        KeyCode::Enter => println!("Enter pressed"),
                        _ => {}
                    }
                }
                Event::Mouse(mouse) => {
                    println!("Mouse event: {:?}", mouse);
                }
                Event::Resize(width, height) => {
                    println!("Terminal resized to {}x{}", width, height);
                }
                _ => {}
            }
        }
    }
    
    // クリーンアップ
    disable_raw_mode()?;
    execute!(stdout, LeaveAlternateScreen, DisableMouseCapture)?;
    
    Ok(())
}

非同期イベント処理

use crossterm::{
    event::{self, Event, KeyCode},
    Result,
};
use futures::{future::FutureExt, StreamExt};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<()> {
    let mut reader = event::EventStream::new();
    
    loop {
        let event = reader.next().fuse();
        
        tokio::select! {
            maybe_event = event => {
                match maybe_event {
                    Some(Ok(event)) => {
                        match event {
                            Event::Key(key) if key.code == KeyCode::Char('q') => break,
                            Event::Key(key) => println!("Key: {:?}", key),
                            _ => {}
                        }
                    }
                    Some(Err(e)) => eprintln!("Error: {}", e),
                    None => break,
                }
            }
            _ = tokio::time::sleep(Duration::from_secs(1)) => {
                println!("Tick");
            }
        }
    }
    
    Ok(())
}

高度な機能

スタイリング

use crossterm::{
    style::{
        Attribute, Color, ContentStyle, Print, PrintStyledContent,
        Stylize, StyledContent,
    },
    execute,
    Result,
};
use std::io::stdout;

fn main() -> Result<()> {
    // スタイル付きテキスト
    let styled = "Bold and Red"
        .with(Color::Red)
        .on(Color::Yellow)
        .attribute(Attribute::Bold);
    
    execute!(
        stdout(),
        PrintStyledContent(styled),
        Print("\n"),
        PrintStyledContent("Underlined".underlined()),
        Print("\n"),
        PrintStyledContent("Italic".italic()),
        Print("\n"),
        PrintStyledContent("Crossed out".crossed_out())
    )?;
    
    Ok(())
}

画面バッファ管理

use crossterm::{
    execute,
    terminal::{EnterAlternateScreen, LeaveAlternateScreen},
    Result,
};
use std::{io::stdout, thread, time::Duration};

fn main() -> Result<()> {
    let mut stdout = stdout();
    
    // 代替画面に切り替え
    execute!(stdout, EnterAlternateScreen)?;
    
    // 代替画面で作業
    execute!(stdout, Print("This is the alternate screen"))?;
    thread::sleep(Duration::from_secs(2));
    
    // 元の画面に戻る
    execute!(stdout, LeaveAlternateScreen)?;
    
    Ok(())
}

カスタムコマンド

use crossterm::{Command, ExecutableCommand, QueueableCommand};
use std::io::{stdout, Write};

// カスタムコマンドの定義
struct MyCustomCommand {
    content: String,
}

impl Command for MyCustomCommand {
    fn write_ansi(&self, f: &mut impl std::fmt::Write) -> std::fmt::Result {
        // ANSIエスケープシーケンスを書き込む
        write!(f, "\x1b[1m{}\x1b[0m", self.content)
    }
}

fn main() -> crossterm::Result<()> {
    let mut stdout = stdout();
    
    // カスタムコマンドの実行
    stdout.execute(MyCustomCommand {
        content: "Bold custom text".to_string(),
    })?;
    
    Ok(())
}

エコシステム

Crosstermを使用するライブラリ

  • Ratatui: 人気のTUIライブラリ
  • tui-rs: TUIライブラリ(メンテナンス終了)
  • Cursive: 高レベルTUIフレームワーク
  • Termion: 代替の低レベルライブラリ

関連ツール

  • crossterm-winapi: Windows API バインディング
  • crossterm-cursor: カーソル操作専用
  • crossterm-style: スタイリング専用

プラットフォーム固有の注意点

Windows

  • Windows 10以降でANSIサポート
  • レガシーコンソールでは一部機能制限
  • ConPTY対応で改善された互換性

macOS/Linux

  • ほぼすべての機能が利用可能
  • ターミナルエミュレータに依存する機能あり
  • SSH経由でも動作

利点

  • 真のクロスプラットフォーム: 主要OSすべてで動作
  • 豊富な機能: ターミナル操作に必要なすべて
  • 高パフォーマンス: 効率的な実装
  • 活発な開発: 継続的な改善とサポート
  • 優れたドキュメント: 詳細な例とガイド

制約事項

  • 低レベル: TUI構築には追加の抽象化が必要
  • ターミナル依存: 一部機能はターミナルに依存
  • 学習曲線: 多くのAPIと概念
  • プラットフォーム差異: 完全な統一は困難

他のライブラリとの比較

項目CrosstermTermionPancurses
プラットフォーム全OSUnix系のみ全OS
依存関係少ないゼロncurses
非同期サポート限定的なし
API高レベル低レベル中レベル
活発さ非常に活発停滞気味中程度

まとめ

Crosstermは、Rustでターミナル操作を行うための最も完成度の高いライブラリです。クロスプラットフォーム対応、豊富な機能、優れたパフォーマンスを提供し、多くのTUIライブラリのバックエンドとして信頼されています。低レベルのターミナル制御が必要な場合や、独自のTUIフレームワークを構築する場合に最適な選択です。