Use `color_eyre` with Ratatui
color_eyre
クレートは、パニックとエラーのエラーレポートハンドラーを提供します。フォーマットされたレポートと色が表示されます。これらのハンドラーを使用するには、エラーを表示する前にターミナルを復元する必要があります。
インストール
最初に Cargo.toml
にクレートを追加します
cargo add color_eyre
メイン関数からcolor_eyre::install
メソッドを呼び出して、返品値をcolor_eyre::Result<()>
に更新します。
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}
ターミナル初期化関数に、パニックの詳細を表示する前にターミナルを復元するデフォルトパニックハンドラーに置き換える新しいコードを追加します。これは、プログラムの終わりまで進むパニックと未処理のエラーの両方によって使用されます。
/// Initialize the terminalpub 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); }));}
使用法
アプリケーションでは、必要に応じて追加のコンテキストでエラーをラップします。
次のインポートを追加します。
use color_eyre::eyre::WrapErr;
エラーで失敗する可能性のあるメソッドからwrap_errを呼び出します。
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
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(())}
use std::io::{self, stdout, Stdout};
use ratatui::{ backend::CrosstermBackend, crossterm::{ execute, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }, Terminal,};
/// Initialize the terminalpub 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 statepub fn restore() -> io::Result<()> { execute!(stdout(), LeaveAlternateScreen)?; disable_raw_mode()?; Ok(())}
パニック
RUST_BACKTRACE=full
で:
エラー
RUST_BACKTRACE=full
で: