aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--helix-term/src/application.rs98
-rw-r--r--helix-tui/Cargo.toml1
-rw-r--r--helix-tui/src/backend/crossterm.rs70
-rw-r--r--helix-tui/src/backend/mod.rs5
-rw-r--r--helix-tui/src/backend/test.rs13
-rw-r--r--helix-tui/src/terminal.rs22
7 files changed, 131 insertions, 79 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cc7265f3..23127395 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1201,6 +1201,7 @@ dependencies = [
"crossterm",
"helix-core",
"helix-view",
+ "log",
"serde",
"termini",
"unicode-segmentation",
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index df6d9da6..2487a02f 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -30,22 +30,14 @@ use crate::{
use log::{debug, error, warn};
use std::{
- io::{stdin, stdout, Write},
+ io::{stdin, stdout},
sync::Arc,
time::{Duration, Instant},
};
use anyhow::{Context, Error};
-use crossterm::{
- event::{
- DisableBracketedPaste, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste,
- EnableFocusChange, EnableMouseCapture, Event as CrosstermEvent, KeyboardEnhancementFlags,
- PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
- },
- execute, terminal,
- tty::IsTty,
-};
+use crossterm::{event::Event as CrosstermEvent, tty::IsTty};
#[cfg(not(windows))]
use {
signal_hook::{consts::signal, low_level},
@@ -63,10 +55,12 @@ use tui::backend::CrosstermBackend;
use tui::backend::TestBackend;
#[cfg(not(feature = "integration"))]
-type Terminal = tui::terminal::Terminal<CrosstermBackend<std::io::Stdout>>;
+type TerminalBackend = CrosstermBackend<std::io::Stdout>;
#[cfg(feature = "integration")]
-type Terminal = tui::terminal::Terminal<TestBackend>;
+type TerminalBackend = TestBackend;
+
+type Terminal = tui::terminal::Terminal<TerminalBackend>;
pub struct Application {
compositor: Compositor,
@@ -108,26 +102,6 @@ fn setup_integration_logging() {
.apply();
}
-fn restore_term() -> Result<(), Error> {
- let mut stdout = stdout();
- // reset cursor shape
- write!(stdout, "\x1B[0 q")?;
- if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) {
- execute!(stdout, PopKeyboardEnhancementFlags)?;
- }
- // Ignore errors on disabling, this might trigger on windows if we call
- // disable without calling enable previously
- let _ = execute!(stdout, DisableMouseCapture);
- execute!(
- stdout,
- DisableBracketedPaste,
- DisableFocusChange,
- terminal::LeaveAlternateScreen
- )?;
- terminal::disable_raw_mode()?;
- Ok(())
-}
-
impl Application {
pub fn new(
args: Args,
@@ -472,13 +446,7 @@ impl Application {
pub async fn handle_signals(&mut self, signal: i32) {
match signal {
signal::SIGTSTP => {
- // restore cursor
- use helix_view::graphics::CursorKind;
- self.terminal
- .backend_mut()
- .show_cursor(CursorKind::Block)
- .ok();
- restore_term().unwrap();
+ self.restore_term().unwrap();
low_level::emulate_default_handler(signal::SIGTSTP).unwrap();
}
signal::SIGCONT => {
@@ -1054,37 +1022,19 @@ impl Application {
}
}
- async fn claim_term(&mut self) -> Result<(), Error> {
- use helix_view::graphics::CursorKind;
- terminal::enable_raw_mode()?;
- if self.terminal.cursor_kind() == CursorKind::Hidden {
- self.terminal.backend_mut().hide_cursor().ok();
- }
- let mut stdout = stdout();
- execute!(
- stdout,
- terminal::EnterAlternateScreen,
- EnableBracketedPaste,
- EnableFocusChange
- )?;
- execute!(stdout, terminal::Clear(terminal::ClearType::All))?;
- if self.config.load().editor.mouse {
- execute!(stdout, EnableMouseCapture)?;
- }
- if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) {
- log::debug!("The enhanced keyboard protocol is supported on this terminal");
- execute!(
- stdout,
- PushKeyboardEnhancementFlags(
- KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
- | KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
- )
- )?;
- } else {
- log::debug!("The enhanced keyboard protocol is not supported on this terminal");
- }
+ async fn claim_term(&mut self) -> std::io::Result<()> {
+ let terminal_config = self.config.load().editor.clone().into();
+ self.terminal.claim(terminal_config)
+ }
- Ok(())
+ fn restore_term(&mut self) -> std::io::Result<()> {
+ let terminal_config = self.config.load().editor.clone().into();
+ use helix_view::graphics::CursorKind;
+ self.terminal
+ .backend_mut()
+ .show_cursor(CursorKind::Block)
+ .ok();
+ self.terminal.restore(terminal_config)
}
pub async fn run<S>(&mut self, input_stream: &mut S) -> Result<i32, Error>
@@ -1099,7 +1049,7 @@ impl Application {
// We can't handle errors properly inside this closure. And it's
// probably not a good idea to `unwrap()` inside a panic handler.
// So we just ignore the `Result`.
- let _ = restore_term();
+ let _ = TerminalBackend::force_restore();
hook(info);
}));
@@ -1107,13 +1057,7 @@ impl Application {
let close_errs = self.close().await;
- // restore cursor
- use helix_view::graphics::CursorKind;
- self.terminal
- .backend_mut()
- .show_cursor(CursorKind::Block)
- .ok();
- restore_term()?;
+ self.restore_term()?;
for err in close_errs {
self.editor.exit_code = 1;
diff --git a/helix-tui/Cargo.toml b/helix-tui/Cargo.toml
index ccd016f5..3ca7e044 100644
--- a/helix-tui/Cargo.toml
+++ b/helix-tui/Cargo.toml
@@ -22,5 +22,6 @@ unicode-segmentation = "1.10"
crossterm = { version = "0.26", optional = true }
termini = "0.1"
serde = { version = "1", "optional" = true, features = ["derive"]}
+log = "~0.4"
helix-view = { version = "0.6", path = "../helix-view", features = ["term"] }
helix-core = { version = "0.6", path = "../helix-core" }
diff --git a/helix-tui/src/backend/crossterm.rs b/helix-tui/src/backend/crossterm.rs
index 5305640c..e81c1e00 100644
--- a/helix-tui/src/backend/crossterm.rs
+++ b/helix-tui/src/backend/crossterm.rs
@@ -1,6 +1,11 @@
-use crate::{backend::Backend, buffer::Cell};
+use crate::{backend::Backend, buffer::Cell, terminal::Config};
use crossterm::{
cursor::{Hide, MoveTo, SetCursorStyle, Show},
+ event::{
+ DisableBracketedPaste, DisableFocusChange, DisableMouseCapture, EnableBracketedPaste,
+ EnableFocusChange, EnableMouseCapture, KeyboardEnhancementFlags,
+ PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
+ },
execute, queue,
style::{
Attribute as CAttribute, Color as CColor, Print, SetAttribute, SetBackgroundColor,
@@ -83,6 +88,69 @@ impl<W> Backend for CrosstermBackend<W>
where
W: Write,
{
+ fn claim(&mut self, config: Config) -> io::Result<()> {
+ terminal::enable_raw_mode()?;
+ execute!(
+ self.buffer,
+ terminal::EnterAlternateScreen,
+ EnableBracketedPaste,
+ EnableFocusChange
+ )?;
+ execute!(self.buffer, terminal::Clear(terminal::ClearType::All))?;
+ if config.enable_mouse_capture {
+ execute!(self.buffer, EnableMouseCapture)?;
+ }
+ if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) {
+ log::debug!("The enhanced keyboard protocol is supported on this terminal");
+ execute!(
+ self.buffer,
+ PushKeyboardEnhancementFlags(
+ KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
+ | KeyboardEnhancementFlags::REPORT_ALTERNATE_KEYS
+ )
+ )?;
+ } else {
+ log::debug!("The enhanced keyboard protocol is not supported on this terminal");
+ }
+ Ok(())
+ }
+
+ fn restore(&mut self, config: Config) -> io::Result<()> {
+ // reset cursor shape
+ write!(self.buffer, "\x1B[0 q")?;
+ if config.enable_mouse_capture {
+ execute!(self.buffer, DisableMouseCapture)?;
+ }
+ if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) {
+ execute!(self.buffer, PopKeyboardEnhancementFlags)?;
+ }
+ execute!(
+ self.buffer,
+ DisableBracketedPaste,
+ DisableFocusChange,
+ terminal::LeaveAlternateScreen
+ )?;
+ terminal::disable_raw_mode()
+ }
+
+ fn force_restore() -> io::Result<()> {
+ let mut stdout = io::stdout();
+
+ // reset cursor shape
+ write!(stdout, "\x1B[0 q")?;
+ // Ignore errors on disabling, this might trigger on windows if we call
+ // disable without calling enable previously
+ let _ = execute!(stdout, DisableMouseCapture);
+ let _ = execute!(stdout, PopKeyboardEnhancementFlags);
+ execute!(
+ stdout,
+ DisableBracketedPaste,
+ DisableFocusChange,
+ terminal::LeaveAlternateScreen
+ )?;
+ terminal::disable_raw_mode()
+ }
+
fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
where
I: Iterator<Item = (u16, u16, &'a Cell)>,
diff --git a/helix-tui/src/backend/mod.rs b/helix-tui/src/backend/mod.rs
index c6c11019..6d7c3894 100644
--- a/helix-tui/src/backend/mod.rs
+++ b/helix-tui/src/backend/mod.rs
@@ -1,6 +1,6 @@
use std::io;
-use crate::buffer::Cell;
+use crate::{buffer::Cell, terminal::Config};
use helix_view::graphics::{CursorKind, Rect};
@@ -13,6 +13,9 @@ mod test;
pub use self::test::TestBackend;
pub trait Backend {
+ fn claim(&mut self, config: Config) -> Result<(), io::Error>;
+ fn restore(&mut self, config: Config) -> Result<(), io::Error>;
+ fn force_restore() -> Result<(), io::Error>;
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
where
I: Iterator<Item = (u16, u16, &'a Cell)>;
diff --git a/helix-tui/src/backend/test.rs b/helix-tui/src/backend/test.rs
index 52474148..ff133ff3 100644
--- a/helix-tui/src/backend/test.rs
+++ b/helix-tui/src/backend/test.rs
@@ -1,6 +1,7 @@
use crate::{
backend::Backend,
buffer::{Buffer, Cell},
+ terminal::Config,
};
use helix_core::unicode::width::UnicodeWidthStr;
use helix_view::graphics::{CursorKind, Rect};
@@ -106,6 +107,18 @@ impl TestBackend {
}
impl Backend for TestBackend {
+ fn claim(&mut self, _config: Config) -> Result<(), io::Error> {
+ Ok(())
+ }
+
+ fn restore(&mut self, _config: Config) -> Result<(), io::Error> {
+ Ok(())
+ }
+
+ fn force_restore() -> Result<(), io::Error> {
+ Ok(())
+ }
+
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
where
I: Iterator<Item = (u16, u16, &'a Cell)>,
diff --git a/helix-tui/src/terminal.rs b/helix-tui/src/terminal.rs
index 22e9232f..802a8c1d 100644
--- a/helix-tui/src/terminal.rs
+++ b/helix-tui/src/terminal.rs
@@ -1,4 +1,5 @@
use crate::{backend::Backend, buffer::Buffer};
+use helix_view::editor::Config as EditorConfig;
use helix_view::graphics::{CursorKind, Rect};
use std::io;
@@ -16,6 +17,19 @@ pub struct Viewport {
resize_behavior: ResizeBehavior,
}
+#[derive(Debug)]
+pub struct Config {
+ pub enable_mouse_capture: bool,
+}
+
+impl From<EditorConfig> for Config {
+ fn from(config: EditorConfig) -> Self {
+ Self {
+ enable_mouse_capture: config.mouse,
+ }
+ }
+}
+
impl Viewport {
/// UNSTABLE
pub fn fixed(area: Rect) -> Viewport {
@@ -98,6 +112,14 @@ where
})
}
+ pub fn claim(&mut self, config: Config) -> io::Result<()> {
+ self.backend.claim(config)
+ }
+
+ pub fn restore(&mut self, config: Config) -> io::Result<()> {
+ self.backend.restore(config)
+ }
+
// /// Get a Frame object which provides a consistent view into the terminal state for rendering.
// pub fn get_frame(&mut self) -> Frame<B> {
// Frame {