Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
3 changes: 3 additions & 0 deletions src/interpreter/flamegraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
42 changes: 42 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F>(siv: &mut Cursive, actions: Vec<ActionDescription>, on_select: F)
where
F: Fn(&mut Cursive, String) + 'static + Send + Sync,
Expand Down Expand Up @@ -206,11 +244,15 @@ pub fn edit_query(query: &str, settings: &HashMap<String, String>) -> Result<Str

let editor = env::var_os("EDITOR").unwrap_or_else(|| "vim".into());
let tmp_file_path = tmp_file.path().to_str().unwrap();

let _guard = TerminalRawModeGuard::leave();

let result = Command::new(&editor)
.arg(tmp_file_path)
.spawn()
.map_err(|e| Error::msg(format!("Cannot execute editor {:?} ({})", editor, e)))?
.wait()?;

if !result.success() {
return Err(Error::msg(format!(
"Editor exited unsuccessfully {:?} ({})",
Expand Down
34 changes: 9 additions & 25 deletions src/view/providers/client.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use crate::{
interpreter::{ContextArc, options::ChDigViews},
utils::TerminalRawModeGuard,
view::ViewProvider,
};
use crossterm::{execute, terminal::disable_raw_mode, terminal::enable_raw_mode};
use cursive::{Cursive, views::Dialog};
use percent_encoding::percent_decode;
use std::io;
use std::process::Command;
use std::str::FromStr;

Expand Down Expand Up @@ -67,22 +66,17 @@ impl ViewProvider for ClientViewProvider {
}
}

disable_raw_mode().unwrap();
execute!(
io::stdout(),
crossterm::event::DisableMouseCapture,
crossterm::style::ResetColor,
crossterm::style::SetAttribute(crossterm::style::Attribute::Reset),
crossterm::terminal::Clear(crossterm::terminal::ClearType::All),
crossterm::cursor::MoveTo(0, 0)
)
.unwrap();

let cb_sink = siv.cb_sink().clone();
let cmd_line = format!("{:?}", cmd);
log::info!("Spawning client: {}", cmd_line);

match cmd.status() {
let result = {
let _guard = TerminalRawModeGuard::leave();
eprintln!("\n--- chdig: launching clickhouse client ---\n");
cmd.status()
};

match result {
Ok(status) => {
cb_sink
.send(Box::new(move |siv| {
Expand All @@ -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.");
}
}