aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAyose <ayosec@gmail.com>2025-02-24 00:00:00 +0000
committerAyose <ayosec@gmail.com>2025-02-24 00:00:00 +0000
commit22c7c29c0303398baa71db8798473ee704f9717c (patch)
tree17174ab40db30d33ef0898b9b3f44841f39ab82e
parent0700cee5af14c63895878dab357119f89ff263d0 (diff)
parent3b3da71c34cc1256c7e20981cf03f8eb95e08ffc (diff)
downloadr-alacritty-vte-graphics.tar.gz
r-alacritty-vte-graphics.tar.bz2
r-alacritty-vte-graphics.zip
Merge remote-tracking branch 'alacritty/master' into graphicsgraphics
-rw-r--r--CHANGELOG.md16
-rw-r--r--Cargo.toml23
-rw-r--r--examples/parselog.rs6
-rw-r--r--rustfmt.toml6
-rw-r--r--src/ansi.rs484
-rw-r--r--src/definitions.rs111
-rw-r--r--src/lib.rs1290
-rw-r--r--src/params.rs5
-rw-r--r--src/table.rs171
-rw-r--r--utf8parse/Cargo.toml15
l---------utf8parse/LICENSE-APACHE1
l---------utf8parse/LICENSE-MIT1
-rw-r--r--utf8parse/src/lib.rs132
-rw-r--r--utf8parse/src/types.rs100
-rw-r--r--utf8parse/tests/UTF-8-demo.txt212
-rw-r--r--utf8parse/tests/utf-8-demo.rs31
-rw-r--r--vte_generate_state_changes/Cargo.toml15
l---------vte_generate_state_changes/LICENSE-APACHE1
l---------vte_generate_state_changes/LICENSE-MIT1
-rw-r--r--vte_generate_state_changes/src/lib.rs176
20 files changed, 1219 insertions, 1578 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9780046..52bf0dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,22 @@
CHANGELOG
=========
+## 0.15.0
+
+- Support `CSI ? 5 W` to reset tabs stops to every 8th column
+- Replaced `no_std` with a new `std` feature
+- Changed default features to include `std`
+
+## 0.14.1
+
+- Crash when partial advance buffer stopped inside some grapheme boundaries
+
+## 0.14.0
+
+- `Parser::advance` now takes byte slices, instead of individual bytes
+- `Parser::advance_until_terminated` allows premature termination,
+ by checking for `Perform::terminated` after each dispatch
+
## 0.13.1
- Add SCP control support
diff --git a/Cargo.toml b/Cargo.toml
index 8e7dacc..1039801 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,26 +8,21 @@ categories = ["parsing", "no-std"]
exclude = ["/.travis.yml"]
readme = "README.md"
license = "Apache-2.0 OR MIT"
-version = "0.13.1"
+version = "0.15.0"
name = "vte-graphics"
edition = "2021"
rust-version = "1.62.1"
+[features]
+ansi = ["log", "cursor-icon", "bitflags"]
+default = ["std"]
+std = ["memchr/std"]
+serde = ["dep:serde"]
+
[dependencies]
-arrayvec = { version = "0.7.2", default-features = false, optional = true }
+arrayvec = { version = "0.7.2", default-features = false }
bitflags = { version = "2.3.3", default-features = false, optional = true }
cursor-icon = { version = "1.0.0", default-features = false, optional = true }
log = { version = "0.4.17", optional = true }
+memchr = { version = "2.7.4", default-features = false }
serde = { version = "1.0.160", features = ["derive"], optional = true }
-utf8parse = { version = "0.2.0", path = "utf8parse" }
-vte_generate_state_changes = { version = "0.1.0", path = "vte_generate_state_changes" }
-
-[features]
-ansi = ["log", "cursor-icon", "bitflags"]
-default = ["no_std"]
-nightly = ["utf8parse/nightly"]
-no_std = ["arrayvec"]
-serde = ["dep:serde"]
-
-[workspace]
-members = ["utf8parse", "vte_generate_state_changes"]
diff --git a/examples/parselog.rs b/examples/parselog.rs
index b90dcda..29f3d9a 100644
--- a/examples/parselog.rs
+++ b/examples/parselog.rs
@@ -61,11 +61,7 @@ fn main() {
loop {
match handle.read(&mut buf) {
Ok(0) => break,
- Ok(n) => {
- for byte in &buf[..n] {
- statemachine.advance(&mut performer, *byte);
- }
- },
+ Ok(n) => statemachine.advance(&mut performer, &buf[..n]),
Err(err) => {
println!("err: {}", err);
break;
diff --git a/rustfmt.toml b/rustfmt.toml
index 9308ba9..f82517e 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,13 +1,17 @@
format_code_in_doc_comments = true
+group_imports = "StdExternalCrate"
match_block_trailing_comma = true
condense_wildcard_suffixes = true
use_field_init_shorthand = true
+normalize_doc_attributes = true
overflow_delimited_expr = true
+imports_granularity = "Module"
+format_macro_matchers = true
use_small_heuristics = "Max"
+hex_literal_case = "Upper"
normalize_comments = true
reorder_impl_items = true
use_try_shorthand = true
newline_style = "Unix"
format_strings = true
wrap_comments = true
-comment_width = 100
diff --git a/src/ansi.rs b/src/ansi.rs
index 5495dc7..9dfc54f 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -11,21 +11,20 @@ extern crate alloc;
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
-use bitflags::bitflags;
-
use core::convert::TryFrom;
use core::fmt::{self, Display, Formatter, Write};
+#[cfg(feature = "std")]
+use core::ops::Mul;
use core::ops::{Add, Sub};
use core::str::FromStr;
use core::time::Duration;
-use core::{iter, str};
-
-#[cfg(not(feature = "no_std"))]
-use core::ops::Mul;
-
-#[cfg(not(feature = "no_std"))]
+use core::{iter, mem, str};
+#[cfg(feature = "std")]
use std::time::Instant;
+use bitflags::bitflags;
+#[doc(inline)]
+pub use cursor_icon;
use cursor_icon::CursorIcon;
use log::debug;
#[cfg(feature = "serde")]
@@ -33,9 +32,6 @@ use serde::{Deserialize, Serialize};
use crate::{Params, ParamsIter};
-#[doc(inline)]
-pub use cursor_icon;
-
/// Maximum time before a synchronized update is aborted.
const SYNC_UPDATE_TIMEOUT: Duration = Duration::from_millis(150);
@@ -71,7 +67,7 @@ impl Rgb {
/// Implementation of [W3C's luminance algorithm].
///
/// [W3C's luminance algorithm]: https://www.w3.org/TR/WCAG20/#relativeluminancedef
- #[cfg(not(feature = "no_std"))]
+ #[cfg(feature = "std")]
pub fn luminance(self) -> f64 {
let channel_luminance = |channel| {
let channel = channel as f64 / 255.;
@@ -92,7 +88,7 @@ impl Rgb {
/// Implementation of [W3C's contrast algorithm].
///
/// [W3C's contrast algorithm]: https://www.w3.org/TR/WCAG20/#contrast-ratiodef
- #[cfg(not(feature = "no_std"))]
+ #[cfg(feature = "std")]
pub fn contrast(self, other: Rgb) -> f64 {
let self_luminance = self.luminance();
let other_luminance = other.luminance();
@@ -108,7 +104,7 @@ impl Rgb {
}
// A multiply function for Rgb, as the default dim is just *2/3.
-#[cfg(not(feature = "no_std"))]
+#[cfg(feature = "std")]
impl Mul<f32> for Rgb {
type Output = Rgb;
@@ -168,9 +164,9 @@ impl FromStr for Rgb {
match u32::from_str_radix(chars, 16) {
Ok(mut color) => {
- let b = (color & 0xff) as u8;
+ let b = (color & 0xFF) as u8;
color >>= 8;
- let g = (color & 0xff) as u8;
+ let g = (color & 0xFF) as u8;
color >>= 8;
let r = color as u8;
Ok(Rgb { r, g, b })
@@ -237,14 +233,8 @@ fn parse_number(input: &[u8]) -> Option<u8> {
let mut num: u8 = 0;
for c in input {
let c = *c as char;
- if let Some(digit) = c.to_digit(10) {
- num = match num.checked_mul(10).and_then(|v| v.checked_add(digit as u8)) {
- Some(v) => v,
- None => return None,
- }
- } else {
- return None;
- }
+ let digit = c.to_digit(10)?;
+ num = num.checked_mul(10).and_then(|v| v.checked_add(digit as u8))?;
}
Some(num)
}
@@ -270,20 +260,22 @@ struct SyncState<T: Timeout> {
impl<T: Timeout> Default for SyncState<T> {
fn default() -> Self {
- Self { buffer: Vec::with_capacity(SYNC_BUFFER_SIZE), timeout: T::default() }
+ Self { buffer: Vec::with_capacity(SYNC_BUFFER_SIZE), timeout: Default::default() }
}
}
-/// The processor wraps a `crate::Parser` to ultimately call methods on a Handler.
-#[cfg(not(feature = "no_std"))]
+/// The processor wraps a `crate::Parser` to ultimately call methods on a
+/// Handler.
+#[cfg(feature = "std")]
#[derive(Default)]
pub struct Processor<T: Timeout = StdSyncHandler> {
state: ProcessorState<T>,
parser: crate::Parser,
}
-/// The processor wraps a `crate::Parser` to ultimately call methods on a Handler.
-#[cfg(feature = "no_std")]
+/// The processor wraps a `crate::Parser` to ultimately call methods on a
+/// Handler.
+#[cfg(not(feature = "std"))]
#[derive(Default)]
pub struct Processor<T: Timeout> {
state: ProcessorState<T>,
@@ -303,15 +295,19 @@ impl<T: Timeout> Processor<T> {
/// Process a new byte from the PTY.
#[inline]
- pub fn advance<H>(&mut self, handler: &mut H, byte: u8)
+ pub fn advance<H>(&mut self, handler: &mut H, bytes: &[u8])
where
H: Handler,
{
- if self.state.sync_state.timeout.pending_timeout() {
- self.advance_sync(handler, byte);
- } else {
- let mut performer = Performer::new(&mut self.state, handler);
- self.parser.advance(&mut performer, byte);
+ let mut processed = 0;
+ while processed != bytes.len() {
+ if self.state.sync_state.timeout.pending_timeout() {
+ processed += self.advance_sync(handler, &bytes[processed..]);
+ } else {
+ let mut performer = Performer::new(&mut self.state, handler);
+ processed +=
+ self.parser.advance_until_terminated(&mut performer, &bytes[processed..]);
+ }
}
}
@@ -320,18 +316,45 @@ impl<T: Timeout> Processor<T> {
where
H: Handler,
{
+ self.stop_sync_internal(handler, None);
+ }
+
+ /// End a synchronized update.
+ ///
+ /// The `bsu_offset` parameter should be passed if the sync buffer contains
+ /// a new BSU escape that is not part of the current synchronized
+ /// update.
+ fn stop_sync_internal<H>(&mut self, handler: &mut H, bsu_offset: Option<usize>)
+ where
+ H: Handler,
+ {
// Process all synchronized bytes.
- for i in 0..self.state.sync_state.buffer.len() {
- let byte = self.state.sync_state.buffer[i];
- let mut performer = Performer::new(&mut self.state, handler);
- self.parser.advance(&mut performer, byte);
+ //
+ // NOTE: We do not use `advance_until_terminated` here since BSU sequences are
+ // processed automatically during the synchronized update.
+ let buffer = mem::take(&mut self.state.sync_state.buffer);
+ let offset = bsu_offset.unwrap_or(buffer.len());
+ let mut performer = Performer::new(&mut self.state, handler);
+ self.parser.advance(&mut performer, &buffer[..offset]);
+ self.state.sync_state.buffer = buffer;
+
+ match bsu_offset {
+ // Just clear processed bytes if there is a new BSU.
+ //
+ // NOTE: We do not need to re-process for a new ESU since the `advance_sync`
+ // function checks for BSUs in reverse.
+ Some(bsu_offset) => {
+ let new_len = self.state.sync_state.buffer.len() - bsu_offset;
+ self.state.sync_state.buffer.copy_within(bsu_offset.., 0);
+ self.state.sync_state.buffer.truncate(new_len);
+ },
+ // Report mode and clear state if no new BSU is present.
+ None => {
+ handler.unset_private_mode(NamedPrivateMode::SyncUpdate.into());
+ self.state.sync_state.timeout.clear_timeout();
+ self.state.sync_state.buffer.clear();
+ },
}
-
- // 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();
}
/// Number of bytes in the synchronization buffer.
@@ -341,36 +364,56 @@ impl<T: Timeout> Processor<T> {
}
/// Process a new byte during a synchronized update.
+ ///
+ /// Returns the number of bytes processed.
#[cold]
- fn advance_sync<H>(&mut self, handler: &mut H, byte: u8)
+ fn advance_sync<H>(&mut self, handler: &mut H, bytes: &[u8]) -> usize
where
H: Handler,
{
- self.state.sync_state.buffer.push(byte);
+ // Advance sync parser or stop sync if we'd exceed the maximum buffer size.
+ if self.state.sync_state.buffer.len() + bytes.len() >= SYNC_BUFFER_SIZE - 1 {
+ // Terminate the synchronized update.
+ self.stop_sync_internal(handler, None);
- // Handle sync CSI escape sequences.
- self.advance_sync_csi(handler);
+ // Just parse the bytes normally.
+ let mut performer = Performer::new(&mut self.state, handler);
+ self.parser.advance_until_terminated(&mut performer, bytes)
+ } else {
+ self.state.sync_state.buffer.extend(bytes);
+ self.advance_sync_csi(handler, bytes.len());
+ bytes.len()
+ }
}
/// Handle BSU/ESU CSI sequences during synchronized update.
- fn advance_sync_csi<H>(&mut self, handler: &mut H)
+ fn advance_sync_csi<H>(&mut self, handler: &mut H, new_bytes: usize)
where
H: Handler,
{
- // Get the last few bytes for comparison.
- let len = self.state.sync_state.buffer.len();
- let offset = len.saturating_sub(SYNC_ESCAPE_LEN);
- let end = &self.state.sync_state.buffer[offset..];
+ // Get constraints within which a new escape character might be relevant.
+ let buffer_len = self.state.sync_state.buffer.len();
+ let start_offset = (buffer_len - new_bytes).saturating_sub(SYNC_ESCAPE_LEN - 1);
+ let end_offset = buffer_len.saturating_sub(SYNC_ESCAPE_LEN - 1);
+ let search_buffer = &self.state.sync_state.buffer[start_offset..end_offset];
+ // Search for termination/extension escapes in the added bytes.
+ //
// NOTE: It is technically legal to specify multiple private modes in the same
// escape, but we only allow EXACTLY `\e[?2026h`/`\e[?2026l` to keep the parser
- // reasonable.
- //
- // Check for extension/termination of the synchronized update.
- if end == BSU_CSI {
- self.state.sync_state.timeout.set_timeout(SYNC_UPDATE_TIMEOUT);
- } else if end == ESU_CSI || len >= SYNC_BUFFER_SIZE - 1 {
- self.stop_sync(handler);
+ // more simple.
+ let mut bsu_offset = None;
+ for index in memchr::memchr_iter(0x1B, search_buffer).rev() {
+ let offset = start_offset + index;
+ let escape = &self.state.sync_state.buffer[offset..offset + SYNC_ESCAPE_LEN];
+
+ if escape == BSU_CSI {
+ self.state.sync_state.timeout.set_timeout(SYNC_UPDATE_TIMEOUT);
+ bsu_offset = Some(offset);
+ } else if escape == ESU_CSI {
+ self.stop_sync_internal(handler, bsu_offset);
+ break;
+ }
}
}
}
@@ -382,23 +425,26 @@ impl<T: Timeout> Processor<T> {
struct Performer<'a, H: Handler, T: Timeout> {
state: &'a mut ProcessorState<T>,
handler: &'a mut H,
+
+ /// Whether the parser should be prematurely terminated.
+ terminated: bool,
}
impl<'a, H: Handler + 'a, T: Timeout> Performer<'a, H, T> {
/// Create a performer.
#[inline]
pub fn new<'b>(state: &'b mut ProcessorState<T>, handler: &'b mut H) -> Performer<'b, H, T> {
- Performer { state, handler }
+ Performer { state, handler, terminated: Default::default() }
}
}
-#[cfg(not(feature = "no_std"))]
+#[cfg(feature = "std")]
#[derive(Default)]
pub struct StdSyncHandler {
timeout: Option<Instant>,
}
-#[cfg(not(feature = "no_std"))]
+#[cfg(feature = "std")]
impl StdSyncHandler {
/// Synchronized update expiration time.
#[inline]
@@ -407,7 +453,7 @@ impl StdSyncHandler {
}
}
-#[cfg(not(feature = "no_std"))]
+#[cfg(feature = "std")]
impl Timeout for StdSyncHandler {
#[inline]
fn set_timeout(&mut self, duration: Duration) {
@@ -566,6 +612,9 @@ pub trait Handler {
/// Clear tab stops.
fn clear_tabs(&mut self, _mode: TabulationClearMode) {}
+ /// Set tab stops at every `interval`.
+ fn set_tabs(&mut self, _interval: u16) {}
+
/// Reset terminal state.
fn reset_state(&mut self) {}
@@ -744,13 +793,14 @@ bitflags! {
///
/// This only applies to keys corresponding to ascii characters.
///
-/// For the details on how to implement the mode handling correctly, consult [`XTerm's
-/// implementation`] and the [`output`] of XTerm's provided [`perl script`]. Some libraries and
-/// implementations also use the [`fixterms`] definition of the `CSI u`.
+/// For the details on how to implement the mode handling correctly, consult
+/// [`XTerm's implementation`] and the [`output`] of XTerm's provided [`perl
+/// script`]. Some libraries and implementations also use the [`fixterms`]
+/// definition of the `CSI u`.
///
-/// The end escape sequence has a `CSI char; modifiers u` form while the original
-/// `CSI 27 ; modifier ; char ~`. The clients should prefer the `CSI u`, since it has
-/// more adoption.
+/// The end escape sequence has a `CSI char; modifiers u` form while the
+/// original `CSI 27 ; modifier ; char ~`. The clients should prefer the `CSI
+/// u`, since it has more adoption.
///
/// [`XTerm's implementation`]: https://invisible-island.net/xterm/modified-keys.html
/// [`perl script`]: https://github.com/ThomasDickey/xterm-snapshots/blob/master/vttests/modify-keys.pl
@@ -761,12 +811,14 @@ bitflags! {
pub enum ModifyOtherKeys {
/// Reset the state.
Reset,
- /// Enables this feature except for keys with well-known behavior, e.g., Tab, Backspace and
- /// some special control character cases which are built into the X11 library (e.g.,
- /// Control-Space to make a NUL, or Control-3 to make an Escape character).
+ /// Enables this feature except for keys with well-known behavior, e.g.,
+ /// Tab, Backspace and some special control character cases which are
+ /// built into the X11 library (e.g., Control-Space to make a NUL, or
+ /// Control-3 to make an Escape character).
///
/// Escape sequences shouldn't be emitted under the following circumstances:
- /// - When the key is in range of `[64;127]` and the modifier is either Control or Shift
+ /// - When the key is in range of `[64;127]` and the modifier is either
+ /// Control or Shift
/// - When the key combination is a known control combination alias
///
/// For more details, consult the [`example`] for the suggested translation.
@@ -774,9 +826,10 @@ pub enum ModifyOtherKeys {
/// [`example`]: https://github.com/alacritty/vte/blob/master/doc/modifyOtherKeys-example.txt
EnableExceptWellDefined,
/// Enables this feature for all keys including the exceptions of
- /// [`Self::EnableExceptWellDefined`]. XTerm still ignores the special cases built into the
- /// X11 library. Any shifted (modified) ordinary key send an escape sequence. The Alt- and
- /// Meta- modifiers cause XTerm to send escape sequences.
+ /// [`Self::EnableExceptWellDefined`]. XTerm still ignores the special
+ /// cases built into the X11 library. Any shifted (modified) ordinary
+ /// key send an escape sequence. The Alt- and Meta- modifiers cause
+ /// XTerm to send escape sequences.
///
/// For more details, consult the [`example`] for the suggested translation.
///
@@ -1237,16 +1290,20 @@ impl StandardCharset {
pub enum ScpCharPath {
/// SCP's first parameter value of 0. Behavior is implementation defined.
Default,
- /// SCP's first parameter value of 1 which sets character path to LEFT-TO-RIGHT.
+ /// SCP's first parameter value of 1 which sets character path to
+ /// LEFT-TO-RIGHT.
LTR,
- /// SCP's first parameter value of 2 which sets character path to RIGHT-TO-LEFT.
+ /// SCP's first parameter value of 2 which sets character path to
+ /// RIGHT-TO-LEFT.
RTL,
}
-/// SCP control's second parameter which determines update mode/direction between components.
+/// SCP control's second parameter which determines update mode/direction
+/// between components.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ScpUpdateMode {
- /// SCP's second parameter value of 0 (the default). Implementation dependant update.
+ /// SCP's second parameter value of 0 (the default). Implementation
+ /// dependant update.
ImplementationDependant,
/// SCP's second parameter value of 1.
///
@@ -1376,8 +1433,8 @@ where
return;
}
- // Link parameters are in format of `key1=value1:key2=value2`. Currently only key
- // `id` is defined.
+ // Link parameters are in format of `key1=value1:key2=value2`. Currently only
+ // key `id` is defined.
let id = link_params
.split(|&b| b == b':')
.find_map(|kv| kv.strip_prefix(b"id="))
@@ -1545,6 +1602,7 @@ where
('E', []) => handler.move_down_and_cr(next_param_or(1) as usize),
('F', []) => handler.move_up_and_cr(next_param_or(1) as usize),
('G', []) | ('`', []) => handler.goto_col(next_param_or(1) as usize - 1),
+ ('W', [b'?']) if next_param_or(0) == 5 => handler.set_tabs(8),
('g', []) => {
let mode = match next_param_or(0) {
0 => TabulationClearMode::Current,
@@ -1572,6 +1630,7 @@ where
// Handle sync updates opaquely.
if param == NamedPrivateMode::SyncUpdate as u16 {
self.state.sync_state.timeout.set_timeout(SYNC_UPDATE_TIMEOUT);
+ self.terminated = true;
}
handler.set_private_mode(PrivateMode::new(param))
@@ -1787,6 +1846,11 @@ where
_ => unhandled!(),
}
}
+
+ #[inline]
+ fn terminated(&self) -> bool {
+ self.terminated
+ }
}
#[inline]
@@ -1969,7 +2033,7 @@ pub mod C0 {
/// Unit Separator.
pub const US: u8 = 0x1F;
/// Delete, should be ignored by terminal.
- pub const DEL: u8 = 0x7f;
+ pub const DEL: u8 = 0x7F;
}
// Tests for parsing escape sequences.
@@ -1980,22 +2044,24 @@ mod tests {
use super::*;
#[derive(Default)]
- pub struct TestSyncHandler;
+ pub struct TestSyncHandler {
+ is_sync: usize,
+ }
impl Timeout for TestSyncHandler {
#[inline]
fn set_timeout(&mut self, _: Duration) {
- unreachable!()
+ self.is_sync += 1;
}
#[inline]
fn clear_timeout(&mut self) {
- unreachable!()
+ self.is_sync = 0;
}
#[inline]
fn pending_timeout(&self) -> bool {
- false
+ self.is_sync != 0
}
}
@@ -2054,72 +2120,60 @@ mod tests {
#[test]
fn parse_control_attribute() {
- static BYTES: &[u8] = &[0x1b, b'[', b'1', b'm'];
+ static BYTES: &[u8] = &[0x1B, b'[', b'1', b'm'];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in BYTES {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, BYTES);
assert_eq!(handler.attr, Some(Attr::Bold));
}
#[test]
fn parse_terminal_identity_csi() {
- let bytes: &[u8] = &[0x1b, b'[', b'1', b'c'];
+ let bytes: &[u8] = &[0x1B, b'[', b'1', b'c'];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
assert!(!handler.identity_reported);
handler.reset_state();
- let bytes: &[u8] = &[0x1b, b'[', b'c'];
+ let bytes: &[u8] = &[0x1B, b'[', b'c'];
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
assert!(handler.identity_reported);
handler.reset_state();
- let bytes: &[u8] = &[0x1b, b'[', b'0', b'c'];
+ let bytes: &[u8] = &[0x1B, b'[', b'0', b'c'];
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
assert!(handler.identity_reported);
}
#[test]
fn parse_terminal_identity_esc() {
- let bytes: &[u8] = &[0x1b, b'Z'];
+ let bytes: &[u8] = &[0x1B, b'Z'];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
assert!(handler.identity_reported);
handler.reset_state();
- let bytes: &[u8] = &[0x1b, b'#', b'Z'];
+ let bytes: &[u8] = &[0x1B, b'#', b'Z'];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
assert!(!handler.identity_reported);
handler.reset_state();
@@ -2128,16 +2182,14 @@ mod tests {
#[test]
fn parse_truecolor_attr() {
static BYTES: &[u8] = &[
- 0x1b, b'[', b'3', b'8', b';', b'2', b';', b'1', b'2', b'8', b';', b'6', b'6', b';',
+ 0x1B, b'[', b'3', b'8', b';', b'2', b';', b'1', b'2', b'8', b';', b'6', b'6', b';',
b'2', b'5', b'5', b'm',
];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in BYTES {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, BYTES);
let spec = Rgb { r: 128, g: 66, b: 255 };
@@ -2148,38 +2200,34 @@ mod tests {
#[test]
fn parse_zsh_startup() {
static BYTES: &[u8] = &[
- 0x1b, b'[', b'1', b'm', 0x1b, b'[', b'7', b'm', b'%', 0x1b, b'[', b'2', b'7', b'm',
- 0x1b, b'[', b'1', b'm', 0x1b, b'[', b'0', b'm', b' ', b' ', b' ', b' ', b' ', b' ',
+ 0x1B, b'[', b'1', b'm', 0x1B, b'[', b'7', b'm', b'%', 0x1B, b'[', b'2', b'7', b'm',
+ 0x1B, b'[', b'1', b'm', 0x1B, b'[', b'0', b'm', b' ', b' ', b' ', b' ', b' ', b' ',
b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ', b' ',
- b' ', b' ', b' ', b'\r', b' ', b'\r', b'\r', 0x1b, b'[', b'0', b'm', 0x1b, b'[', b'2',
- b'7', b'm', 0x1b, b'[', b'2', b'4', b'm', 0x1b, b'[', b'J', b'j', b'w', b'i', b'l',
- b'm', b'@', b'j', b'w', b'i', b'l', b'm', b'-', b'd', b'e', b's', b'k', b' ', 0x1b,
- b'[', b'0', b'1', b';', b'3', b'2', b'm', 0xe2, 0x9e, 0x9c, b' ', 0x1b, b'[', b'0',
- b'1', b';', b'3', b'2', b'm', b' ', 0x1b, b'[', b'3', b'6', b'm', b'~', b'/', b'c',
+ b' ', b' ', b' ', b'\r', b' ', b'\r', b'\r', 0x1B, b'[', b'0', b'm', 0x1B, b'[', b'2',
+ b'7', b'm', 0x1B, b'[', b'2', b'4', b'm', 0x1B, b'[', b'J', b'j', b'w', b'i', b'l',
+ b'm', b'@', b'j', b'w', b'i', b'l', b'm', b'-', b'd', b'e', b's', b'k', b' ', 0x1B,
+ b'[', b'0', b'1', b';', b'3', b'2', b'm', 0xE2, 0x9E, 0x9C, b' ', 0x1B, b'[', b'0',
+ b'1', b';', b'3', b'2', b'm', b' ', 0x1B, b'[', b'3', b'6', b'm', b'~', b'/', b'c',
b'o', b'd', b'e',
];
let mut handler = MockHandler::default();
let mut parser = Processor::<TestSyncHandler>::new();
- for byte in BYTES {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, BYTES);
}
#[test]
fn parse_designate_g0_as_line_drawing() {
- static BYTES: &[u8] = &[0x1b, b'(', b'0'];
+ static BYTES: &[u8] = &[0x1B, b'(', b'0'];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in BYTES {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, BYTES);
assert_eq!(handler.index, CharsetIndex::G0);
assert_eq!(handler.charset, StandardCharset::SpecialCharacterAndLineDrawing);
@@ -2187,37 +2235,35 @@ mod tests {
#[test]
fn parse_designate_g1_as_line_drawing_and_invoke() {
- static BYTES: &[u8] = &[0x1b, b')', b'0', 0x0e];
+ static BYTES: &[u8] = &[0x1B, b')', b'0', 0x0E];
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in &BYTES[..3] {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, &BYTES[..3]);
assert_eq!(handler.index, CharsetIndex::G1);
assert_eq!(handler.charset, StandardCharset::SpecialCharacterAndLineDrawing);
let mut handler = MockHandler::default();
- parser.advance(&mut handler, BYTES[3]);
+ parser.advance(&mut handler, &[BYTES[3]]);
assert_eq!(handler.index, CharsetIndex::G1);
}
#[test]
fn parse_valid_rgb_colors() {
- assert_eq!(xparse_color(b"rgb:f/e/d"), Some(Rgb { r: 0xff, g: 0xee, b: 0xdd }));
- assert_eq!(xparse_color(b"rgb:11/aa/ff"), Some(Rgb { r: 0x11, g: 0xaa, b: 0xff }));
- assert_eq!(xparse_color(b"rgb:f/ed1/cb23"), Some(Rgb { r: 0xff, g: 0xec, b: 0xca }));
- assert_eq!(xparse_color(b"rgb:ffff/0/0"), Some(Rgb { r: 0xff, g: 0x0, b: 0x0 }));
+ assert_eq!(xparse_color(b"rgb:f/e/d"), Some(Rgb { r: 0xFF, g: 0xEE, b: 0xDD }));
+ assert_eq!(xparse_color(b"rgb:11/aa/ff"), Some(Rgb { r: 0x11, g: 0xAA, b: 0xFF }));
+ assert_eq!(xparse_color(b"rgb:f/ed1/cb23"), Some(Rgb { r: 0xFF, g: 0xEC, b: 0xCA }));
+ assert_eq!(xparse_color(b"rgb:ffff/0/0"), Some(Rgb { r: 0xFF, g: 0x0, b: 0x0 }));
}
#[test]
fn parse_valid_legacy_rgb_colors() {
- assert_eq!(xparse_color(b"#1af"), Some(Rgb { r: 0x10, g: 0xa0, b: 0xf0 }));
- assert_eq!(xparse_color(b"#11aaff"), Some(Rgb { r: 0x11, g: 0xaa, b: 0xff }));
- assert_eq!(xparse_color(b"#110aa0ff0"), Some(Rgb { r: 0x11, g: 0xaa, b: 0xff }));
- assert_eq!(xparse_color(b"#1100aa00ff00"), Some(Rgb { r: 0x11, g: 0xaa, b: 0xff }));
+ assert_eq!(xparse_color(b"#1af"), Some(Rgb { r: 0x10, g: 0xA0, b: 0xF0 }));
+ assert_eq!(xparse_color(b"#11aaff"), Some(Rgb { r: 0x11, g: 0xAA, b: 0xFF }));
+ assert_eq!(xparse_color(b"#110aa0ff0"), Some(Rgb { r: 0x11, g: 0xAA, b: 0xFF }));
+ assert_eq!(xparse_color(b"#1100aa00ff00"), Some(Rgb { r: 0x11, g: 0xAA, b: 0xFF }));
}
#[test]
@@ -2254,11 +2300,9 @@ mod tests {
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
- assert_eq!(handler.color, Some(Rgb { r: 0xf0, g: 0xf0, b: 0xf0 }));
+ assert_eq!(handler.color, Some(Rgb { r: 0xF0, g: 0xF0, b: 0xF0 }));
}
#[test]
@@ -2268,9 +2312,7 @@ mod tests {
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
assert_eq!(handler.reset_colors, vec![1]);
}
@@ -2282,9 +2324,7 @@ mod tests {
let mut parser = Processor::<TestSyncHandler>::new();
let mut handler = MockHandler::default();
- for byte in bytes {
- parser.advance(&mut handler, *byte);
- }
+ parser.advance(&mut handler, bytes);
let expected: Vec<usize> = (0..256).collect();