|
|
@ -4,11 +4,12 @@ use crate::{
|
|
|
|
log::*,
|
|
|
|
log::*,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use anyhow::{Context, Result};
|
|
|
|
use anyhow::{Context, Result};
|
|
|
|
|
|
|
|
use log::error;
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
|
cell::{RefCell, RefMut},
|
|
|
|
cell::{RefCell, RefMut},
|
|
|
|
collections::VecDeque,
|
|
|
|
collections::VecDeque,
|
|
|
|
fmt,
|
|
|
|
fmt,
|
|
|
|
rc::Rc,
|
|
|
|
rc::{Rc, Weak},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
use windows::Win32::{Foundation::HANDLE, System::Console};
|
|
|
|
use windows::Win32::{Foundation::HANDLE, System::Console};
|
|
|
|
|
|
|
|
|
|
|
@ -181,8 +182,13 @@ impl Reader {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if is_escape_start(&record) {
|
|
|
|
if is_escape_start(&record) {
|
|
|
|
let escape = self.next_escape_sequence()?;
|
|
|
|
match self.next_escape_sequence() {
|
|
|
|
return Ok(Event::Escape(escape));
|
|
|
|
Ok(escape) => return Ok(Event::Escape(escape)),
|
|
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
|
|
error!("{e}");
|
|
|
|
|
|
|
|
return self.next();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let event: Event = record.into();
|
|
|
|
let event: Event = record.into();
|
|
|
@ -239,9 +245,12 @@ impl Reader {
|
|
|
|
panic!();
|
|
|
|
panic!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let c = as_escape_character(&record).ok_or(InputError::BadEscapeSequence)?;
|
|
|
|
let c = as_escape_character(&record)
|
|
|
|
if let Some(escape) = self.escapes.step(c) {
|
|
|
|
.ok_or(InputError::UnexpectedInputRecordDuringEscapeParting)?;
|
|
|
|
return Ok(escape);
|
|
|
|
match self.escapes.step(c) {
|
|
|
|
|
|
|
|
EscapeStep::Continue => {}
|
|
|
|
|
|
|
|
EscapeStep::End(escape) => return Ok(escape),
|
|
|
|
|
|
|
|
EscapeStep::Abort(s) => return Err(InputError::BadEscapeSequence(s).into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -333,13 +342,14 @@ impl From<Console::INPUT_RECORD> for Event {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A reference to a target node in a prefix tree, used for manipulating the prefix tree
|
|
|
|
/// A reference to a target node in a prefix tree, used for manipulating the prefix tree
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct EscapeCursor {
|
|
|
|
pub struct EscapeCursor {
|
|
|
|
target: Rc<EscapeNode>,
|
|
|
|
target: Rc<EscapeNode>,
|
|
|
|
root: Rc<EscapeNode>,
|
|
|
|
root: Rc<EscapeNode>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// A node in a prefix tree. This prefix tree is used to parse strings into escape sequences
|
|
|
|
/// A node in a prefix tree. This prefix tree is used to parse strings into escape sequences. This
|
|
|
|
|
|
|
|
/// prefix tree is special in that there are no values in the intermediate nodes of the tree.
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum EscapeNode {
|
|
|
|
pub enum EscapeNode {
|
|
|
|
Root {
|
|
|
|
Root {
|
|
|
@ -347,15 +357,18 @@ pub enum EscapeNode {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Nonterminal {
|
|
|
|
Nonterminal {
|
|
|
|
c: char,
|
|
|
|
c: char,
|
|
|
|
|
|
|
|
parent: Weak<EscapeNode>,
|
|
|
|
children: RefCell<Vec<Rc<EscapeNode>>>,
|
|
|
|
children: RefCell<Vec<Rc<EscapeNode>>>,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Terminal {
|
|
|
|
Terminal {
|
|
|
|
c: char,
|
|
|
|
c: char,
|
|
|
|
|
|
|
|
parent: Weak<EscapeNode>,
|
|
|
|
v: Escape,
|
|
|
|
v: Escape,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl EscapeNode {
|
|
|
|
impl EscapeNode {
|
|
|
|
|
|
|
|
/// Creates a new prefix tree mapping character sequences to structured escape codes
|
|
|
|
pub fn new() -> EscapeCursor {
|
|
|
|
pub fn new() -> EscapeCursor {
|
|
|
|
let root = Rc::new(EscapeNode::Root {
|
|
|
|
let root = Rc::new(EscapeNode::Root {
|
|
|
|
children: RefCell::new(Vec::new()),
|
|
|
|
children: RefCell::new(Vec::new()),
|
|
|
@ -382,51 +395,44 @@ impl EscapeNode {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn child(&self, c: char) -> Option<Rc<EscapeNode>> {
|
|
|
|
fn parent(&self) -> Option<Rc<EscapeNode>> {
|
|
|
|
for child in self.children().iter_mut() {
|
|
|
|
match self {
|
|
|
|
if child.char() == c {
|
|
|
|
EscapeNode::Root { .. } => None,
|
|
|
|
return Some(Rc::clone(child));
|
|
|
|
EscapeNode::Nonterminal { parent, .. } => parent.upgrade(),
|
|
|
|
}
|
|
|
|
EscapeNode::Terminal { parent, .. } => parent.upgrade(),
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn child_nonterminal(&self, c: char) -> Rc<EscapeNode> {
|
|
|
|
|
|
|
|
for child in self.children().iter_mut() {
|
|
|
|
|
|
|
|
if child.char() == c {
|
|
|
|
|
|
|
|
return Rc::clone(child);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let child = Rc::new(EscapeNode::Nonterminal {
|
|
|
|
|
|
|
|
c,
|
|
|
|
|
|
|
|
children: RefCell::new(Vec::new()),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
self.children().push(Rc::clone(&child));
|
|
|
|
|
|
|
|
child
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn add_child_terminal(&self, c: char, v: Escape) {
|
|
|
|
fn child(&self, c: char) -> Option<Rc<EscapeNode>> {
|
|
|
|
for child in self.children().iter_mut() {
|
|
|
|
for child in self.children().iter_mut() {
|
|
|
|
if child.char() == c {
|
|
|
|
if child.char() == c {
|
|
|
|
panic!();
|
|
|
|
return Some(Rc::clone(child));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let child = Rc::new(EscapeNode::Terminal { c, v });
|
|
|
|
None
|
|
|
|
self.children().push(child);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl EscapeCursor {
|
|
|
|
impl EscapeCursor {
|
|
|
|
fn step(&mut self, c: char) -> Option<Escape> {
|
|
|
|
/// advances our cursor by one step. We look at the current position and descend the tree into
|
|
|
|
let child = self.target.child(c)?;
|
|
|
|
/// the node described by the target character. If that node is a terminal node, we return that
|
|
|
|
|
|
|
|
/// node's value.
|
|
|
|
|
|
|
|
fn step(&mut self, c: char) -> EscapeStep {
|
|
|
|
|
|
|
|
let child = match self.target.child(c) {
|
|
|
|
|
|
|
|
Some(c) => c,
|
|
|
|
|
|
|
|
None => {
|
|
|
|
|
|
|
|
let path = self.path();
|
|
|
|
|
|
|
|
return EscapeStep::Abort(format!("{path}{c}"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
match child.as_ref() {
|
|
|
|
match child.as_ref() {
|
|
|
|
EscapeNode::Terminal { v, .. } => {
|
|
|
|
EscapeNode::Terminal { v, .. } => {
|
|
|
|
self.reset();
|
|
|
|
self.reset();
|
|
|
|
Some(*v)
|
|
|
|
EscapeStep::End(*v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
_ => {
|
|
|
|
self.target = child;
|
|
|
|
self.target = child;
|
|
|
|
None
|
|
|
|
EscapeStep::Continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -435,14 +441,36 @@ impl EscapeCursor {
|
|
|
|
match self.target.child(c) {
|
|
|
|
match self.target.child(c) {
|
|
|
|
Some(child) => self.target = child,
|
|
|
|
Some(child) => self.target = child,
|
|
|
|
None => {
|
|
|
|
None => {
|
|
|
|
self.target = self.target.child_nonterminal(c);
|
|
|
|
for child in self.target.clone().children().iter() {
|
|
|
|
|
|
|
|
if child.char() == c {
|
|
|
|
|
|
|
|
self.target = Rc::clone(child);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let child = Rc::new(EscapeNode::Nonterminal {
|
|
|
|
|
|
|
|
c,
|
|
|
|
|
|
|
|
parent: Rc::downgrade(&self.target),
|
|
|
|
|
|
|
|
children: RefCell::new(Vec::new()),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
self.target.children().push(Rc::clone(&child));
|
|
|
|
|
|
|
|
self.target = child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// adds a terminal node into the tree as a child of the current node
|
|
|
|
/// adds a terminal node into the tree as a child of the current node
|
|
|
|
fn add_terminal(&mut self, c: char, v: Escape) {
|
|
|
|
fn add_terminal(&mut self, c: char, v: Escape) {
|
|
|
|
self.target.add_child_terminal(c, v);
|
|
|
|
for child in self.target.children().iter_mut() {
|
|
|
|
|
|
|
|
if child.char() == c {
|
|
|
|
|
|
|
|
panic!();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
let child = Rc::new(EscapeNode::Terminal {
|
|
|
|
|
|
|
|
c,
|
|
|
|
|
|
|
|
parent: Rc::downgrade(&self.target),
|
|
|
|
|
|
|
|
v,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
self.target.children().push(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// resets the cursor back to the top of the tree
|
|
|
|
/// resets the cursor back to the top of the tree
|
|
|
@ -467,6 +495,23 @@ impl EscapeCursor {
|
|
|
|
self.add_step(c);
|
|
|
|
self.add_step(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// renders as a string the path that takes us to the node to which we are currently pointed
|
|
|
|
|
|
|
|
fn path(&self) -> String {
|
|
|
|
|
|
|
|
let mut cursor = self.clone();
|
|
|
|
|
|
|
|
let mut chars = Vec::new();
|
|
|
|
|
|
|
|
while !cursor.is_at_root() {
|
|
|
|
|
|
|
|
chars.push(cursor.target.char());
|
|
|
|
|
|
|
|
cursor.target = cursor.target.parent().unwrap();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
chars.iter().rev().collect()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum EscapeStep {
|
|
|
|
|
|
|
|
Continue,
|
|
|
|
|
|
|
|
Abort(String),
|
|
|
|
|
|
|
|
End(Escape),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// generates a prefix tree used for parsing escape sequences
|
|
|
|
/// generates a prefix tree used for parsing escape sequences
|
|
|
|