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:
parent
192eaeb3ff
commit
5440cbe521
@ -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");
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user