diff --git a/Cargo.toml b/Cargo.toml index c9ce5d5..3e0473d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,7 @@ console-subscriber = { version = "*", default-features = false, optional = true # Flamegraphs flamelens = { git = "https://github.com/ys-l/flamelens", branch = "main", default-features = false } ratatui = { version = "0.29.0", features = ["unstable-rendered-line-info"] } +# Should **only** with the flamelens, since cursive re-export it, while flamelens does not crossterm = { version = "0.28.1", features = ["use-dev-tty"] } # Sharing aes-gcm = { version = "0.10", default-features = false, features = ["aes", "alloc"] } diff --git a/src/interpreter/flamegraph.rs b/src/interpreter/flamegraph.rs index 17dc532..302fa7e 100644 --- a/src/interpreter/flamegraph.rs +++ b/src/interpreter/flamegraph.rs @@ -66,6 +66,9 @@ pub fn show(block: Columns) -> AppResult<()> { } terminal.clear()?; + // ratatui's Terminal::drop may shows the cursor, re-hide it for cursive + drop(terminal); + crossterm::execute!(io::stderr(), crossterm::cursor::Hide)?; Ok(()) } diff --git a/src/utils.rs b/src/utils.rs index ba41c77..f6b50c5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -18,6 +18,44 @@ use std::process::{Command, Stdio}; use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use tempfile::Builder; +/// RAII guard that leaves cursive's terminal state (raw mode, alternate screen, +/// mouse capture, hidden cursor) and restores it on drop. +/// +/// Uses cursive's re-exported crossterm to ensure we operate on the same global +/// raw mode state that the cursive backend uses. +pub struct TerminalRawModeGuard; + +use cursive::backends::crossterm::crossterm as ct; + +impl TerminalRawModeGuard { + pub fn leave() -> Self { + ct::terminal::disable_raw_mode().unwrap(); + ct::execute!( + std::io::stdout(), + ct::event::DisableMouseCapture, + ct::style::ResetColor, + ct::style::SetAttribute(ct::style::Attribute::Reset), + ct::cursor::Show, + ct::terminal::LeaveAlternateScreen, + ) + .unwrap(); + Self + } +} + +impl Drop for TerminalRawModeGuard { + fn drop(&mut self) { + ct::terminal::enable_raw_mode().unwrap(); + ct::execute!( + std::io::stdout(), + ct::terminal::EnterAlternateScreen, + ct::event::EnableMouseCapture, + ct::cursor::Hide, + ) + .unwrap(); + } +} + pub fn fuzzy_actions(siv: &mut Cursive, actions: Vec, on_select: F) where F: Fn(&mut Cursive, String) + 'static + Send + Sync, @@ -206,11 +244,15 @@ pub fn edit_query(query: &str, settings: &HashMap) -> Result { cb_sink .send(Box::new(move |siv| { @@ -107,17 +101,7 @@ impl ViewProvider for ClientViewProvider { } } - enable_raw_mode().unwrap(); - execute!( - io::stdout(), - crossterm::event::EnableMouseCapture, - crossterm::terminal::Clear(crossterm::terminal::ClearType::All) - ) - .unwrap(); - - // Force a full redraw of the screen siv.complete_clear(); - - log::info!("Client terminated. Raw mode and mouse capture enabled."); + log::info!("Client terminated."); } }