1use std::fmt;
2use std::io::{Read, Write, Result, Error, ErrorKind};
3use std::iter::Peekable;
4
5#[derive(Clone, Copy, PartialEq, Eq)]
6pub enum Sequence<'a> {
7 Reset,
9
10 LineWrap(bool),
12
13 FontDefault,
15
16 FontAlternate,
18
19 CursorAt(u32, u32),
21
22 CursorMove(i32, i32),
26
27 CursorSave,
29
30 CursorRestore,
32
33 CursorSaveAttributes,
35
36 CursorRestoreAttributes,
38
39 ScrollEnable(Option<(u32, u32)>),
44
45 Scroll(i32),
48
49 EraseEndOfLine,
51
52 EraseStartOfLine,
54
55 EraseLine,
57
58 EraseDown,
60
61 EraseUp,
63
64 EraseScreen,
66
67 SetAttributes(&'a [Attribute])
69}
70
71#[derive(Clone, Copy, PartialEq, Eq)]
73pub enum Attribute {
74 Default,
76
77 Bright,
79
80 Dim,
82
83 Underscore,
85
86 Blink,
88
89 Reverse,
91
92 Hidden,
94
95 Foreground(Color),
97
98 Background(Color)
100}
101
102#[derive(Clone, Copy, PartialEq, Eq)]
104pub enum Color {
105 Black,
106 Red,
107 Green,
108 Yellow,
109 Blue,
110 Magenta,
111 Cyan,
112 White
113}
114
115impl<'a> fmt::Display for Sequence<'a> {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 use Sequence::*;
118 match self {
119 Reset => write!(f, "\x1bc"),
120 LineWrap(true) => write!(f, "\x1b[7h"),
121 LineWrap(false) => write!(f, "\x1b[7l"),
122 FontDefault => write!(f, "\x1b("),
123 FontAlternate => write!(f, "\x1b)"),
124 CursorAt(row, column) => write!(f, "\x1b[{};{}H", row, column),
125 CursorMove(drow, dcolumn) => {
126 if *drow != 0 {
127 if *drow < 0 {
128 write!(f, "\x1b[{}A", -drow)?;
129 } else {
130 write!(f, "\x1b[{}B", drow)?;
131 }
132 }
133 if *dcolumn != 0 {
134 if *dcolumn > 0 {
135 write!(f, "\x1b[{}C", dcolumn)?;
136 } else {
137 write!(f, "\x1b[{}D", -dcolumn)?;
138 }
139 }
140 Ok(())
141 },
142 CursorSave => write!(f, "\x1b[s"),
143 CursorRestore => write!(f, "\x1b[u"),
144 CursorSaveAttributes => write!(f, "\x1b7"),
145 CursorRestoreAttributes => write!(f, "\x1b8"),
146 ScrollEnable(None) => write!(f, "\x1b[r"),
147 ScrollEnable(Some((start, end))) => write!(f, "\x1b[{};{}r", start, end),
148 Scroll(d) => {
149 if *d < 0 {
150 for _ in 0..(-*d) {
151 write!(f, "\x1b[D")?;
152 }
153 } else {
154 for _ in 0..*d {
155 write!(f, "\x1b[M")?;
156 }
157 }
158 Ok(())
159 },
160 EraseEndOfLine => write!(f, "\x1b[K"),
161 EraseStartOfLine => write!(f, "\x1b[1K"),
162 EraseLine => write!(f, "\x1b[2K"),
163 EraseDown => write!(f, "\x1b[J"),
164 EraseUp => write!(f, "\x1b[1J"),
165 EraseScreen => write!(f, "\x1b[2J"),
166 SetAttributes(attributes) => {
167 write!(f, "\x1b[{}m", DisplayAttributes(attributes))
168 }
169 }
170 }
171}
172
173impl fmt::Display for Attribute {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 use Attribute::*;
176 match self {
177 Default => write!(f, "0"),
178 Bright => write!(f, "1"),
179 Dim => write!(f, "2"),
180 Underscore => write!(f, "4"),
181 Blink => write!(f, "5"),
182 Reverse => write!(f, "7"),
183 Hidden => write!(f, "8"),
184 Foreground(c) => write!(f, "{}", 30+c.index()),
185 Background(c) => write!(f, "{}", 40+c.index()),
186 }
187 }
188}
189
190impl Color {
191 pub fn index(&self) -> u8 {
195 use Color::*;
196 match self {
197 Black => 0,
198 Red => 1,
199 Green => 2,
200 Yellow => 3,
201 Blue => 4,
202 Magenta => 5,
203 Cyan => 6,
204 White => 7
205 }
206 }
207}
208
209struct DisplayAttributes<'a>(&'a [Attribute]);
210
211impl<'a> fmt::Display for DisplayAttributes<'a> {
212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213 match self.0.split_first() {
214 Some((head, tail)) => {
215 write!(f, "{}", head)?;
216 for a in tail {
217 write!(f, ";{}", a)?;
218 }
219 Ok(())
220 },
221 None => Ok(())
222 }
223 }
224}
225
226pub enum Query {
228 CursorPosition
230}
231
232impl fmt::Display for Query {
233 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234 use Query::*;
235 match self {
236 CursorPosition => write!(f, "\x1b[6n")
237 }
238 }
239}
240
241pub enum Response {
243 CursorPosition(u32, u32)
245}
246
247pub struct Device<I: Read, O: Write> {
249 input: I,
250 output: O,
251 buffer: Vec<u8>,
252 offset: usize
253}
254
255impl<I: Read, O: Write> Device<I, O> {
256 pub fn new(input: I, output: O) -> Device<I, O> {
258 Device {
259 input: input,
260 output: output,
261 buffer: Vec::new(),
262 offset: 0
263 }
264 }
265
266 fn next_byte(&mut self) -> Result<Option<u8>> {
268 let mut buffer = [0];
269 let n = self.input.read(&mut buffer)?;
270 if n == 0 {
271 Ok(None)
272 } else {
273 Ok(Some(buffer[0]))
274 }
275 }
276
277 fn response(&mut self) -> Result<Response> {
282 loop {
283 match self.next_byte()? {
284 Some(0x1b) => {
285 return self.parse_response()
286 },
287 Some(c) => {
288 self.buffer.push(c)
289 },
290 None => return Err(Error::new(ErrorKind::UnexpectedEof, "no response from the device"))
291 }
292 }
293 }
294
295 fn parse_response(&mut self) -> Result<Response> {
297 let mut buffer = Vec::new();
298 loop {
299 match self.next_byte()? {
300 Some(c) => {
301 match c {
302 0x52 => { let mut it = buffer.into_iter().peekable();
304 expect_byte(&mut it, 0x5b)?; let row = read_u32(&mut it)?; expect_byte(&mut it, 0x3b)?; let column = read_u32(&mut it)?; return Ok(Response::CursorPosition(row-1, column-1))
310 },
311 _ => {
312 buffer.push(c)
313 }
314 }
315 },
316 None => return Err(Error::new(ErrorKind::UnexpectedEof, "incomplete device response"))
317 }
318 }
319 }
320
321 #[allow(irrefutable_let_patterns)]
325 pub fn cursor_position(&mut self) -> Result<(u32, u32)> {
326 write!(self.output, "{}", Query::CursorPosition)?;
327 self.flush()?;
328 if let Response::CursorPosition(x, y) = self.response()? {
329 Ok((x, y))
330 } else {
331 Err(Error::new(ErrorKind::InvalidData, "invalid device response"))
332 }
333 }
334
335 pub fn reset(&mut self) -> Result<()> {
337 write!(self.output, "{}", Sequence::Reset)
338 }
339
340 pub fn line_wrap(&mut self, enable: bool) -> Result<()> {
342 write!(self.output, "{}", Sequence::LineWrap(enable))
343 }
344
345 pub fn font_default(&mut self) -> Result<()> {
347 write!(self.output, "{}", Sequence::FontDefault)
348 }
349
350 pub fn font_alternate(&mut self) -> Result<()> {
352 write!(self.output, "{}", Sequence::FontAlternate)
353 }
354
355 pub fn cursor_at(&mut self, row: u32, column: u32) -> Result<()> {
357 write!(self.output, "{}", Sequence::CursorAt(row, column))
358 }
359
360 pub fn cursor_move(&mut self, drow: i32, dcolumn: i32) -> Result<()> {
364 write!(self.output, "{}", Sequence::CursorMove(drow, dcolumn))
365 }
366
367 pub fn cursor_save(&mut self) -> Result<()> {
369 write!(self.output, "{}", Sequence::CursorSave)
370 }
371
372 pub fn cursor_restore(&mut self) -> Result<()> {
374 write!(self.output, "{}", Sequence::CursorRestore)
375 }
376
377 pub fn cursor_save_attributes(&mut self) -> Result<()> {
379 write!(self.output, "{}", Sequence::CursorSaveAttributes)
380 }
381
382 pub fn cursor_restore_attributes(&mut self) -> Result<()> {
384 write!(self.output, "{}", Sequence::CursorRestoreAttributes)
385 }
386
387 pub fn scroll_enable(&mut self, region: Option<(u32, u32)>) -> Result<()> {
392 write!(self.output, "{}", Sequence::ScrollEnable(region))
393 }
394
395 pub fn scroll(&mut self, rows: i32) -> Result<()> {
398 write!(self.output, "{}", Sequence::Scroll(rows))
399 }
400
401 pub fn erase_end_of_line(&mut self) -> Result<()> {
403 write!(self.output, "{}", Sequence::EraseEndOfLine)
404 }
405
406 pub fn erase_start_of_line(&mut self) -> Result<()> {
408 write!(self.output, "{}", Sequence::EraseStartOfLine)
409 }
410
411 pub fn erase_line(&mut self) -> Result<()> {
413 write!(self.output, "{}", Sequence::EraseLine)
414 }
415
416 pub fn erase_down(&mut self) -> Result<()> {
418 write!(self.output, "{}", Sequence::EraseDown)
419 }
420
421 pub fn erase_up(&mut self) -> Result<()> {
423 write!(self.output, "{}", Sequence::EraseUp)
424 }
425
426 pub fn erase_screen(&mut self) -> Result<()> {
428 write!(self.output, "{}", Sequence::EraseScreen)
429 }
430
431 pub fn set_attributes(&mut self, attributes: &[Attribute]) -> Result<()> {
433 write!(self.output, "{}", Sequence::SetAttributes(attributes))
434 }
435}
436
437fn expect_byte<I: Iterator<Item = u8>>(it: &mut Peekable<I>, expected: u8) -> Result<()> {
439 match it.next() {
440 Some(b) if b == expected => Ok(()),
441 _ => Err(Error::new(ErrorKind::InvalidData, "invalid device response"))
442 }
443}
444
445fn read_u32<I: Iterator<Item = u8>>(it: &mut Peekable<I>) -> Result<u32> {
447 let mut empty = true;
448 let mut value = 0u32;
449
450 loop {
451 match it.peek() {
452 Some(b) => {
453 if *b >= 0x30 && *b <= 0x39 {
454 let b = it.next().unwrap();
455 empty = false;
456 value = value * 10 + (b - 0x30) as u32;
457 } else {
458 break
459 }
460 },
461 None => {
462 break
463 }
464 }
465 }
466
467 if empty {
468 Err(Error::new(ErrorKind::InvalidData, "invalid device response"))
469 } else {
470 Ok(value)
471 }
472}
473
474impl<I: Read, O: Write> Read for Device<I, O> {
475 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
476 let len = std::cmp::min(self.buffer.len()-self.offset, buf.len());
477 if len > 0 {
478 for i in 0..len {
479 buf[i] = self.buffer[self.offset];
480 self.offset += 1;
481 }
482
483 if self.offset >= self.buffer.len() {
484 self.offset = 0;
485 self.buffer.clear();
486 }
487 }
488
489 Ok(self.input.read(&mut buf[len..])? + len)
490 }
491}
492
493impl<I: Read, O: Write> Write for Device<I, O> {
494 fn write(&mut self, buf: &[u8]) -> Result<usize> {
495 self.output.write(buf)
496 }
497
498 fn flush(&mut self) -> Result<()> {
499 self.output.flush()
500 }
501}