Skip to content

Commit 612f620

Browse files
committed
fix: scope keyboard enhancement flags
1 parent ee37a8b commit 612f620

2 files changed

Lines changed: 51 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.rs

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ use std::time::Duration;
1313
use anyhow::Result;
1414
use app::{App, AppAction, StatusKind, StatusLine};
1515
use config::ConfigStore;
16-
use crossterm::event;
16+
use crossterm::event::{
17+
self, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
18+
};
1719
use crossterm::execute;
1820
use crossterm::terminal::{
1921
disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen,
@@ -29,16 +31,21 @@ fn main() {
2931
}
3032

3133
fn start() -> Result<()> {
32-
let mut terminal = setup_terminal()?;
33-
let res = run_loop(&mut terminal);
34-
restore_terminal(&mut terminal)?;
34+
let mut guard = TerminalGuard::new()?;
35+
let res = run_loop(guard.terminal());
36+
guard.restore()?;
3537
res
3638
}
3739

3840
fn setup_terminal() -> Result<Terminal<CrosstermBackend<io::Stdout>>> {
3941
enable_raw_mode()?;
4042
let mut stdout = io::stdout();
41-
execute!(stdout, EnterAlternateScreen)?;
43+
execute!(
44+
stdout,
45+
EnterAlternateScreen,
46+
// Keep kitty keyboard protocol scoped to the TUI session.
47+
PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES)
48+
)?;
4249
let backend = CrosstermBackend::new(stdout);
4350
let mut terminal = Terminal::new(backend)?;
4451
terminal.clear()?;
@@ -47,11 +54,48 @@ fn setup_terminal() -> Result<Terminal<CrosstermBackend<io::Stdout>>> {
4754

4855
fn restore_terminal(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>) -> Result<()> {
4956
disable_raw_mode()?;
50-
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
57+
execute!(
58+
terminal.backend_mut(),
59+
// Pop before leaving the alternate screen to avoid leaking CSI u sequences.
60+
PopKeyboardEnhancementFlags,
61+
LeaveAlternateScreen
62+
)?;
5163
terminal.show_cursor()?;
5264
Ok(())
5365
}
5466

67+
struct TerminalGuard {
68+
terminal: Terminal<CrosstermBackend<io::Stdout>>,
69+
restored: bool,
70+
}
71+
72+
impl TerminalGuard {
73+
fn new() -> Result<Self> {
74+
Ok(Self {
75+
terminal: setup_terminal()?,
76+
restored: false,
77+
})
78+
}
79+
80+
fn terminal(&mut self) -> &mut Terminal<CrosstermBackend<io::Stdout>> {
81+
&mut self.terminal
82+
}
83+
84+
fn restore(&mut self) -> Result<()> {
85+
if !self.restored {
86+
restore_terminal(&mut self.terminal)?;
87+
self.restored = true;
88+
}
89+
Ok(())
90+
}
91+
}
92+
93+
impl Drop for TerminalGuard {
94+
fn drop(&mut self) {
95+
let _ = self.restore();
96+
}
97+
}
98+
5599
fn run_loop(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>) -> Result<()> {
56100
let mut app = App::new(ConfigStore::new()?)?;
57101
loop {

0 commit comments

Comments
 (0)