@@ -30,22 +30,14 @@ use crate::{
31use log::{debug, error, warn};
31use log::{debug, error, warn};
33− io::{stdin, stdout, Write},
33+ io::{stdin, stdout},
34 sync::Arc,
34 sync::Arc,
35 time::{Duration, Instant},
35 time::{Duration, Instant},
38use anyhow::{Context, Error};
38use anyhow::{Context, Error};
40−use crossterm::{
40+use crossterm::{event::Event as CrosstermEvent, tty::IsTty};
42− DisableBracketedPaste, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste,
43− EnableFocusChange, EnableMouseCapture, Event as CrosstermEvent, KeyboardEnhancementFlags,
44− PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
49#[cfg(not(windows))]
41#[cfg(not(windows))]
51 signal_hook::{consts::signal, low_level},
43 signal_hook::{consts::signal, low_level},
@@ -63,10 +55,12 @@ use tui::backend::CrosstermBackend;
63use tui::backend::TestBackend;
55use tui::backend::TestBackend;
65#[cfg(not(feature = "integration"))]
57#[cfg(not(feature = "integration"))]
66−type Terminal = tui::terminal::Terminal<CrosstermBackend<std::io::Stdout>>;
58+type TerminalBackend = CrosstermBackend<std::io::Stdout>;
68#[cfg(feature = "integration")]
60#[cfg(feature = "integration")]
61+type TerminalBackend = TestBackend;
69−type Terminal = tui::terminal::Terminal<TestBackend>;
63+type Terminal = tui::terminal::Terminal<TerminalBackend>;
71pub struct Application {
65pub struct Application {
72 compositor: Compositor,
66 compositor: Compositor,
@@ -108,26 +102,6 @@ fn setup_integration_logging() {
108 .apply();
102 .apply();
111−fn restore_term() -> Result<(), Error> {
112− let mut stdout = stdout();
113− // reset cursor shape
114− write!(stdout, "\x1B[0 q")?;
115− if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) {
116− execute!(stdout, PopKeyboardEnhancementFlags)?;
118− // Ignore errors on disabling, this might trigger on windows if we call
119− // disable without calling enable previously
120− let _ = execute!(stdout, DisableMouseCapture);
123− DisableBracketedPaste,
125− terminal::LeaveAlternateScreen
127− terminal::disable_raw_mode()?;
131impl Application {
105impl Application {
132 pub fn new(
106 pub fn new(
133 args: Args,
107 args: Args,
@@ -472,13 +446,7 @@ impl Application {
472 pub async fn handle_signals(&mut self, signal: i32) {
446 pub async fn handle_signals(&mut self, signal: i32) {
473 match signal {
447 match signal {
474 signal::SIGTSTP => {
448 signal::SIGTSTP => {
476− use helix_view::graphics::CursorKind;
479− .show_cursor(CursorKind::Block)
481− restore_term().unwrap();
449+ self.restore_term().unwrap();
482 low_level::emulate_default_handler(signal::SIGTSTP).unwrap();
450 low_level::emulate_default_handler(signal::SIGTSTP).unwrap();
484 signal::SIGCONT => {
452 signal::SIGCONT => {
@@ -1054,37 +1022,19 @@ impl Application {
1057− async fn claim_term(&mut self) -> Result<(), Error> {
1025+ async fn claim_term(&mut self) -> std::io::Result<()> {
1058− use helix_view::graphics::CursorKind;
1059− terminal::enable_raw_mode()?;
1060− if self.terminal.cursor_kind() == CursorKind::Hidden {
1061− self.terminal.backend_mut().hide_cursor().ok();
1063− let mut stdout = stdout();
1066− terminal::EnterAlternateScreen,
1067− EnableBracketedPaste,
1070− execute!(stdout, terminal::Clear(terminal::ClearType::All))?;
1071− if self.config.load().editor.mouse {
1026+ let terminal_config = self.config.load().editor.clone().into();
1072− execute!(stdout, EnableMouseCapture)?;
1027+ self.terminal.claim(terminal_config)
1074− if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) {
1075− log::debug!("The enhanced keyboard protocol is supported on this terminal");
1078− PushKeyboardEnhancementFlags(
1079− KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
1080− | KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
1084− log::debug!("The enhanced keyboard protocol is not supported on this terminal");
1087− Ok(())
1030+ fn restore_term(&mut self) -> std::io::Result<()> {
1031+ let terminal_config = self.config.load().editor.clone().into();
1032+ use helix_view::graphics::CursorKind;
1035+ .show_cursor(CursorKind::Block)
1037+ self.terminal.restore(terminal_config)
1090 pub async fn run<S>(&mut self, input_stream: &mut S) -> Result<i32, Error>
1040 pub async fn run<S>(&mut self, input_stream: &mut S) -> Result<i32, Error>
@@ -1099,7 +1049,7 @@ impl Application {
1099 // We can't handle errors properly inside this closure. And it's
1049 // We can't handle errors properly inside this closure. And it's
1100 // probably not a good idea to `unwrap()` inside a panic handler.
1050 // probably not a good idea to `unwrap()` inside a panic handler.
1101 // So we just ignore the `Result`.
1051 // So we just ignore the `Result`.
1102− let _ = restore_term();
1052+ let _ = TerminalBackend::force_restore();
1103 hook(info);
1053 hook(info);
@@ -1107,13 +1057,7 @@ impl Application {
1108 let close_errs = self.close().await;
1058 let close_errs = self.close().await;
1111− use helix_view::graphics::CursorKind;
1114− .show_cursor(CursorKind::Block)
1116− restore_term()?;
1060+ self.restore_term()?;
1118 for err in close_errs {
1062 for err in close_errs {
1119 self.editor.exit_code = 1;
1063 self.editor.exit_code = 1;