refactor: move terminal guard to own file
This commit is contained in:
37
src/main.rs
37
src/main.rs
@@ -1,45 +1,18 @@
|
|||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crossterm::cursor::Show;
|
|
||||||
use crossterm::event::{self, Event, KeyCode};
|
use crossterm::event::{self, Event, KeyCode};
|
||||||
use crossterm::execute;
|
use crossterm::execute;
|
||||||
use crossterm::terminal::{
|
use crossterm::terminal::{EnterAlternateScreen, enable_raw_mode};
|
||||||
EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode,
|
|
||||||
};
|
|
||||||
use ratatui::Terminal;
|
use ratatui::Terminal;
|
||||||
use ratatui::backend::CrosstermBackend;
|
use ratatui::backend::CrosstermBackend;
|
||||||
use ratatui::layout::{Constraint, Direction, Layout};
|
use ratatui::layout::{Constraint, Direction, Layout};
|
||||||
use ratatui::style::Style;
|
use ratatui::style::Style;
|
||||||
use ratatui::widgets::{Block, Borders, List, ListItem, ListState};
|
use ratatui::widgets::{Block, Borders, List, ListItem, ListState};
|
||||||
|
|
||||||
// RAII guard to ensure terminal is restored on panic/unwind
|
mod terminal_guard;
|
||||||
struct TerminalModeGuard {
|
use terminal_guard::TerminalModeGuard;
|
||||||
// track whether we still need to clean up
|
|
||||||
active: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TerminalModeGuard {
|
|
||||||
fn new() -> Self {
|
|
||||||
TerminalModeGuard { active: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cleanup(&mut self) {
|
|
||||||
if !self.active {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let _ = disable_raw_mode();
|
|
||||||
let mut stdout = std::io::stdout();
|
|
||||||
let _ = execute!(stdout, LeaveAlternateScreen, Show);
|
|
||||||
self.active = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for TerminalModeGuard {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.cleanup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
io::stdin().read_to_string(&mut input)?;
|
io::stdin().read_to_string(&mut input)?;
|
||||||
@@ -78,8 +51,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, l)| {
|
.map(|(i, l)| {
|
||||||
let prefix = if marked[i] { "[x]" } else { "[ ]" };
|
let prefix = if marked[i] { 'x' } else { ' ' };
|
||||||
ListItem::new(format!("{} {}", prefix, l))
|
ListItem::new(format!("[{prefix}] {l}"))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|||||||
29
src/terminal_guard.rs
Normal file
29
src/terminal_guard.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use crossterm::cursor::Show;
|
||||||
|
use crossterm::execute;
|
||||||
|
use crossterm::terminal::{LeaveAlternateScreen, disable_raw_mode};
|
||||||
|
|
||||||
|
pub struct TerminalModeGuard {
|
||||||
|
active: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TerminalModeGuard {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { active: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cleanup(&mut self) {
|
||||||
|
if !self.active {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let _ = disable_raw_mode();
|
||||||
|
let mut stdout = std::io::stdout();
|
||||||
|
let _ = execute!(stdout, LeaveAlternateScreen, Show);
|
||||||
|
self.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TerminalModeGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user