aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2023-11-17 05:30:32 +0400
committerGitHub <noreply@github.com>2023-11-17 05:30:32 +0400
commit4fb1594a30d0c60653811496f845137f4420f7cd (patch)
tree2d93c0e4072d649fd20606b4295898746cd754d8
parentaea74a14760d2cb3c11768db6079c3212f98ee89 (diff)
downloadr-alacritty-vte-4fb1594a30d0c60653811496f845137f4420f7cd.tar.gz
r-alacritty-vte-4fb1594a30d0c60653811496f845137f4420f7cd.tar.bz2
r-alacritty-vte-4fb1594a30d0c60653811496f845137f4420f7cd.zip
Split-out `PrivateMode` from 'Mode'
The modes could overlap and there's also no way to actually forward information about unhandled modes downstream, thus split the modes into 2 separate structures and pass unhandled modes.
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/ansi.rs207
2 files changed, 122 insertions, 87 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71f6486..e31cd35 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@ CHANGELOG
## Unreleased
- Reexport `cursor_icon` crate in `ansi`
+- Split-out private modes from `Mode` into `PrivateMode`
+- Add `unset_private_mode` and `set_private_mode`
## 0.12.0
diff --git a/src/ansi.rs b/src/ansi.rs
index dc59ce7..7a59af1 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -27,7 +27,7 @@ use core::ops::Mul;
use std::time::Instant;
use cursor_icon::CursorIcon;
-use log::{debug, trace};
+use log::debug;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@@ -119,7 +119,7 @@ impl Mul<f32> for Rgb {
b: (f32::from(self.b) * rhs).clamp(0.0, 255.0) as u8,
};
- trace!("Scaling RGB by {} from {:?} to {:?}", rhs, self, result);
+ log::trace!("Scaling RGB by {} from {:?} to {:?}", rhs, self, result);
result
}
}
@@ -327,6 +327,8 @@ impl<T: Timeout> Processor<T> {
self.parser.advance(&mut performer, byte);
}
+ // Report that update ended, since we could end due to timeout.
+ handler.unset_private_mode(NamedPrivateMode::SyncUpdate.into());
// Resetting state after processing makes sure we don't interpret buffered sync escapes.
self.state.sync_state.buffer.clear();
self.state.sync_state.timeout.clear_timeout();
@@ -581,7 +583,13 @@ pub trait Handler {
fn set_mode(&mut self, _mode: Mode) {}
/// Unset mode.
- fn unset_mode(&mut self, _: Mode) {}
+ fn unset_mode(&mut self, _mode: Mode) {}
+
+ /// Set private mode.
+ fn set_private_mode(&mut self, _mode: PrivateMode) {}
+
+ /// Unset private mode.
+ fn unset_private_mode(&mut self, _mode: PrivateMode) {}
/// DECSTBM - Set the terminal scrolling region.
fn set_scrolling_region(&mut self, _top: usize, _bottom: Option<usize>) {}
@@ -773,10 +781,99 @@ pub enum CursorShape {
Hidden,
}
-/// Terminal modes.
-#[derive(Debug, Eq, PartialEq)]
+/// Wrapper for the ANSI modes.
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Mode {
- /// ?1
+ /// Known ANSI mode.
+ Named(NamedMode),
+ /// Unidentified publc mode.
+ Unknown(u16),
+}
+
+impl Mode {
+ fn new(mode: u16) -> Self {
+ match mode {
+ 4 => Self::Named(NamedMode::Insert),
+ 20 => Self::Named(NamedMode::LineFeedNewLine),
+ _ => Self::Unknown(mode),
+ }
+ }
+
+ /// Get the raw value of the mode.
+ pub fn raw(self) -> u16 {
+ match self {
+ Self::Named(named) => named as u16,
+ Self::Unknown(mode) => mode,
+ }
+ }
+}
+
+impl From<NamedMode> for Mode {
+ fn from(value: NamedMode) -> Self {
+ Self::Named(value)
+ }
+}
+
+/// ANSI modes.
+#[repr(u16)]
+#[derive(Debug, Clone, Copy, Eq, PartialEq)]
+pub enum NamedMode {
+ /// IRM Insert Mode.
+ Insert = 4,
+ LineFeedNewLine = 20,
+}
+
+/// Wrapper for the private DEC modes.
+#[derive(Debug, Eq, PartialEq)]
+pub enum PrivateMode {
+ /// Known private mode.
+ Named(NamedPrivateMode),
+ /// Unknown private mode.
+ Unknown(u16),
+}
+
+impl PrivateMode {
+ fn new(mode: u16) -> Self {
+ match mode {
+ 1 => Self::Named(NamedPrivateMode::CursorKeys),
+ 3 => Self::Named(NamedPrivateMode::ColumnMode),
+ 6 => Self::Named(NamedPrivateMode::Origin),
+ 7 => Self::Named(NamedPrivateMode::LineWrap),
+ 12 => Self::Named(NamedPrivateMode::BlinkingCursor),
+ 25 => Self::Named(NamedPrivateMode::ShowCursor),
+ 1000 => Self::Named(NamedPrivateMode::ReportMouseClicks),
+ 1002 => Self::Named(NamedPrivateMode::ReportCellMouseMotion),
+ 1003 => Self::Named(NamedPrivateMode::ReportAllMouseMotion),
+ 1004 => Self::Named(NamedPrivateMode::ReportFocusInOut),
+ 1005 => Self::Named(NamedPrivateMode::Utf8Mouse),
+ 1006 => Self::Named(NamedPrivateMode::SgrMouse),
+ 1007 => Self::Named(NamedPrivateMode::AlternateScroll),
+ 1042 => Self::Named(NamedPrivateMode::UrgencyHints),
+ 1049 => Self::Named(NamedPrivateMode::SwapScreenAndSetRestoreCursor),
+ 2004 => Self::Named(NamedPrivateMode::BracketedPaste),
+ 2026 => Self::Named(NamedPrivateMode::SyncUpdate),
+ _ => Self::Unknown(mode),
+ }
+ }
+
+ /// Get the raw value of the mode.
+ pub fn raw(self) -> u16 {
+ match self {
+ Self::Named(named) => named as u16,
+ Self::Unknown(mode) => mode,
+ }
+ }
+}
+
+impl From<NamedPrivateMode> for PrivateMode {
+ fn from(value: NamedPrivateMode) -> Self {
+ Self::Named(value)
+ }
+}
+
+/// Private DEC modes.
+#[derive(Debug, Eq, PartialEq)]
+pub enum NamedPrivateMode {
CursorKeys = 1,
/// Select 80 or 132 columns per page (DECCOLM).
///
@@ -790,88 +887,22 @@ pub enum Mode {
/// * resets DECLRMM to unavailable
/// * clears data from the status line (if set to host-writable)
ColumnMode = 3,
- /// IRM Insert Mode.
- ///
- /// NB should be part of non-private mode enum.
- ///
- /// * `CSI 4 h` change to insert mode
- /// * `CSI 4 l` reset to replacement mode
- Insert = 4,
- /// ?6
Origin = 6,
- /// ?7
LineWrap = 7,
- /// ?12
BlinkingCursor = 12,
- /// 20
- ///
- /// NB This is actually a private mode. We should consider adding a second
- /// enumeration for public/private modesets.
- LineFeedNewLine = 20,
- /// ?25
ShowCursor = 25,
- /// ?1000
ReportMouseClicks = 1000,
- /// ?1002
ReportCellMouseMotion = 1002,
- /// ?1003
ReportAllMouseMotion = 1003,
- /// ?1004
ReportFocusInOut = 1004,
- /// ?1005
Utf8Mouse = 1005,
- /// ?1006
SgrMouse = 1006,
- /// ?1007
AlternateScroll = 1007,
- /// ?1042
UrgencyHints = 1042,
- /// ?1049
SwapScreenAndSetRestoreCursor = 1049,
- /// ?2004
BracketedPaste = 2004,
-}
-
-impl Mode {
- /// Create mode from a primitive.
- pub fn from_primitive(intermediate: Option<&u8>, num: u16) -> Option<Mode> {
- let private = match intermediate {
- Some(b'?') => true,
- None => false,
- _ => return None,
- };
-
- if private {
- Some(match num {
- 1 => Mode::CursorKeys,
- 3 => Mode::ColumnMode,
- 6 => Mode::Origin,
- 7 => Mode::LineWrap,
- 12 => Mode::BlinkingCursor,
- 25 => Mode::ShowCursor,
- 1000 => Mode::ReportMouseClicks,
- 1002 => Mode::ReportCellMouseMotion,
- 1003 => Mode::ReportAllMouseMotion,
- 1004 => Mode::ReportFocusInOut,
- 1005 => Mode::Utf8Mouse,
- 1006 => Mode::SgrMouse,
- 1007 => Mode::AlternateScroll,
- 1042 => Mode::UrgencyHints,
- 1049 => Mode::SwapScreenAndSetRestoreCursor,
- 2004 => Mode::BracketedPaste,
- _ => {
- trace!("[unimplemented] primitive mode: {}", num);
- return None;
- },
- })
- } else {
- Some(match num {
- 4 => Mode::Insert,
- 20 => Mode::LineFeedNewLine,
- _ => return None,
- })
- }
- }
+ /// The mode is handled automatically by [`Processor`].
+ SyncUpdate = 2026,
}
/// Mode for clearing line.
@@ -1471,19 +1502,19 @@ where
let x = next_param_or(1) as usize;
handler.goto(y - 1, x - 1);
},
- ('h', intermediates) => {
+ ('h', []) => {
+ for param in params_iter.map(|param| param[0]) {
+ handler.set_mode(Mode::new(param))
+ }
+ },
+ ('h', [b'?']) => {
for param in params_iter.map(|param| param[0]) {
- let intermediate = intermediates.first();
-
// Handle sync updates opaquely.
- if intermediate == Some(&b'?') && param == 2026 {
+ if param == NamedPrivateMode::SyncUpdate as u16 {
self.state.sync_state.timeout.set_timeout(SYNC_UPDATE_TIMEOUT);
}
- match Mode::from_primitive(intermediate, param) {
- Some(mode) => handler.set_mode(mode),
- None => unhandled!(),
- }
+ handler.set_private_mode(PrivateMode::new(param))
}
},
('I', []) => handler.move_forward_tabs(next_param_or(1)),
@@ -1515,12 +1546,14 @@ where
handler.clear_line(mode);
},
('L', []) => handler.insert_blank_lines(next_param_or(1) as usize),
- ('l', intermediates) => {
+ ('l', []) => {
for param in params_iter.map(|param| param[0]) {
- match Mode::from_primitive(intermediates.first(), param) {
- Some(mode) => handler.unset_mode(mode),
- None => unhandled!(),
- }
+ handler.unset_mode(Mode::new(param))
+ }
+ },
+ ('l', [b'?']) => {
+ for param in params_iter.map(|param| param[0]) {
+ handler.unset_private_mode(PrivateMode::new(param))
}
},
('M', []) => handler.delete_lines(next_param_or(1) as usize),