refactor: extract terminal setup/teardown

This commit is contained in:
Edward Langley
2026-03-31 21:27:12 -07:00
parent 22ea265b63
commit 85eabebd88

View File

@ -6,7 +6,7 @@ mod persistence;
mod ui; mod ui;
mod view; mod view;
use std::io; use std::io::{self, Stdout};
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
@ -202,7 +202,7 @@ fn parse_args(args: Vec<String>) -> Box<dyn Runnable> {
} }
fn get_initial_model(file_path: &Option<PathBuf>) -> Result<Model> { fn get_initial_model(file_path: &Option<PathBuf>) -> Result<Model> {
return if let Some(ref path) = file_path { if let Some(ref path) = file_path {
if path.exists() { if path.exists() {
let mut m = persistence::load(path) let mut m = persistence::load(path)
.with_context(|| format!("Failed to load {}", path.display()))?; .with_context(|| format!("Failed to load {}", path.display()))?;
@ -218,7 +218,29 @@ fn get_initial_model(file_path: &Option<PathBuf>) -> Result<Model> {
} }
} else { } else {
Ok(Model::new("New Model")) Ok(Model::new("New Model"))
}; }
}
struct TuiGuard<'a> {
terminal: Terminal<CrosstermBackend<&'a mut Stdout>>,
}
impl<'a> TuiGuard<'a> {
fn enter(out: &'a mut Stdout) -> Result<Self> {
enable_raw_mode()?;
execute!(out, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(out);
let terminal = Terminal::new(backend)?;
Ok(Self { terminal })
}
}
impl<'a> Drop for TuiGuard<'a> {
fn drop(&mut self) {
let _ = execute!(self.terminal.backend_mut(), LeaveAlternateScreen);
let _ = disable_raw_mode();
}
} }
fn run_tui( fn run_tui(
@ -226,11 +248,8 @@ fn run_tui(
file_path: Option<PathBuf>, file_path: Option<PathBuf>,
import_json: Option<serde_json::Value>, import_json: Option<serde_json::Value>,
) -> Result<()> { ) -> Result<()> {
enable_raw_mode()?;
let mut stdout = io::stdout(); let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?; let mut tui_context = TuiGuard::enter(&mut stdout)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
let mut app = App::new(model, file_path); let mut app = App::new(model, file_path);
if let Some(json) = import_json { if let Some(json) = import_json {
@ -238,7 +257,7 @@ fn run_tui(
} }
loop { loop {
terminal.draw(|f| draw(f, &app))?; tui_context.terminal.draw(|f| draw(f, &app))?;
if event::poll(Duration::from_millis(100))? { if event::poll(Duration::from_millis(100))? {
if let Event::Key(key) = event::read()? { if let Event::Key(key) = event::read()? {
@ -253,8 +272,6 @@ fn run_tui(
} }
} }
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
Ok(()) Ok(())
} }