Improve printer

This commit is contained in:
Rico Riedel 2022-08-01 14:03:02 +02:00
parent ef4eaec34d
commit 393d3dd67e
No known key found for this signature in database
GPG Key ID: 75AC868575DE7B18
2 changed files with 122 additions and 18 deletions

View File

@ -14,6 +14,12 @@ impl From<std::io::Error> for Error {
} }
} }
impl From<&str> for Error {
fn from(msg: &str) -> Self {
Error(msg.to_string())
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
@ -26,4 +32,11 @@ mod test {
assert_eq!(msg, format!("{:?}", err)); assert_eq!(msg, format!("{:?}", err));
} }
#[test]
fn from_ref_str() {
let err: Error = "123".into();
assert_eq!("123", format!("{:?}", err));
}
} }

View File

@ -18,17 +18,21 @@ pub trait Printer {
pub struct PrinterImpl<T> { pub struct PrinterImpl<T> {
term: T, term: T,
position: (u16, u16),
cursor: Option<bool>, cursor: Option<bool>,
foreground: Option<Color>, foreground: Option<Color>,
} }
impl<T> PrinterImpl<T> { impl<T: Terminal> PrinterImpl<T> {
pub fn new(term: T) -> Self { pub fn new(term: T) -> Result<Self, Error> {
Self { let position = term.position()?;
Ok(Self {
term, term,
position,
cursor: None, cursor: None,
foreground: None, foreground: None,
} })
} }
} }
@ -50,12 +54,17 @@ impl<T: Terminal> Printer for PrinterImpl<T> {
} }
fn print(&mut self, char: char) -> Result<(), Error> { fn print(&mut self, char: char) -> Result<(), Error> {
if char < '\u{20}' || char == '\u{7F}' {
return Err("Special chars can't be printed.".into());
}
self.position.0 += 1;
self.term.queue(Print(char))?; self.term.queue(Print(char))?;
Ok(()) Ok(())
} }
fn move_to(&mut self, x: u16, y: u16) -> Result<(), Error> { fn move_to(&mut self, x: u16, y: u16) -> Result<(), Error> {
if (x, y) != self.term.position()? { if self.position != (x, y) {
self.position = (x, y);
self.term.queue(MoveTo(x, y))?; self.term.queue(MoveTo(x, y))?;
} }
Ok(()) Ok(())
@ -66,7 +75,7 @@ impl<T: Terminal> Printer for PrinterImpl<T> {
} }
fn set_foreground(&mut self, color: Color) -> Result<(), Error> { fn set_foreground(&mut self, color: Color) -> Result<(), Error> {
if self.foreground == Some(color) { if self.foreground != Some(color) {
self.foreground = Some(color); self.foreground = Some(color);
self.term.queue(SetForegroundColor(color))?; self.term.queue(SetForegroundColor(color))?;
} }
@ -93,23 +102,25 @@ mod test {
#[test] #[test]
fn show_cursor() { fn show_cursor() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Show)) .with(eq(Show))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
PrinterImpl::new(mock).show_cursor().unwrap(); PrinterImpl::new(mock).unwrap().show_cursor().unwrap();
} }
#[test] #[test]
fn show_cursor_twice_queues_once() { fn show_cursor_twice_queues_once() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Show)) .with(eq(Show))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
let mut printer = PrinterImpl::new(mock); let mut printer = PrinterImpl::new(mock).unwrap();
printer.show_cursor().unwrap(); printer.show_cursor().unwrap();
printer.show_cursor().unwrap(); printer.show_cursor().unwrap();
@ -118,13 +129,14 @@ mod test {
#[test] #[test]
fn show_cursor_after_hiding_queues_show() { fn show_cursor_after_hiding_queues_show() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Show)) .with(eq(Show))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
mock.expect_queue().with(eq(Hide)).returning(|_| Ok(())); mock.expect_queue().with(eq(Hide)).returning(|_| Ok(()));
let mut printer = PrinterImpl::new(mock); let mut printer = PrinterImpl::new(mock).unwrap();
printer.hide_cursor().unwrap(); printer.hide_cursor().unwrap();
printer.show_cursor().unwrap(); printer.show_cursor().unwrap();
@ -133,23 +145,25 @@ mod test {
#[test] #[test]
fn hide_cursor() { fn hide_cursor() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Hide)) .with(eq(Hide))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
PrinterImpl::new(mock).hide_cursor().unwrap(); PrinterImpl::new(mock).unwrap().hide_cursor().unwrap();
} }
#[test] #[test]
fn hide_cursor_twice_queues_once() { fn hide_cursor_twice_queues_once() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Hide)) .with(eq(Hide))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
let mut printer = PrinterImpl::new(mock); let mut printer = PrinterImpl::new(mock).unwrap();
printer.hide_cursor().unwrap(); printer.hide_cursor().unwrap();
printer.hide_cursor().unwrap(); printer.hide_cursor().unwrap();
@ -158,27 +172,101 @@ mod test {
#[test] #[test]
fn hide_cursor_after_showing_queues_hide() { fn hide_cursor_after_showing_queues_hide() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Show)) .with(eq(Show))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
mock.expect_queue().with(eq(Hide)).returning(|_| Ok(())); mock.expect_queue().with(eq(Hide)).returning(|_| Ok(()));
let mut printer = PrinterImpl::new(mock); let mut printer = PrinterImpl::new(mock).unwrap();
printer.show_cursor().unwrap(); printer.show_cursor().unwrap();
printer.hide_cursor().unwrap(); printer.hide_cursor().unwrap();
} }
#[test]
fn set_foreground() {
let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue()
.with(eq(SetForegroundColor(Color::Blue)))
.once()
.returning(|_| Ok(()));
PrinterImpl::new(mock)
.unwrap()
.set_foreground(Color::Blue)
.unwrap();
}
#[test]
fn set_foreground_twice_queues_once() {
let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue()
.once()
.returning(|_: SetForegroundColor| Ok(()));
let mut printer = PrinterImpl::new(mock).unwrap();
printer.set_foreground(Color::Red).unwrap();
printer.set_foreground(Color::Red).unwrap();
}
#[test]
fn set_foreground_different_color_queues() {
let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue()
.times(3)
.returning(|_: SetForegroundColor| Ok(()));
let mut printer = PrinterImpl::new(mock).unwrap();
printer.set_foreground(Color::Red).unwrap();
printer.set_foreground(Color::Blue).unwrap();
printer.set_foreground(Color::Red).unwrap();
}
#[test] #[test]
fn print() { fn print() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Print('R'))) .with(eq(Print('R')))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
PrinterImpl::new(mock).print('R').unwrap(); PrinterImpl::new(mock).unwrap().print('R').unwrap();
}
#[test]
fn print_moves_cursor() {
let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((2, 4)));
mock.expect_queue()
.times(3)
.returning(|_: Print<char>| Ok(()));
let mut printer = PrinterImpl::new(mock).unwrap();
printer.print('A').unwrap();
printer.print('B').unwrap();
printer.print('C').unwrap();
printer.move_to(5, 4).unwrap();
}
#[test]
fn print_special_char_fails() {
let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((2, 4)));
let mut printer = PrinterImpl::new(mock).unwrap();
assert!(printer.print('\u{0}').is_err());
assert!(printer.print('\u{1F}').is_err());
assert!(printer.print('\u{7F}').is_err());
} }
#[test] #[test]
@ -190,7 +278,7 @@ mod test {
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
PrinterImpl::new(mock).move_to(5, 4).unwrap(); PrinterImpl::new(mock).unwrap().move_to(5, 4).unwrap();
} }
#[test] #[test]
@ -198,33 +286,36 @@ mod test {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((3, 13))); mock.expect_position().returning(|| Ok((3, 13)));
PrinterImpl::new(mock).move_to(3, 13).unwrap(); PrinterImpl::new(mock).unwrap().move_to(3, 13).unwrap();
} }
#[test] #[test]
fn size() { fn size() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_size().returning(|| Ok((14, 76))); mock.expect_size().returning(|| Ok((14, 76)));
assert_eq!((14, 76), PrinterImpl::new(mock).size().unwrap()); assert_eq!((14, 76), PrinterImpl::new(mock).unwrap().size().unwrap());
} }
#[test] #[test]
fn clear() { fn clear() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_queue() mock.expect_queue()
.with(eq(Clear(ClearType::Purge))) .with(eq(Clear(ClearType::Purge)))
.once() .once()
.returning(|_| Ok(())); .returning(|_| Ok(()));
PrinterImpl::new(mock).clear().unwrap(); PrinterImpl::new(mock).unwrap().clear().unwrap();
} }
#[test] #[test]
fn flush() { fn flush() {
let mut mock = MockTerminal::new(); let mut mock = MockTerminal::new();
mock.expect_position().returning(|| Ok((0, 0)));
mock.expect_flush().once().returning(|| Ok(())); mock.expect_flush().once().returning(|| Ok(()));
PrinterImpl::new(mock).flush().unwrap(); PrinterImpl::new(mock).unwrap().flush().unwrap();
} }
} }