aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ansi.rs77
-rw-r--r--src/event_loop.rs2
-rw-r--r--src/term/mod.rs5
-rw-r--r--tests/ref.rs17
4 files changed, 79 insertions, 22 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
index 8ff0a2e4..50dec9ac 100644
--- a/src/ansi.rs
+++ b/src/ansi.rs
@@ -31,6 +31,7 @@
//! should be, feel free to add it. Please try not to become overzealous and adding support for
//! sequences only used by folks trapped in 1988.
use std::ops::Range;
+use std::io;
use vte;
@@ -51,18 +52,24 @@ struct ProcessorState;
///
/// Processor creates a Performer when running advance and passes the Performer
/// to vte::Parser.
-struct Performer<'a, H: Handler + TermInfo + 'a> {
+struct Performer<'a, H: Handler + TermInfo + 'a, W: io::Write + 'a> {
_state: &'a mut ProcessorState,
- handler: &'a mut H
+ handler: &'a mut H,
+ writer: &'a mut W
}
-impl<'a, H: Handler + TermInfo + 'a> Performer<'a, H> {
+impl<'a, H: Handler + TermInfo + 'a, W: io::Write> Performer<'a, H, W> {
/// Create a performer
#[inline]
- pub fn new<'b>(state: &'b mut ProcessorState, handler: &'b mut H) -> Performer<'b, H> {
+ pub fn new<'b>(
+ state: &'b mut ProcessorState,
+ handler: &'b mut H,
+ writer: &'b mut W,
+ ) -> Performer<'b, H, W> {
Performer {
_state: state,
- handler: handler
+ handler: handler,
+ writer: writer,
}
}
}
@@ -76,8 +83,16 @@ impl Processor {
}
#[inline]
- pub fn advance<H: Handler + TermInfo>(&mut self, handler: &mut H, byte: u8) {
- let mut performer = Performer::new(&mut self.state, handler);
+ pub fn advance<H, W>(
+ &mut self,
+ handler: &mut H,
+ byte: u8,
+ writer: &mut W
+ )
+ where H: Handler + TermInfo,
+ W: io::Write
+ {
+ let mut performer = Performer::new(&mut self.state, handler, writer);
self.parser.advance(&mut performer, byte);
}
}
@@ -116,7 +131,9 @@ pub trait Handler {
fn move_down(&mut self, Line) {}
/// Identify the terminal (should write back to the pty stream)
- fn identify_terminal(&mut self) {}
+ ///
+ /// TODO this should probably return an io::Result
+ fn identify_terminal<W: io::Write>(&mut self, &mut W) {}
/// Move cursor forward `cols`
fn move_forward(&mut self, Column) {}
@@ -415,7 +432,10 @@ pub enum Attr {
Background(Color),
}
-impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
+impl<'a, H, W> vte::Perform for Performer<'a, H, W>
+ where H: Handler + TermInfo + 'a,
+ W: io::Write + 'a
+{
#[inline]
fn print(&mut self, c: char) {
self.handler.input(c);
@@ -432,7 +452,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
C0::SUB => self.handler.substitute(),
C1::NEL => self.handler.newline(),
C1::HTS => self.handler.set_horizontal_tabstop(),
- C1::DECID => self.handler.identify_terminal(),
+ C1::DECID => self.handler.identify_terminal(self.writer),
_ => err_println!("[unhandled] execute byte={:02x}", byte)
}
}
@@ -469,9 +489,16 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
}
#[inline]
- fn csi_dispatch(&mut self, args: &[i64], intermediates: &[u8], _ignore: bool, action: char) {
+ fn csi_dispatch(
+ &mut self,
+ args: &[i64],
+ intermediates: &[u8],
+ _ignore: bool,
+ action: char
+ ) {
let private = intermediates.get(0).map(|b| *b == b'?').unwrap_or(false);
let handler = &mut self.handler;
+ let writer = &mut self.writer;
macro_rules! unhandled {
@@ -500,7 +527,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
handler.move_up(Line(arg_or_default!(idx: 0, default: 1) as usize));
},
'B' | 'e' => handler.move_down(Line(arg_or_default!(idx: 0, default: 1) as usize)),
- 'c' => handler.identify_terminal(),
+ 'c' => handler.identify_terminal(writer),
'C' | 'a' => handler.move_forward(Column(arg_or_default!(idx: 0, default: 1) as usize)),
'D' => handler.move_backward(Column(arg_or_default!(idx: 0, default: 1) as usize)),
'E' => handler.move_down_and_cr(Line(arg_or_default!(idx: 0, default: 1) as usize)),
@@ -650,7 +677,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
i += 1; // C-for expr
}
}
- 'n' => handler.identify_terminal(),
+ 'n' => handler.identify_terminal(writer),
'r' => {
if private {
unhandled!();
@@ -679,7 +706,7 @@ impl<'a, H: Handler + TermInfo + 'a> vte::Perform for Performer<'a, H> {
b'E' => self.handler.newline(),
b'H' => self.handler.set_horizontal_tabstop(),
b'M' => self.handler.reverse_index(),
- b'Z' => self.handler.identify_terminal(),
+ b'Z' => self.handler.identify_terminal(self.writer),
b'c' => self.handler.reset_state(),
b'7' => self.handler.save_cursor_position(),
b'8' => self.handler.restore_cursor_position(),
@@ -899,10 +926,26 @@ pub mod C1 {
// Byte sequences used in these tests are recording of pty stdout.
#[cfg(test)]
mod tests {
+ use std::io;
+
use index::{Line, Column};
use super::{Processor, Handler, Attr, TermInfo, Color};
use ::Rgb;
+ /// The /dev/null of io::Write
+ struct Void;
+
+ impl io::Write for Void {
+ fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
+ Ok(bytes.len())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+ }
+
+
#[derive(Default)]
struct AttrHandler {
attr: Option<Attr>,
@@ -934,7 +977,7 @@ mod tests {
let mut handler = AttrHandler::default();
for byte in &BYTES[..] {
- parser.advance(&mut handler, *byte);
+ parser.advance(&mut handler, *byte, &mut Void);
}
assert_eq!(handler.attr, Some(Attr::Bold));
@@ -951,7 +994,7 @@ mod tests {
let mut handler = AttrHandler::default();
for byte in &BYTES[..] {
- parser.advance(&mut handler, *byte);
+ parser.advance(&mut handler, *byte, &mut Void);
}
let spec = Rgb {
@@ -986,7 +1029,7 @@ mod tests {
let mut parser = Processor::new();
for byte in &BYTES[..] {
- parser.advance(&mut handler, *byte);
+ parser.advance(&mut handler, *byte, &mut Void);
}
}
}
diff --git a/src/event_loop.rs b/src/event_loop.rs
index 632ad28e..72b98425 100644
--- a/src/event_loop.rs
+++ b/src/event_loop.rs
@@ -189,7 +189,7 @@ impl<Io> EventLoop<Io>
let mut terminal = self.terminal.lock();
for byte in &buf[..got] {
- state.parser.advance(&mut *terminal, *byte);
+ state.parser.advance(&mut *terminal, *byte, &mut self.pty);
}
terminal.dirty = true;
diff --git a/src/term/mod.rs b/src/term/mod.rs
index 9ed19c81..979999a9 100644
--- a/src/term/mod.rs
+++ b/src/term/mod.rs
@@ -16,6 +16,7 @@
use std::ops::{Deref, Range};
use std::ptr;
use std::cmp;
+use std::io;
use ansi::{self, Attr, Handler};
use grid::{Grid, ClearRegion};
@@ -557,8 +558,8 @@ impl ansi::Handler for Term {
}
#[inline]
- fn identify_terminal(&mut self) {
- err_println!("[unimplemented] identify_terminal");
+ fn identify_terminal<W: io::Write>(&mut self, writer: &mut W) {
+ let _ = writer.write_all("\x1b[?6c".as_bytes());
}
#[inline]
diff --git a/tests/ref.rs b/tests/ref.rs
index 2859dba1..6fe4c665 100644
--- a/tests/ref.rs
+++ b/tests/ref.rs
@@ -4,7 +4,7 @@ extern crate serde_json;
/// ref tests
mod reference {
use std::fs::File;
- use std::io::Read;
+ use std::io::{self, Read};
use std::path::Path;
use serde_json as json;
@@ -15,6 +15,19 @@ mod reference {
use alacritty::term::SizeInfo;
use alacritty::ansi;
+ /// The /dev/null of io::Write
+ struct Void;
+
+ impl io::Write for Void {
+ fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
+ Ok(bytes.len())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+ }
+
macro_rules! ref_file {
($ref_name:ident, $file:expr) => {
concat!(
@@ -59,7 +72,7 @@ mod reference {
let mut parser = ansi::Processor::new();
for byte in recording {
- parser.advance(&mut terminal, byte);
+ parser.advance(&mut terminal, byte, &mut Void);
}
assert_eq!(grid, *terminal.grid());