Notcurses

TUITerminalGraphicsMultimediaHigh-performance

GitHub概要

dankamongmen/notcurses

blingful character graphics/TUI library. definitely not curses.

スター4,009
ウォッチ33
フォーク127
作成日:2019年11月17日
言語:C
ライセンス:Other

トピックス

cclincursesterminalterminal-emulators

スター履歴

dankamongmen/notcurses Star History
データ取得日時: 2025/7/25 11:08

Notcurses

Notcursesは、最新のターミナル機能を最大限に活用する高性能TUIライブラリです。グラフィックス、動画、マルチメディアコンテンツの表示をサポートし、従来のTUIライブラリの限界を超えた表現力を提供します。C言語で書かれたライブラリのRustバインディングとして提供されています。

特徴

高度なグラフィックス機能

  • ピクセル操作: 真のピクセルレベルの描画
  • 画像表示: JPEG、PNG、GIF、WebPなどの画像フォーマット対応
  • 動画再生: ターミナル内での動画再生機能
  • 透過処理: アルファチャンネルのサポート
  • ブレンディング: 高度な色混合処理

パフォーマンス最適化

  • ダブルバッファリング: ちらつきのない描画
  • 差分レンダリング: 変更部分のみの再描画
  • 並列処理: マルチコアCPUを活用
  • メモリ効率: 最適化されたメモリ使用
  • ハードウェアアクセラレーション: 可能な場合はGPU活用

豊富な機能セット

  • Unicode完全対応: 絵文字、結合文字、RTL言語
  • 24ビットカラー: トゥルーカラーサポート
  • マウス対応: 高精度マウストラッキング
  • サウンド: オーディオ再生機能
  • 統計情報: レンダリング統計とデバッグ情報

ターミナル互換性

  • 幅広いサポート: 主要なターミナルエミュレータに対応
  • 機能検出: ターミナル機能の自動検出
  • グレースフルデグレーデーション: 機能が使えない場合の代替処理
  • Sixel/Kitty: グラフィックスプロトコル対応

基本的な使用方法

インストール

[dependencies]
notcurses = "3.0"

基本的な初期化と描画

use notcurses::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Notcursesの初期化
    let mut nc = Notcurses::new()?;
    
    // 標準プレーンを取得
    let mut stdplane = nc.stdplane();
    
    // テキストを描画
    stdplane.putstr("Hello, Notcurses!")?;
    
    // 色を設定して描画
    stdplane.set_fg_rgb(0xFF0000)?; // 赤
    stdplane.set_bg_rgb(0x000000)?; // 黒
    stdplane.putstr_yx(2, 0, "Colored text")?;
    
    // レンダリング
    nc.render()?;
    
    // キー入力を待つ
    nc.get_blocking(None)?;
    
    Ok(())
}

プレーンの操作

use notcurses::*;

fn create_window(nc: &mut Notcurses) -> Result<NcPlane, NcError> {
    let opts = NcPlaneOptions {
        y: 5,
        x: 10,
        rows: 10,
        cols: 40,
        userptr: std::ptr::null_mut(),
        name: Some("mywindow".to_string()),
        resizecb: None,
        flags: 0,
        margin_b: 0,
        margin_r: 0,
    };
    
    // 新しいプレーンを作成
    let mut plane = NcPlane::new(nc, &opts)?;
    
    // ボーダーを描画
    plane.perimeter_rounded(0, 0, 0)?;
    
    // タイトルを追加
    plane.putstr_yx(0, 2, " Window Title ")?;
    
    // コンテンツを追加
    plane.putstr_yx(2, 2, "This is a window!")?;
    
    Ok(plane)
}

画像の表示

use notcurses::*;

fn display_image(
    nc: &mut Notcurses,
    path: &str,
) -> Result<(), Box<dyn std::error::Error>> {
    let mut stdplane = nc.stdplane();
    
    // ビジュアルを作成
    let mut visual = NcVisual::from_file(path)?;
    
    // スケーリングオプション
    let vopts = NcVisualOptions {
        n: Some(&mut stdplane),
        scaling: NcScale::Scale,
        y: 0,
        x: 0,
        begy: 0,
        begx: 0,
        leny: 0,
        lenx: 0,
        blitter: NcBlitter::Default,
        flags: 0,
        transcolor: 0,
        pxoffy: 0,
        pxoffx: 0,
    };
    
    // 画像をレンダリング
    visual.blit(nc, &vopts)?;
    nc.render()?;
    
    Ok(())
}

アニメーション

use notcurses::*;
use std::time::Duration;
use std::thread;

fn animate_text(nc: &mut Notcurses) -> Result<(), NcError> {
    let mut plane = nc.stdplane();
    let text = "Animated Text";
    let max_x = plane.dim_x() as i32 - text.len() as i32;
    
    for x in 0..max_x {
        plane.erase();
        
        // 虹色のグラデーション
        let hue = (x as f32 / max_x as f32) * 360.0;
        let (r, g, b) = hsl_to_rgb(hue, 1.0, 0.5);
        plane.set_fg_rgb8(r, g, b)?;
        
        plane.putstr_yx(5, x, text)?;
        nc.render()?;
        
        thread::sleep(Duration::from_millis(50));
    }
    
    Ok(())
}

fn hsl_to_rgb(h: f32, s: f32, l: f32) -> (u8, u8, u8) {
    let c = (1.0 - (2.0 * l - 1.0).abs()) * s;
    let x = c * (1.0 - ((h / 60.0) % 2.0 - 1.0).abs());
    let m = l - c / 2.0;
    
    let (r, g, b) = match (h / 60.0) as u8 {
        0 => (c, x, 0.0),
        1 => (x, c, 0.0),
        2 => (0.0, c, x),
        3 => (0.0, x, c),
        4 => (x, 0.0, c),
        _ => (c, 0.0, x),
    };
    
    (
        ((r + m) * 255.0) as u8,
        ((g + m) * 255.0) as u8,
        ((b + m) * 255.0) as u8,
    )
}

高度な機能

メニューシステム

use notcurses::*;

fn create_menu(nc: &mut Notcurses) -> Result<NcMenu, NcError> {
    let sections = vec![
        NcMenuSection {
            name: "File".to_string(),
            items: vec![
                NcMenuItem {
                    desc: "New".to_string(),
                    shortcut: Some("Ctrl+N".to_string()),
                },
                NcMenuItem {
                    desc: "Open".to_string(),
                    shortcut: Some("Ctrl+O".to_string()),
                },
                NcMenuItem {
                    desc: "Save".to_string(),
                    shortcut: Some("Ctrl+S".to_string()),
                },
            ],
        },
        NcMenuSection {
            name: "Edit".to_string(),
            items: vec![
                NcMenuItem {
                    desc: "Copy".to_string(),
                    shortcut: Some("Ctrl+C".to_string()),
                },
                NcMenuItem {
                    desc: "Paste".to_string(),
                    shortcut: Some("Ctrl+V".to_string()),
                },
            ],
        },
    ];
    
    let opts = NcMenuOptions {
        sections,
        ..Default::default()
    };
    
    NcMenu::new(&mut nc.stdplane(), &opts)
}

グラフとチャート

use notcurses::*;

fn draw_chart(
    plane: &mut NcPlane,
    data: &[f64],
) -> Result<(), NcError> {
    let height = plane.dim_y() as usize;
    let width = plane.dim_x() as usize;
    
    // データを正規化
    let max_val = data.iter().cloned().fold(f64::MIN, f64::max);
    let min_val = data.iter().cloned().fold(f64::MAX, f64::min);
    let range = max_val - min_val;
    
    // グラフを描画
    for (i, &value) in data.iter().enumerate() {
        let x = (i * width) / data.len();
        let normalized = (value - min_val) / range;
        let y = height - (normalized * height as f64) as usize - 1;
        
        // バーを描画
        for bar_y in y..height {
            plane.putchar_yx(bar_y as i32, x as i32, '█')?;
        }
    }
    
    Ok(())
}

エコシステム

関連プロジェクト

  • notcurses-rs: 公式Rustバインディング
  • ncplayer: メディアプレーヤー
  • ncneofetch: システム情報表示ツール
  • nctetris: テトリスゲーム実装

ツールとユーティリティ

  • notcurses-demo: 機能デモンストレーション
  • ncls: lsコマンドの拡張版
  • ncplayer: ターミナルメディアプレーヤー

利点

  • 最先端機能: 最新のターミナル機能を完全活用
  • 高パフォーマンス: 最適化されたレンダリングエンジン
  • 豊富な表現力: 画像、動画、グラフィックスのサポート
  • プロフェッショナル: 商用品質のライブラリ
  • 活発な開発: 継続的な機能追加と改善

制約事項

  • 複雑性: 高機能ゆえに学習曲線が急
  • 依存関係: C言語ライブラリへの依存
  • ターミナル要件: 最新機能には対応ターミナルが必要
  • リソース使用: メモリとCPU使用量が多い
  • 移植性: 一部機能はプラットフォーム固有

他のライブラリとの比較

項目NotcursesRatatuiCursive
グラフィックス完全対応テキストのみテキストのみ
パフォーマンス非常に高い高い高い
学習コスト非常に高い低〜中
機能の豊富さ最高
移植性

まとめ

Notcursesは、ターミナルアプリケーションの可能性を最大限に引き出す革新的なライブラリです。従来のTUIライブラリでは不可能だった、画像表示、動画再生、高度なグラフィックス表現を可能にします。学習曲線は急ですが、プロフェッショナルなターミナルアプリケーションや、視覚的に印象的なTUIを作成したい開発者にとって最適な選択肢です。