Termion

TerminalUnixLow-levelZero-depsLightweight

GitHub概要

redox-os/termion

Mirror of https://gitlab.redox-os.org/redox-os/termion

スター2,143
ウォッチ27
フォーク115
作成日:2016年3月6日
言語:Rust
ライセンス:MIT License

トピックス

rustterminalttytui

スター履歴

redox-os/termion Star History
データ取得日時: 2025/7/25 11:09

Termion

Termionは、Unix系システム向けのゼロ依存ターミナル制御ライブラリです。純粋Rustで書かれており、外部依存なしで動作します。Redox OSプロジェクトの一部として開発され、軽量かつ高速なターミナル操作を実現します。

特徴

ゼロ依存

  • 純粋Rust: Cライブラリへの依存なし
  • 軽量: 最小限のバイナリサイズ
  • シンプル: 必要最小限の機能に特化
  • 高速: オーバーヘッドが少ない

低レベルAPI

  • Rawモード: ターミナルのrawモード切り替え
  • ANSIエスケープ: 直接的なANSIシーケンス操作
  • カーソル制御: カーソルの移動、表示/非表示
  • 色・スタイル: 256色、RGB、属性設定

イベント処理

  • キー入力: 同期/非同期キー入力
  • マウスサポート: 基本的なマウスイベント
  • ターミナルサイズ: ターミナルサイズの取得
  • シグナル: Unixシグナルの処理

シンプルな設計

  • 直感的API: Unixターミナルの概念に沿った設計
  • マクロ: よく使う操作の簡略化
  • 型安全: Rustの型システムを活用
  • エラー処理: Result型によるエラーハンドリング

基本的な使用方法

インストール

[dependencies]
termion = "4.0"

Hello World

use termion::{color, style};

fn main() {
    println!(
        "{}{}Hello, {}Termion!{}",
        color::Fg(color::Red),
        style::Bold,
        color::Fg(color::Blue),
        style::Reset
    );
}

Rawモードとキー入力

use termion::raw::IntoRawMode;
use termion::input::TermRead;
use termion::event::Key;
use std::io::{Write, stdout, stdin};

fn main() {
    // Rawモードに切り替え
    let stdout = stdout();
    let mut stdout = stdout.lock().into_raw_mode().unwrap();
    let stdin = stdin();
    let mut stdin = stdin.lock();
    
    write!(stdout, "{}{}Press 'q' to quit.\r\n", 
           termion::clear::All, 
           termion::cursor::Goto(1, 1)).unwrap();
    stdout.flush().unwrap();
    
    // キー入力を読み取る
    for key in stdin.keys() {
        match key.unwrap() {
            Key::Char('q') => break,
            Key::Char(c) => {
                write!(stdout, "{}", c).unwrap();
                stdout.flush().unwrap();
            }
            Key::Alt(c) => {
                write!(stdout, "Alt-{}", c).unwrap();
                stdout.flush().unwrap();
            }
            Key::Ctrl(c) => {
                write!(stdout, "Ctrl-{}", c).unwrap();
                stdout.flush().unwrap();
            }
            _ => {}
        }
    }
}

カーソル操作

use termion::{clear, cursor};

fn main() {
    // 画面をクリアしてカーソルを移動
    print!("{}{}", clear::All, cursor::Goto(1, 1));
    println!("Top left corner");
    
    print!("{}", cursor::Goto(10, 5));
    println!("Position (10, 5)");
    
    // カーソルを非表示に
    print!("{}", cursor::Hide);
    println!("Cursor is hidden");
    
    // カーソルを表示
    print!("{}", cursor::Show);
}

色とスタイル

use termion::{color, style};

fn main() {
    // 16色
    println!(
        "{}Red text{}",
        color::Fg(color::Red),
        color::Fg(color::Reset)
    );
    
    // 256色
    println!(
        "{}Orange text{}",
        color::Fg(color::AnsiValue(208)),
        color::Fg(color::Reset)
    );
    
    // RGB色
    println!(
        "{}RGB Purple{}",
        color::Fg(color::Rgb(128, 0, 128)),
        color::Fg(color::Reset)
    );
    
    // 背景色
    println!(
        "{}{}White on Blue{}",
        color::Fg(color::White),
        color::Bg(color::Blue),
        style::Reset
    );
    
    // スタイル
    println!("{}Bold{}", style::Bold, style::Reset);
    println!("{}Italic{}", style::Italic, style::Reset);
    println!("{}Underline{}", style::Underline, style::Reset);
}

高度な機能

非同期入力

use termion::async_stdin;
use std::io::Read;
use std::thread;
use std::time::Duration;

fn main() {
    let mut stdin = async_stdin().bytes();
    
    loop {
        // 非ブロッキングで入力をチェック
        if let Some(Ok(b)) = stdin.next() {
            match b {
                b'q' => break,
                c => println!("Pressed: {}", c as char),
            }
        }
        
        // 他の処理を実行
        println!("Doing other work...");
        thread::sleep(Duration::from_millis(100));
    }
}

マウスイベント

use termion::event::{Event, MouseEvent};
use termion::input::{TermRead, MouseTerminal};
use termion::raw::IntoRawMode;
use std::io::{stdout, stdin};

fn main() {
    let stdin = stdin();
    let stdout = stdout().into_raw_mode().unwrap();
    let mut stdout = MouseTerminal::from(stdout);
    
    println!("Click or move the mouse (press 'q' to quit)\r");
    
    for event in stdin.events() {
        match event.unwrap() {
            Event::Key(key) if key == termion::event::Key::Char('q') => break,
            Event::Mouse(MouseEvent::Press(_, x, y)) => {
                println!("Mouse clicked at ({}, {})\r", x, y);
            }
            Event::Mouse(MouseEvent::Hold(x, y)) => {
                println!("Mouse dragged to ({}, {})\r", x, y);
            }
            _ => {}
        }
    }
}

ターミナル情報

use termion::terminal_size;

fn main() {
    // ターミナルサイズを取得
    match terminal_size() {
        Ok((width, height)) => {
            println!("Terminal size: {}x{}", width, height);
        }
        Err(e) => {
            eprintln!("Failed to get terminal size: {}", e);
        }
    }
}

カスタムマクロ

// カスタムなエスケープシーケンスを定義
macro_rules! gotoxy {
    ($x:expr, $y:expr) => {
        format!("\x1b[{};{}H", $y, $x)
    };
}

fn main() {
    print!("{}", gotoxy!(10, 5));
    println!("Custom macro position");
}

エコシステム

Termionを使用するプロジェクト

  • Alacritty: GPUアクセラレーションターミナル
  • Xi Editor: モダンなテキストエディタ
  • Amp: ターミナルテキストエディタ
  • 多数のTUIアプリケーション: 軽量性を求めるプロジェクト

代替ライブラリとの統合

  • tui-rs/Ratatui: Termionをバックエンドとして使用可能
  • Cursive: Termionバックエンドをサポート

設計原則

  1. ゼロ依存: 外部ライブラリへの依存を排除
  2. Unix専用: Unix系システムに特化した最適化
  3. シンプル: 必要最小限の機能に絞る
  4. 高速: パフォーマンスを優先

利点

  • ゼロ依存: 依存関係の管理が不要
  • 軽量: 非常に小さいバイナリサイズ
  • 高速: 最小限のオーバーヘッド
  • 純粋Rust: 安全性と信頼性
  • シンプルAPI: 学習が容易

制約事項

  • Unix専用: Windows非対応
  • 機能制限: 高度な機能は限定的
  • メンテナンス: 開発が停滞気味
  • コミュニティ: Crosstermに比べて小さい
  • ドキュメント: 最小限のドキュメント

他のライブラリとの比較

項目TermionCrosstermPancurses
プラットフォームUnixのみ全OS全OS
依存関係ゼロ少ないncurses
パフォーマンス非常に高い高い中程度
機能性基本的豊富豊富
メンテナンス停滞気味活発中程度

まとめ

Termionは、Unix系システムで軽量かつ高速なターミナル操作が必要な場合に最適な選択です。ゼロ依存でシンプルなAPIを提供し、小さなバイナリサイズと優れたパフォーマンスを実現します。ただし、Windowsサポートが必要な場合や、より高度な機能が必要な場合は、Crosstermなどの代替ライブラリを検討すべきです。