【tui-rs】RustでTUIソフトを作る

プログラミング

わたすけです。

皆さん、Rustは好きですか?わたしはすきです。

きっとTUIも好きでしょう。

今回は、RustでTUIを作るために役立つtui-rsを紹介します。

スポンサーリンク

tui-rsとは

tui-rsはRustでTUIを簡単に構築できるライブラリです。crossterm(もしくはtermion)をバックエンドとして、TUIでよくあるウィンドウのような表示はもちろん、キーボード入力を扱うこともできます。

とりあえずREADMEにあるGIFを見ると良いと思います。

GitHub - fdehau/tui-rs: Build terminal user interfaces and dashboards using Rust
Build terminal user interfaces and dashboards using Rust - GitHub - fdehau/tui-rs: Build terminal user interfaces and dashboards using Rust

使い方

ドキュメントにあることが全てです。Rustはドキュメント見れば書けます(要出典)。とりあえずサンプルを貼り付けて、具体的に何をしているのか見てみましょう。

use std::{io, thread, time::Duration};
use tui::{
    backend::CrosstermBackend,
    widgets::{Widget, Block, Borders},
    layout::{Layout, Constraint, Direction},
    Terminal
};
use crossterm::{
    event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};

fn main() -> Result<(), io::Error> {
    // setup terminal
    enable_raw_mode()?;
    let mut stdout = io::stdout();
    execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
    let backend = CrosstermBackend::new(stdout);
    let mut terminal = Terminal::new(backend)?;

    terminal.draw(|f| {
        let size = f.size();
        let block = Block::default()
            .title("Block")
            .borders(Borders::ALL);
        f.render_widget(block, size);
    })?;

    thread::sleep(Duration::from_millis(5000));

    // restore terminal
    disable_raw_mode()?;
    execute!(
        terminal.backend_mut(),
        LeaveAlternateScreen,
        DisableMouseCapture
    )?;
    terminal.show_cursor()?;

    Ok(())
}

ブログのハイライト機能にRustがなくて寂しい見た目になっていますが、ターミナルに描画してから5000ms待って終了するだけのシンプルなプログラムです。main関数を見ていきましょう。

ターミナルのセットアップ

enable_raw_mode() で、ターミナルをraw modeにします。次に、stdoutを持ってきて、execute! マクロでコマンドを実行しています。そして、crosstermのバックエンドを作成して、tui-rsのTerminalを作成します。

このあたりは(最後のTerminal生成を除いて)ぜんぶcrosstermが提供しているものなので、おまじない程度に捉えてよいでしょう。詳しく知りたければcrosstermのドキュメントを見れば良いと思います。

execute in crossterm - Rust
Executes one or more command(s).

Terminalを作ったら、draw関数を呼び出します。これに関数(クロージャ)を渡すことによってUIを描画していくことになります。
引数となっているfはFrame型です。

Frame in tui::terminal - Rust
Represents a consistent terminal interface for rendering.

このサンプルでは、”Block” というタイトルが付与されているボーダー付きのBlock(Widgetの一種)を作って、それをレンダリングしています。

これが終わったら、Rust標準ライブラリのthread::sleapを呼んで、5000ms待ちます。

待機が終わったら、raw modeを終了し、executeマクロで後処理を行って、終わりです。

まだ他にもある機能たち

他にも様々な機能があります。例えば、今回はBlockというWidgetを使いましたが、他にもTabs・List・Paragraphといった基本的なWidgetから、SparklineやBarChartといった便利そうなWidgetまでたくさんあります。かなり色々なことができそうです。

また、今回は画面全体にBlockを表示しましたが、Layoutというものを使えば、複数のWidgetをタイル状に並べることができます。exampleが参考になります。というかexampleは全部面白いので、一通り見てみるのが良いと思います。

https://github.com/fdehau/tui-rs/blob/master/examples/layout.rs

終わりに

かなり前にNcursesのRustラッパみたいなライブラリを使ったことがあるのですが、それよりも格段に書きやすくて驚きました。

ちなみに、以下のリポジトリは自分が最近開発しているもので、複数のスクリプトを起動し、横に並べて表示できるというものです。そもそもRustが便利なので、複数スレッドでスクリプトを動かして、出力をTUIで並べる・・・みたいなプログラムが簡単にかけるのが良いですね。

GitHub - watasuke102/script-manager: run shell script, and monitor their stdout
run shell script, and monitor their stdout. Contribute to watasuke102/script-manager development by creating an account on GitHub.

というわけで、今後もRustで色々作っていこうと思います。

コメント

タイトルとURLをコピーしました