Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml2
-rw-r--r--helix-term/src/application.rs2
-rw-r--r--helix-tui/src/backend/termina.rs148
4 files changed, 87 insertions, 69 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d0fdf561..c0fe3d28 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2796,9 +2796,9 @@ dependencies = [
[[package]]
name = "termina"
-version = "0.2.0"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9747435fb6e4b6db463ce5a7ec39354e60b555a1083211d976421384beb5b8db"
+checksum = "9a49b3d294d994319c4cd8c30f2172aab3217db673bb057912dc383677372830"
dependencies = [
"bitflags",
"futures-core",
diff --git a/Cargo.toml b/Cargo.toml
index b5a2565c..bf546efd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -52,7 +52,7 @@ futures-executor = "0.3"
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
tokio-stream = "0.1.18"
toml = "1.1"
-termina = "0.2"
+termina = "0.3"
sonic-rs = "0.5"
globset = "0.4"
etcetera = "0.11"
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index ed03edfc..c4e0bc3e 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -751,6 +751,8 @@ impl Application {
kind: crossterm::event::KeyEventKind::Release,
..
}) => false,
+ #[cfg(not(windows))]
+ event if event.is_escape() => false,
event => self.compositor.handle_event(&event.into(), &mut cx),
};
diff --git a/helix-tui/src/backend/termina.rs b/helix-tui/src/backend/termina.rs
index 30f67a3e..a5850edd 100644
--- a/helix-tui/src/backend/termina.rs
+++ b/helix-tui/src/backend/termina.rs
@@ -79,64 +79,26 @@ pub struct TerminaBackend {
capabilities: Capabilities,
reset_cursor_command: String,
is_synchronized_output_set: bool,
+ /// The requested terminal background color, set in `Self::set_background_color`.
background_color: Option<RgbColor>,
+ /// The terminal emulator's background color. This is queried when claiming the terminal so
+ /// that custom colors set outside of Helix with OSC11 are restored when Helix exits.
+ original_background_color: Option<RgbColor>,
}
impl TerminaBackend {
pub fn new(config: Config) -> io::Result<Self> {
- let mut terminal = PlatformTerminal::new()?;
- let (capabilities, reset_cursor_command) =
- Self::detect_capabilities(&mut terminal, &config)?;
-
- // In the case of a panic, reset the terminal eagerly. If we didn't do this and instead
- // relied on `Drop`, the backtrace would be lost because it is printed before we would
- // clear and exit the alternate screen.
- let hook_reset_cursor_command = reset_cursor_command.clone();
- terminal.set_panic_hook(move |term| {
- let _ = write!(
- term,
- "{}{}{}{}{}{}{}{}{}{}{}{}",
- Csi::Keyboard(csi::Keyboard::PopFlags(1)),
- decreset!(MouseTracking),
- decreset!(ButtonEventMouse),
- decreset!(AnyEventMouse),
- decreset!(RXVTMouse),
- decreset!(SGRMouse),
- &hook_reset_cursor_command,
- decreset!(BracketedPaste),
- decreset!(FocusTracking),
- Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor),
- Csi::Edit(csi::Edit::EraseInDisplay(csi::EraseInDisplay::EraseDisplay)),
- decreset!(ClearAndEnableAlternateScreen),
- );
- });
-
- Ok(Self {
- terminal,
- config,
- capabilities,
- reset_cursor_command,
- is_synchronized_output_set: false,
- background_color: None,
- })
- }
-
- pub fn terminal(&self) -> &PlatformTerminal {
- &self.terminal
- }
-
- fn detect_capabilities(
- terminal: &mut PlatformTerminal,
- config: &Config,
- ) -> io::Result<(Capabilities, String)> {
use std::time::{Duration, Instant};
+ let mut terminal = PlatformTerminal::new()?;
+
// Colibri "midnight"
const TEST_COLOR: RgbColor = RgbColor::new(59, 34, 76);
terminal.enter_raw_mode()?;
let mut capabilities = Capabilities::default();
+ let mut original_background_color = None;
let start = Instant::now();
// HACK: emitting OSC11 / OSC111 seems to break SGR and cause flickering in tmux.
@@ -158,7 +120,7 @@ impl TerminaBackend {
// If we only receive the device attributes then we know it is not.
write!(
terminal,
- "{}{}{}{}{}{}{}",
+ "{}{}{}{}{}{}{}{}",
// Synchronized output
Csi::Mode(csi::Mode::QueryDecPrivateMode(csi::DecPrivateMode::Code(
csi::DecPrivateModeCode::SynchronizedOutput
@@ -171,6 +133,10 @@ impl TerminaBackend {
Csi::Sgr(csi::Sgr::UnderlineColor(TEST_COLOR.into())),
Dcs::Request(dcs::DcsRequest::GraphicRendition),
Csi::Sgr(csi::Sgr::Reset),
+ Osc::ChangeDynamicColors(
+ osc::DynamicColorNumber::TextBackgroundColor,
+ vec![osc::ColorOrQuery::Query]
+ ),
// Finally request the primary device attributes
Csi::Device(csi::Device::RequestPrimaryDeviceAttributes),
)?;
@@ -199,6 +165,14 @@ impl TerminaBackend {
Event::Csi(Csi::Mode(csi::Mode::ReportTheme(mode))) => {
capabilities.theme_mode = Some(mode.into());
}
+ Event::Osc(Osc::ChangeDynamicColors(
+ osc::DynamicColorNumber::TextBackgroundColor,
+ colors,
+ )) => {
+ if let Some(osc::ColorOrQuery::Color(color)) = colors.first() {
+ original_background_color = Some(*color);
+ }
+ }
Event::Dcs(dcs::Dcs::Response {
value: dcs::DcsResponse::GraphicRendition(sgrs),
..
@@ -250,7 +224,42 @@ impl TerminaBackend {
terminal.enter_cooked_mode()?;
- Ok((capabilities, reset_cursor_command))
+ // In the case of a panic, reset the terminal eagerly. If we didn't do this and instead
+ // relied on `Drop`, the backtrace would be lost because it is printed before we would
+ // clear and exit the alternate screen.
+ let hook_reset_cursor_command = reset_cursor_command.clone();
+ terminal.set_panic_hook(move |term| {
+ let _ = write!(
+ term,
+ "{}{}{}{}{}{}{}{}{}{}{}{}",
+ Csi::Keyboard(csi::Keyboard::PopFlags(1)),
+ decreset!(MouseTracking),
+ decreset!(ButtonEventMouse),
+ decreset!(AnyEventMouse),
+ decreset!(RXVTMouse),
+ decreset!(SGRMouse),
+ &hook_reset_cursor_command,
+ decreset!(BracketedPaste),
+ decreset!(FocusTracking),
+ Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor),
+ Csi::Edit(csi::Edit::EraseInDisplay(csi::EraseInDisplay::EraseDisplay)),
+ decreset!(ClearAndEnableAlternateScreen),
+ );
+ });
+
+ Ok(Self {
+ terminal,
+ config,
+ capabilities,
+ reset_cursor_command,
+ is_synchronized_output_set: false,
+ background_color: None,
+ original_background_color,
+ })
+ }
+
+ pub fn terminal(&self) -> &PlatformTerminal {
+ &self.terminal
}
fn enable_mouse_capture(&mut self) -> io::Result<()> {
@@ -283,6 +292,20 @@ impl TerminaBackend {
Ok(())
}
+ fn reset_background_color(&mut self) -> io::Result<()> {
+ write!(
+ self.terminal,
+ "{}",
+ match self.original_background_color {
+ Some(color) => Osc::ChangeDynamicColors(
+ osc::DynamicColorNumber::TextBackgroundColor,
+ vec![color.into()]
+ ),
+ None => Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor),
+ }
+ )
+ }
+
fn enable_extensions(&mut self) -> io::Result<()> {
const KEYBOARD_FLAGS: csi::KittyKeyboardFlags =
csi::KittyKeyboardFlags::DISAMBIGUATE_ESCAPE_CODES
@@ -440,11 +463,7 @@ impl Backend for TerminaBackend {
decreset!(ClearAndEnableAlternateScreen),
)?;
if self.background_color.is_some() {
- write!(
- self.terminal,
- "{}",
- Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor)
- )?;
+ self.reset_background_color()?;
}
self.terminal.flush()?;
self.terminal.enter_cooked_mode()?;
@@ -606,17 +625,18 @@ impl Backend for TerminaBackend {
Some(Color::Rgb(r, g, b)) => Some(RgbColor::new(r, g, b)),
_ => None,
};
- write!(
- self.terminal,
- "{}",
- match self.background_color {
- Some(color) => Osc::ChangeDynamicColors(
+ if let Some(color) = self.background_color {
+ write!(
+ self.terminal,
+ "{}",
+ Osc::ChangeDynamicColors(
osc::DynamicColorNumber::TextBackgroundColor,
vec![color.into()]
- ),
- _ => Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor),
- }
- )
+ )
+ )
+ } else {
+ self.reset_background_color()
+ }
}
}
@@ -636,11 +656,7 @@ impl Drop for TerminaBackend {
decreset!(ClearAndEnableAlternateScreen),
);
if self.background_color.is_some() {
- let _ = write!(
- self.terminal,
- "{}",
- Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor)
- );
+ let _ = self.reset_background_color();
}
// NOTE: Drop for Platform terminal resets the mode and flushes the buffer when not
// panicking.