pacsea/app/terminal.rs
1use crossterm::{
2 event::{DisableMouseCapture, EnableMouseCapture},
3 execute,
4 terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
5};
6
7/// Result type alias for terminal operations.
8type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
9
10/// What: Enter raw mode and switch to the alternate screen with mouse capture enabled.
11///
12/// Inputs:
13/// - None
14///
15/// Output:
16/// - `Ok(())` if the terminal was prepared; `Err` on I/O or terminal backend failure.
17///
18/// # Errors
19///
20/// Returns an error if raw mode cannot be enabled or the alternate screen cannot be entered.
21pub fn setup_terminal() -> Result<()> {
22 if std::env::var("PACSEA_TEST_HEADLESS").ok().as_deref() == Some("1") {
23 // Skip raw TTY setup in headless/test mode
24 // Explicitly disable mouse reporting to prevent mouse position escape sequences
25 // from appearing in test output when mouse moves over terminal
26 let _ = execute!(std::io::stdout(), DisableMouseCapture);
27 return Ok(());
28 }
29 enable_raw_mode()?;
30 execute!(std::io::stdout(), EnterAlternateScreen, EnableMouseCapture)?;
31 Ok(())
32}
33
34/// What: Restore terminal to normal mode, leave the alternate screen, and disable mouse capture.
35///
36/// Inputs:
37/// - None
38///
39/// Output:
40/// - `Ok(())` when restoration succeeds; `Err` if underlying terminal operations fail.
41///
42/// # Errors
43///
44/// Returns an error if raw mode cannot be disabled or the alternate screen cannot be left.
45pub fn restore_terminal() -> Result<()> {
46 if std::env::var("PACSEA_TEST_HEADLESS").ok().as_deref() == Some("1") {
47 // Skip terminal restore in headless/test mode
48 return Ok(());
49 }
50 disable_raw_mode()?;
51 execute!(std::io::stdout(), DisableMouseCapture, LeaveAlternateScreen)?;
52 Ok(())
53}