aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/parselog.rs4
-rw-r--r--src/definitions.rs4
-rw-r--r--src/lib.rs121
-rw-r--r--src/table.rs4
-rw-r--r--utf8parse/src/lib.rs1
-rw-r--r--utf8parse/src/types.rs2
-rw-r--r--vte_generate_state_changes/src/lib.rs4
7 files changed, 83 insertions, 57 deletions
diff --git a/examples/parselog.rs b/examples/parselog.rs
index 83ba2b5..331a003 100644
--- a/examples/parselog.rs
+++ b/examples/parselog.rs
@@ -30,8 +30,8 @@ impl vte::Perform for Log {
println!("[unhook]");
}
- fn osc_dispatch(&mut self, params: &[&[u8]]) {
- println!("[osc_dispatch] params={:?}", params);
+ fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
+ println!("[osc_dispatch] params={:?} bell_terminated={}", params, bell_terminated);
}
fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) {
diff --git a/src/definitions.rs b/src/definitions.rs
index 568eb41..5d01623 100644
--- a/src/definitions.rs
+++ b/src/definitions.rs
@@ -50,7 +50,7 @@ pub enum Action {
impl State {
#[inline]
- pub fn entry_action(&self) -> Action {
+ pub fn entry_action(self) -> Action {
match self {
State::CsiEntry | State::DcsEntry | State::Escape => Action::Clear,
State::DcsPassthrough => Action::Hook,
@@ -60,7 +60,7 @@ impl State {
}
#[inline]
- pub fn exit_action(&self) -> Action {
+ pub fn exit_action(self) -> Action {
match self {
State::DcsPassthrough => Action::Unhook,
State::OscString => Action::OscEnd,
diff --git a/src/lib.rs b/src/lib.rs
index e0f4331..1402108 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,6 +30,7 @@
//! [`Parser`]: struct.Parser.html
//! [`Perform`]: trait.Perform.html
//! [Paul Williams' ANSI parser state machine]: https://vt100.net/emu/dec_ansi_parser
+#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use, clippy::wrong_pub_self_convention)]
#![cfg_attr(all(feature = "nightly", test), feature(test))]
#![cfg_attr(feature = "no_std", no_std)]
@@ -179,7 +180,7 @@ impl Parser {
///
/// The aliasing is needed here for multiple slices into self.osc_raw
#[inline]
- fn osc_dispatch<P: Perform>(&self, performer: &mut P) {
+ fn osc_dispatch<P: Perform>(&self, performer: &mut P, byte: u8) {
let mut slices: [MaybeUninit<&[u8]>; MAX_PARAMS] =
unsafe { MaybeUninit::uninit().assume_init() };
@@ -191,7 +192,7 @@ impl Parser {
unsafe {
let num_params = self.osc_num_params;
let params = &slices[..num_params] as *const [MaybeUninit<&[u8]>] as *const [&[u8]];
- performer.osc_dispatch(&*params);
+ performer.osc_dispatch(&*params, byte == 0x07);
}
}
@@ -268,7 +269,7 @@ impl Parser {
self.osc_num_params += 1;
},
}
- self.osc_dispatch(performer);
+ self.osc_dispatch(performer, byte);
},
Action::Unhook => performer.unhook(),
Action::CsiDispatch => {
@@ -343,13 +344,13 @@ impl Parser {
/// referenced if something isn't clear. If the site disappears at some point in
/// the future, consider checking archive.org.
pub trait Perform {
- /// Draw a character to the screen and update states
+ /// Draw a character to the screen and update states.
fn print(&mut self, _: char);
- /// Execute a C0 or C1 control function
+ /// Execute a C0 or C1 control function.
fn execute(&mut self, byte: u8);
- /// Invoked when a final character arrives in first part of device control string
+ /// Invoked when a final character arrives in first part of device control string.
///
/// The control function should be determined from the private marker, final character, and
/// execute with a parameter list. A handler should be selected for remaining characters in the
@@ -358,27 +359,27 @@ pub trait Perform {
///
/// The `ignore` flag indicates that more than two intermediates arrived and
/// subsequent characters were ignored.
- fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, _: char);
+ fn hook(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, action: char);
/// Pass bytes as part of a device control string to the handle chosen in `hook`. C0 controls
/// will also be passed to the handler.
fn put(&mut self, byte: u8);
- /// Called when a device control string is terminated
+ /// Called when a device control string is terminated.
///
/// The previously selected handler should be notified that the DCS has
/// terminated.
fn unhook(&mut self);
- /// Dispatch an operating system command
- fn osc_dispatch(&mut self, params: &[&[u8]]);
+ /// Dispatch an operating system command.
+ fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool);
/// A final character has arrived for a CSI sequence
///
/// The `ignore` flag indicates that either more than two intermediates arrived
/// or the number of parameters exceeded the maximum supported length,
/// and subsequent characters were ignored.
- fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, _: char);
+ fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, action: char);
/// The final character of an escape sequence has arrived.
///
@@ -409,6 +410,7 @@ mod tests {
#[derive(Default)]
struct OscDispatcher {
dispatched_osc: bool,
+ bell_terminated: bool,
params: Vec<Vec<u8>>,
}
@@ -424,9 +426,10 @@ mod tests {
fn unhook(&mut self) {}
- fn osc_dispatch(&mut self, params: &[&[u8]]) {
+ fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
// Set a flag so we know these assertions all run
self.dispatched_osc = true;
+ self.bell_terminated = bell_terminated;
self.params = params.iter().map(|p| p.to_vec()).collect();
}
@@ -467,7 +470,7 @@ mod tests {
fn unhook(&mut self) {}
- fn osc_dispatch(&mut self, _params: &[&[u8]]) {}
+ fn osc_dispatch(&mut self, _params: &[&[u8]], _bell_terminated: bool) {}
fn csi_dispatch(&mut self, params: &[i64], _intermediates: &[u8], ignore: bool, _c: char) {
self.dispatched_csi = true;
@@ -511,7 +514,7 @@ mod tests {
self.dispatched_dcs = true;
}
- fn osc_dispatch(&mut self, _params: &[&[u8]]) {}
+ fn osc_dispatch(&mut self, _params: &[&[u8]], _bell_terminated: bool) {}
fn csi_dispatch(
&mut self,
@@ -534,12 +537,9 @@ mod tests {
#[test]
fn parse_osc() {
- // Create dispatcher and check state
let mut dispatcher = OscDispatcher::default();
- assert_eq!(dispatcher.dispatched_osc, false);
-
- // Run parser using OSC_BYTES
let mut parser = Parser::new();
+
for byte in OSC_BYTES {
parser.advance(&mut dispatcher, *byte);
}
@@ -553,12 +553,9 @@ mod tests {
#[test]
fn parse_empty_osc() {
- // Create dispatcher and check state
let mut dispatcher = OscDispatcher::default();
- assert_eq!(dispatcher.dispatched_osc, false);
-
- // Run parser using OSC_BYTES
let mut parser = Parser::new();
+
for byte in &[0x1b, 0x5d, 0x07] {
parser.advance(&mut dispatcher, *byte);
}
@@ -570,13 +567,9 @@ mod tests {
#[test]
fn parse_osc_max_params() {
static INPUT: &[u8] = b"\x1b];;;;;;;;;;;;;;;;;\x1b";
-
- // Create dispatcher and check state
let mut dispatcher = OscDispatcher::default();
- assert_eq!(dispatcher.dispatched_osc, false);
-
- // Run parser using OSC_BYTES
let mut parser = Parser::new();
+
for byte in INPUT {
parser.advance(&mut dispatcher, *byte);
}
@@ -590,6 +583,48 @@ mod tests {
}
#[test]
+ fn osc_bell_terminated() {
+ static INPUT: &[u8] = b"\x1b]11;ff/00/ff\x07";
+ let mut dispatcher = OscDispatcher::default();
+ let mut parser = Parser::new();
+
+ for byte in INPUT {
+ parser.advance(&mut dispatcher, *byte);
+ }
+
+ assert!(dispatcher.dispatched_osc);
+ assert!(dispatcher.bell_terminated);
+ }
+
+ #[test]
+ fn osc_c1_st_terminated() {
+ static INPUT: &[u8] = b"\x1b]11;ff/00/ff\x9c";
+ let mut dispatcher = OscDispatcher::default();
+ let mut parser = Parser::new();
+
+ for byte in INPUT {
+ parser.advance(&mut dispatcher, *byte);
+ }
+
+ assert!(dispatcher.dispatched_osc);
+ assert!(!dispatcher.bell_terminated);
+ }
+
+ #[test]
+ fn osc_c0_st_terminated() {
+ static INPUT: &[u8] = b"\x1b]11;ff/00/ff\x1b\\";
+ let mut dispatcher = OscDispatcher::default();
+ let mut parser = Parser::new();
+
+ for byte in INPUT {
+ parser.advance(&mut dispatcher, *byte);
+ }
+
+ assert!(dispatcher.dispatched_osc);
+ assert!(!dispatcher.bell_terminated);
+ }
+
+ #[test]
fn parse_csi_max_params() {
// This will build a list of repeating '1;'s
// The length is MAX_PARAMS - 1 because the last semicolon is interpreted
@@ -597,12 +632,9 @@ mod tests {
let params = std::iter::repeat("1;").take(MAX_PARAMS - 1).collect::<String>();
let input = format!("\x1b[{}p", &params[..]).into_bytes();
- // Create dispatcher and check state
let mut dispatcher = CsiDispatcher::default();
- assert!(!dispatcher.dispatched_csi);
-
- // Run parser using INPUT
let mut parser = Parser::new();
+
for byte in input {
parser.advance(&mut dispatcher, byte);
}
@@ -622,12 +654,9 @@ mod tests {
let params = std::iter::repeat("1;").take(MAX_PARAMS).collect::<String>();
let input = format!("\x1b[{}p", &params[..]).into_bytes();
- // Create dispatcher and check state
let mut dispatcher = CsiDispatcher::default();
- assert!(!dispatcher.dispatched_csi);
-
- // Run parser using INPUT
let mut parser = Parser::new();
+
for byte in input {
parser.advance(&mut dispatcher, byte);
}
@@ -656,9 +685,8 @@ mod tests {
fn parse_semi_set_underline() {
// Create dispatcher and check state
let mut dispatcher = CsiDispatcher::default();
-
- // Run parser using OSC_BYTES
let mut parser = Parser::new();
+
for byte in b"\x1b[;4m" {
parser.advance(&mut dispatcher, *byte);
}
@@ -671,10 +699,9 @@ mod tests {
fn parse_long_csi_param() {
// The important part is the parameter, which is (i64::MAX + 1)
static INPUT: &[u8] = b"\x1b[9223372036854775808m";
-
let mut dispatcher = CsiDispatcher::default();
-
let mut parser = Parser::new();
+
for byte in INPUT {
parser.advance(&mut dispatcher, *byte);
}
@@ -689,12 +716,9 @@ mod tests {
0x5f, 0x28, 0xe3, 0x83, 0x84, 0x29, 0x5f, 0x2f, 0xc2, 0xaf, 0x27, 0x20, 0x26, 0x26,
0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x31, 0x07,
];
-
- // Create dispatcher and check state
- let mut dispatcher = OscDispatcher { params: vec![], dispatched_osc: false };
-
- // Run parser using OSC_BYTES
+ let mut dispatcher = OscDispatcher::default();
let mut parser = Parser::new();
+
for byte in INPUT {
parser.advance(&mut dispatcher, *byte);
}
@@ -708,12 +732,9 @@ mod tests {
fn parse_dcs() {
static INPUT: &[u8] =
&[0x1b, 0x50, 0x30, 0x3b, 0x31, 0x7c, 0x31, 0x37, 0x2f, 0x61, 0x62, 0x9c];
-
- // Create dispatcher and check state
let mut dispatcher = DcsDispatcher::default();
-
- // Run parser using OSC_BYTES
let mut parser = Parser::new();
+
for byte in INPUT {
parser.advance(&mut dispatcher, *byte);
}
@@ -792,8 +813,8 @@ mod bench {
fn unhook(&mut self) {}
- fn osc_dispatch(&mut self, params: &[&[u8]]) {
- black_box(params);
+ fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
+ black_box((params, bell_terminated));
}
fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) {
diff --git a/src/table.rs b/src/table.rs
index c19e4ab..392cf05 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -170,6 +170,8 @@ generate_state_changes!(state_changes, {
0x08..=0x17 => (Anywhere, Ignore),
0x19 => (Anywhere, Ignore),
0x1c..=0x1f => (Anywhere, Ignore),
- 0x20..=0xff => (Anywhere, OscPut),
+ 0x20..=0x9b => (Anywhere, OscPut),
+ 0x9c => (Ground, None),
+ 0x9d..=0xff => (Anywhere, OscPut),
}
});
diff --git a/utf8parse/src/lib.rs b/utf8parse/src/lib.rs
index c092647..6168e2e 100644
--- a/utf8parse/src/lib.rs
+++ b/utf8parse/src/lib.rs
@@ -3,6 +3,7 @@
//! This module implements a table-driven UTF-8 parser which should
//! theoretically contain the minimal number of branches (1). The only branch is
//! on the `Action` returned from unpacking a transition.
+#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use, clippy::wrong_pub_self_convention)]
#![cfg_attr(all(feature = "nightly", test), feature(test))]
#![no_std]
diff --git a/utf8parse/src/types.rs b/utf8parse/src/types.rs
index 5a70b3c..77a79cc 100644
--- a/utf8parse/src/types.rs
+++ b/utf8parse/src/types.rs
@@ -58,7 +58,7 @@ impl State {
/// This takes the current state and input byte into consideration, to determine the next state
/// and any action that should be taken.
#[inline]
- pub fn advance(&self, byte: u8) -> (State, Action) {
+ pub fn advance(self, byte: u8) -> (State, Action) {
match self {
State::Ground => match byte {
0x00..=0x7f => (State::Ground, Action::EmitByte),
diff --git a/vte_generate_state_changes/src/lib.rs b/vte_generate_state_changes/src/lib.rs
index 5cfb3ac..cae8f65 100644
--- a/vte_generate_state_changes/src/lib.rs
+++ b/vte_generate_state_changes/src/lib.rs
@@ -1,3 +1,5 @@
+#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use, clippy::wrong_pub_self_convention)]
+
extern crate proc_macro;
use std::iter::Peekable;
@@ -53,7 +55,7 @@ fn states_stream(iter: &mut impl Iterator<Item = TokenTree>) -> TokenStream {
/// Generate the array assignment statements for one origin state.
fn state_entry_stream(iter: &mut Peekable<token_stream::IntoIter>) -> TokenStream {
// Origin state name
- let state = iter.next().unwrap().into();
+ let state = iter.next().unwrap();
// Token stream with all the byte->target mappings
let mut changes_stream = next_group(iter).into_iter().peekable();