Skip to content

Use `color_eyre` with Ratatui

color_eyreクレートは、パニックとエラーのエラーレポートハンドラーを提供します。フォーマットされたレポートと色が表示されます。これらのハンドラーを使用するには、エラーを表示する前にターミナルを復元する必要があります。

インストール

最初に Cargo.toml にクレートを追加します

add color_eyre to Cargo.toml
cargo add color_eyre

メイン関数からcolor_eyre::installメソッドを呼び出して、返品値をcolor_eyre::Result<()>に更新します。

main.rs
fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
9 collapsed lines
let terminal = tui::init()?;
let result = run(terminal).wrap_err("run failed");
if let Err(err) = tui::restore() {
eprintln!(
"failed to restore terminal. Run `reset` or restart your terminal to recover: {}",
err
);
}
result
}

ターミナル初期化関数に、パニックの詳細を表示する前にターミナルを復元するデフォルトパニックハンドラーに置き換える新しいコードを追加します。これは、プログラムの終わりまで進むパニックと未処理のエラーの両方によって使用されます。

tui.rs
/// Initialize the terminal
pub fn init() -> io::Result<ratatui::Terminal<CrosstermBackend<Stdout>>> {
execute!(stdout(), EnterAlternateScreen)?;
enable_raw_mode()?;
set_panic_hook();
Terminal::new(CrosstermBackend::new(stdout()))
}
fn set_panic_hook() {
let hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
let _ = restore(); // ignore any errors as we are already failing
hook(panic_info);
}));
}

使用法

アプリケーションでは、必要に応じて追加のコンテキストでエラーをラップします。

次のインポートを追加します。

main.rs
use color_eyre::eyre::WrapErr;

エラーで失敗する可能性のあるメソッドからwrap_errを呼び出します。

main.rs
fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
let terminal = tui::init()?;
let result = run(terminal).wrap_err("run failed");
if let Err(err) = tui::restore() {
eprintln!(
"failed to restore terminal. Run `reset` or restart your terminal to recover: {}",
err
);
}
result
}

デモ

Full code
main.rs
use std::panic;
use color_eyre::eyre::WrapErr;
use color_eyre::eyre::bail;
use ratatui::{
backend::Backend,
crossterm::event::{self, Event, KeyCode, KeyEvent},
widgets::Paragraph,
Terminal,
};
mod tui;
fn main() -> color_eyre::Result<()> {
color_eyre::install()?;
let terminal = tui::init()?;
let result = run(terminal).wrap_err("run failed");
if let Err(err) = tui::restore() {
eprintln!(
"failed to restore terminal. Run `reset` or restart your terminal to recover: {}",
err
);
}
result
}
fn run(mut terminal: Terminal<impl Backend>) -> color_eyre::Result<()> {
loop {
terminal.draw(|frame| {
let message = "Press <Q> to quit, <P> to panic, or <E> to error";
frame.render_widget(Paragraph::new(message), frame.area());
})?;
match event::read()? {
Event::Key(KeyEvent {
code: KeyCode::Char('q'),
..
}) => break,
Event::Key(KeyEvent {
code: KeyCode::Char('p'),
..
}) => panic!("User triggered panic"),
Event::Key(KeyEvent {
code: KeyCode::Char('e'),
..
}) => bail!("user triggered error"),
_ => {}
}
}
Ok(())
}
tui.rs
use std::io::{self, stdout, Stdout};
use ratatui::{
backend::CrosstermBackend,
crossterm::{
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
},
Terminal,
};
/// Initialize the terminal
pub fn init() -> io::Result<ratatui::Terminal<CrosstermBackend<Stdout>>> {
execute!(stdout(), EnterAlternateScreen)?;
enable_raw_mode()?;
set_panic_hook();
Terminal::new(CrosstermBackend::new(stdout()))
}
fn set_panic_hook() {
let hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
let _ = restore(); // ignore any errors as we are already failing
hook(panic_info);
}));
}
/// Restore the terminal to its original state
pub fn restore() -> io::Result<()> {
execute!(stdout(), LeaveAlternateScreen)?;
disable_raw_mode()?;
Ok(())
}

パニック

Panic

RUST_BACKTRACE=full で:

Panic Full

エラー

Error

RUST_BACKTRACE=full で:

Error Full

通常の出口

Quit

さらなるステップ

より高度なセットアップについては、 color_eyre docsおよびExamplesを参照してください。