use std::io;
use crossterm::{
cursor,
event::{
DisableBracketedPaste, DisableMouseCapture, EnableBracketedPaste, EnableMouseCapture,
KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{backend::CrosstermBackend, Terminal};
use super::termcaps::TermCaps;
type Term = Terminal<CrosstermBackend<io::Stdout>>;
pub(super) fn setup_terminal(caps: Option<&TermCaps>) -> synaps_cli::Result<Term> {
enable_raw_mode().map_err(|e| {
synaps_cli::error::RuntimeError::Tool(format!("terminal setup failed: {}", e))
})?;
let mut stdout = io::stdout();
execute!(
stdout,
EnterAlternateScreen,
EnableMouseCapture,
EnableBracketedPaste
)
.map_err(|e| {
synaps_cli::error::RuntimeError::Tool(format!("terminal setup failed: {}", e))
})?;
if super::termcaps::kitty_push_enabled(caps) {
let _ = execute!(
stdout,
PushKeyboardEnhancementFlags(
KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
| KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
)
);
}
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend).map_err(|e| {
synaps_cli::error::RuntimeError::Tool(format!("terminal setup failed: {}", e))
})?;
terminal.hide_cursor().ok();
Ok(terminal)
}
pub(super) fn emergency_teardown_terminal() {
disable_raw_mode().ok();
let mut stdout = io::stdout();
let _ = execute!(stdout, PopKeyboardEnhancementFlags);
execute!(
stdout,
DisableBracketedPaste,
DisableMouseCapture,
LeaveAlternateScreen
)
.ok();
execute!(stdout, cursor::Show).ok();
}
#[cfg(test)]
mod kitty_gate_tests {
use super::TermCaps;
use crate::tui::termcaps::kitty_push_enabled;
#[test]
fn unknown_caps_default_to_blind_push() {
assert!(kitty_push_enabled(None), "unknown caps must push (= today)");
}
#[test]
fn da1_timeout_defaults_to_blind_push() {
let caps = TermCaps::default();
assert!(!caps.da1_answered);
assert!(kitty_push_enabled(Some(&caps)), "no fence ⇒ blind push (= today)");
}
#[test]
fn negotiated_kitty_support_pushes() {
let caps = TermCaps { da1_answered: true, kitty_keyboard: true, ..TermCaps::default() };
assert!(kitty_push_enabled(Some(&caps)));
}
#[test]
fn negotiated_no_kitty_skips_push() {
let caps = TermCaps { da1_answered: true, kitty_keyboard: false, ..TermCaps::default() };
assert!(!kitty_push_enabled(Some(&caps)), "kitty negotiated off ⇒ no push");
}
}