1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

replace vte with our own vtparse crate

This enables using large OSC buffers in a form that we can publish
to crates.io without blocking on an external crate.  Large OSC
buffers are important both for some tunnelling use cases and for
eg: iTerm2 image protocol handling.
This commit is contained in:
Wez Furlong 2019-06-29 16:28:39 -07:00
parent 192eaeb3ff
commit 5440cbe521
5 changed files with 51 additions and 41 deletions

View File

@ -1859,7 +1859,7 @@ impl TerminalState {
}
}
/// A helper struct for implementing `vte::Perform` while compartmentalizing
/// A helper struct for implementing `vtparse::VTActor` while compartmentalizing
/// the terminal state and the embedding/host terminal interface
pub(crate) struct Performer<'a> {
pub state: &'a mut TerminalState,
@ -2029,7 +2029,7 @@ impl<'a> Performer<'a> {
match esc {
Esc::Code(EscCode::StringTerminator) => {
// String Terminator (ST); explicitly has nothing to do here, as its purpose is
// handled by vte::Parser
// handled implicitly through a state transition in the vtparse state tables.
}
Esc::Code(EscCode::DecApplicationKeyPad) => {
debug!("DECKPAM on");

View File

@ -34,8 +34,6 @@ smallvec = "0.6"
terminfo = "0.6"
unicode-segmentation = "1.2"
unicode-width = "0.1"
# https://github.com/jwilm/vte/pull/20
vte = { git = "https://github.com/wez/vte", branch="oscbigbuf" }
vtparse = { path="../vtparse"}
[dev-dependencies]

View File

@ -1108,7 +1108,7 @@ pub enum Font {
/// it parses them out from the input sequence.
struct CSIParser<'a> {
intermediates: &'a [u8],
/// From vte::Perform: this flag is set when more than two intermediates
/// this flag is set when more than two intermediates
/// arrived and subsequent characters were ignored.
ignored_extra_intermediates: bool,
control: char,

View File

@ -2,7 +2,7 @@ use crate::escape::{Action, DeviceControlMode, Esc, OperatingSystemCommand, CSI}
use log::error;
use num;
use std::cell::RefCell;
use vte;
use vtparse::{VTActor, VTParser};
/// The `Parser` struct holds the state machine that is used to decode
/// a sequence of bytes. The byte sequence can be streaming into the
@ -11,7 +11,7 @@ use vte;
/// decoded, or have it return a `Vec<Action>` holding zero-or-more
/// decoded actions.
pub struct Parser {
state_machine: vte::Parser,
state_machine: VTParser,
}
impl Default for Parser {
@ -23,7 +23,7 @@ impl Default for Parser {
impl Parser {
pub fn new() -> Self {
Self {
state_machine: vte::Parser::new(),
state_machine: VTParser::new(),
}
}
@ -31,9 +31,7 @@ impl Parser {
let mut perform = Performer {
callback: &mut callback,
};
for b in bytes {
self.state_machine.advance(&mut perform, *b);
}
self.state_machine.parse(bytes, &mut perform);
}
/// A specialized version of the parser that halts after recognizing the
@ -58,7 +56,7 @@ impl Parser {
},
};
for (idx, b) in bytes.iter().enumerate() {
self.state_machine.advance(&mut perform, *b);
self.state_machine.parse_byte(*b, &mut perform);
if first.borrow().is_some() {
// if we recognized an action, record the iterator index
first_idx = Some(idx);
@ -86,11 +84,11 @@ impl Parser {
let mut actions = Vec::new();
let mut first_idx = None;
for (idx, b) in bytes.iter().enumerate() {
self.state_machine.advance(
self.state_machine.parse_byte(
*b,
&mut Performer {
callback: &mut |action| actions.push(action),
},
*b,
);
if !actions.is_empty() {
// if we recognized any actions, record the iterator index
@ -106,19 +104,24 @@ struct Performer<'a, F: FnMut(Action) + 'a> {
callback: &'a mut F,
}
impl<'a, F: FnMut(Action)> vte::Perform for Performer<'a, F> {
impl<'a, F: FnMut(Action)> VTActor for Performer<'a, F> {
fn print(&mut self, c: char) {
(self.callback)(Action::Print(c));
}
fn execute(&mut self, byte: u8) {
fn execute_c0_or_c1(&mut self, byte: u8) {
match num::FromPrimitive::from_u8(byte) {
Some(code) => (self.callback)(Action::Control(code)),
None => error!("impossible C0/C1 control code {:?} was dropped", byte),
}
}
fn hook(&mut self, params: &[i64], intermediates: &[u8], ignored_extra_intermediates: bool) {
fn dcs_hook(
&mut self,
params: &[i64],
intermediates: &[u8],
ignored_extra_intermediates: bool,
) {
(self.callback)(Action::DeviceControl(Box::new(DeviceControlMode::Enter {
params: params.to_vec(),
intermediates: intermediates.to_vec(),
@ -126,13 +129,13 @@ impl<'a, F: FnMut(Action)> vte::Perform for Performer<'a, F> {
})));
}
fn put(&mut self, data: u8) {
fn dcs_put(&mut self, data: u8) {
(self.callback)(Action::DeviceControl(Box::new(DeviceControlMode::Data(
data,
))));
}
fn unhook(&mut self) {
fn dcs_unhook(&mut self) {
(self.callback)(Action::DeviceControl(Box::new(DeviceControlMode::Exit)));
}
@ -146,9 +149,14 @@ impl<'a, F: FnMut(Action)> vte::Perform for Performer<'a, F> {
params: &[i64],
intermediates: &[u8],
ignored_extra_intermediates: bool,
control: char,
control: u8,
) {
for action in CSI::parse(params, intermediates, ignored_extra_intermediates, control) {
for action in CSI::parse(
params,
intermediates,
ignored_extra_intermediates,
control as char,
) {
(self.callback)(Action::CSI(action));
}
}

View File

@ -254,7 +254,6 @@ impl VTParser {
}
fn action(&mut self, action: Action, param: u8, actor: &mut dyn VTActor) {
eprintln!("action {:?} {}", action, param);
match action {
Action::None | Action::Ignore => {}
Action::Print => actor.print(param as char),
@ -403,27 +402,32 @@ impl VTParser {
self.utf8_parser.advance(&mut decoder, byte);
}
#[inline(always)]
pub fn parse_byte(&mut self, byte: u8, actor: &mut dyn VTActor) {
// While in utf-8 parsing mode, co-opt the vt state
// table and instead use the utf-8 state table from the
// parser. It will drop us back into the Ground state
// after each recognized (or invalid) codepoint.
if self.state == State::Utf8Sequence {
self.next_utf8(actor, byte);
return;
}
let (action, state) = lookup(self.state, byte);
if state != self.state {
self.action(lookup_exit(self.state), 0, actor);
self.action(action, byte, actor);
self.action(lookup_entry(state), 0, actor);
self.state = state;
} else {
self.action(action, byte, actor);
}
}
pub fn parse(&mut self, bytes: &[u8], actor: &mut dyn VTActor) {
for b in bytes {
// While in utf-8 parsing mode, co-opt the vt state
// table and instead use the utf-8 state table from the
// parser. It will drop us back into the Ground state
// after each recognized (or invalid) codepoint.
if self.state == State::Utf8Sequence {
self.next_utf8(actor, *b);
continue;
}
let (action, state) = lookup(self.state, *b);
if state != self.state {
self.action(lookup_exit(self.state), 0, actor);
self.action(action, *b, actor);
self.action(lookup_entry(state), 0, actor);
self.state = state;
} else {
self.action(action, *b, actor);
}
self.parse_byte(*b, actor);
}
}
}