summaryrefslogtreecommitdiffstats
path: root/tests/fakes/fake_output.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/fakes/fake_output.rs')
-rw-r--r--tests/fakes/fake_output.rs263
1 files changed, 263 insertions, 0 deletions
diff --git a/tests/fakes/fake_output.rs b/tests/fakes/fake_output.rs
new file mode 100644
index 0000000..4714bad
--- /dev/null
+++ b/tests/fakes/fake_output.rs
@@ -0,0 +1,263 @@
+// mostly copied and adjusted from https://github.com/fdehau/tui-rs/blob/master/src/backend/termion.rs
+
+use std::fmt;
+use std::io;
+
+use ::std::sync::{Arc, Mutex};
+
+use ::tui::backend::Backend;
+use ::tui::buffer::Cell;
+use ::tui::layout::Rect;
+use ::tui::style;
+
+#[derive(Hash, Debug, PartialEq)]
+pub enum TerminalEvent {
+ Clear,
+ HideCursor,
+ ShowCursor,
+ GetCursor,
+ Flush,
+ Draw
+}
+
+pub struct TestBackend {
+ pub events: Arc<Mutex<Vec<TerminalEvent>>>,
+ pub draw_events: Arc<Mutex<Vec<String>>>
+}
+
+impl TestBackend {
+ pub fn new(log: Arc<Mutex<Vec<TerminalEvent>>>, draw_log: Arc<Mutex<Vec<String>>>) -> TestBackend {
+ TestBackend { events: log, draw_events: draw_log }
+ }
+}
+
+impl Backend for TestBackend {
+
+ /// Clears the entire screen and move the cursor to the top left of the screen
+ fn clear(&mut self) -> io::Result<()> {
+ self.events.lock().unwrap().push(TerminalEvent::Clear);
+ Ok(())
+ }
+
+ /// Hides cursor
+ fn hide_cursor(&mut self) -> io::Result<()> {
+ self.events.lock().unwrap().push(TerminalEvent::HideCursor);
+ Ok(())
+ }
+
+ /// Shows cursor
+ fn show_cursor(&mut self) -> io::Result<()> {
+ self.events.lock().unwrap().push(TerminalEvent::ShowCursor);
+ Ok(())
+ }
+
+ /// Gets cursor position (0-based index)
+ fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
+ self.events.lock().unwrap().push(TerminalEvent::GetCursor);
+ Ok((0, 0))
+ }
+
+ /// Sets cursor position (0-based index)
+ fn set_cursor(&mut self, _x: u16, _y: u16) -> io::Result<()> {
+ Ok(())
+ }
+
+ fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
+ where
+ I: Iterator<Item = (u16, u16, &'a Cell)>,
+ {
+ use std::fmt::Write;
+ self.events.lock().unwrap().push(TerminalEvent::Draw);
+
+ let mut string = String::with_capacity(content.size_hint().0 * 3);
+ let mut style = style::Style::default();
+ let mut last_y = 0;
+ let mut last_x = 0;
+ let mut inst = 0;
+ for (x, y, cell) in content {
+ if y != last_y || x != last_x + 1 || inst == 0 {
+ write!(string, "{}", termion::cursor::Goto(x + 1, y + 1)).unwrap();
+ inst += 1;
+ }
+ last_x = x;
+ last_y = y;
+ if cell.style.modifier != style.modifier {
+ write!(
+ string,
+ "{}",
+ ModifierDiff {
+ from: style.modifier,
+ to: cell.style.modifier
+ }
+ )
+ .unwrap();
+ style.modifier = cell.style.modifier;
+ inst += 1;
+ }
+ if cell.style.fg != style.fg {
+ write!(string, "{}", Fg(cell.style.fg)).unwrap();
+ style.fg = cell.style.fg;
+ inst += 1;
+ }
+ if cell.style.bg != style.bg {
+ write!(string, "{}", Bg(cell.style.bg)).unwrap();
+ style.bg = cell.style.bg;
+ inst += 1;
+ }
+ string.push_str(&cell.symbol);
+ inst += 1;
+ }
+ self.draw_events.lock().unwrap().push(string.clone());
+ // uncomment this to print to screen
+ //
+ // write!(self.stdout, "{}", termion::clear::All)?;
+ // write!(
+ // self.stdout,
+ // "{}{}{}{}",
+ // string,
+ // Fg(style::Color::Reset),
+ // Bg(style::Color::Reset),
+ // termion::style::Reset,
+ // );
+ Ok(())
+ }
+
+ /// Return the size of the terminal
+ fn size(&self) -> io::Result<Rect> {
+ Ok(Rect::new(0, 0, 190, 50))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.events.lock().unwrap().push(TerminalEvent::Flush);
+ Ok(())
+ }
+}
+
+struct Fg(style::Color);
+
+struct Bg(style::Color);
+
+struct ModifierDiff {
+ from: style::Modifier,
+ to: style::Modifier,
+}
+
+impl fmt::Display for Fg {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use termion::color::Color;
+ match self.0 {
+ style::Color::Reset => termion::color::Reset.write_fg(f),
+ style::Color::Black => termion::color::Black.write_fg(f),
+ style::Color::Red => termion::color::Red.write_fg(f),
+ style::Color::Green => termion::color::Green.write_fg(f),
+ style::Color::Yellow => termion::color::Yellow.write_fg(f),
+ style::Color::Blue => termion::color::Blue.write_fg(f),
+ style::Color::Magenta => termion::color::Magenta.write_fg(f),
+ style::Color::Cyan => termion::color::Cyan.write_fg(f),
+ style::Color::Gray => termion::color::White.write_fg(f),
+ style::Color::DarkGray => termion::color::LightBlack.write_fg(f),
+ style::Color::LightRed => termion::color::LightRed.write_fg(f),
+ style::Color::LightGreen => termion::color::LightGreen.write_fg(f),
+ style::Color::LightBlue => termion::color::LightBlue.write_fg(f),
+ style::Color::LightYellow => termion::color::LightYellow.write_fg(f),
+ style::Color::LightMagenta => termion::color::LightMagenta.write_fg(f),
+ style::Color::LightCyan => termion::color::LightCyan.write_fg(f),
+ style::Color::White => termion::color::LightWhite.write_fg(f),
+ style::Color::Indexed(i) => termion::color::AnsiValue(i).write_fg(f),
+ style::Color::Rgb(r, g, b) => termion::color::Rgb(r, g, b).write_fg(f),
+ }
+ }
+}
+impl fmt::Display for Bg {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use termion::color::Color;
+ match self.0 {
+ style::Color::Reset => termion::color::Reset.write_bg(f),
+ style::Color::Black => termion::color::Black.write_bg(f),
+ style::Color::Red => termion::color::Red.write_bg(f),
+ style::Color::Green => termion::color::Green.write_bg(f),
+ style::Color::Yellow => termion::color::Yellow.write_bg(f),
+ style::Color::Blue => termion::color::Blue.write_bg(f),
+ style::Color::Magenta => termion::color::Magenta.write_bg(f),
+ style::Color::Cyan => termion::color::Cyan.write_bg(f),
+ style::Color::Gray => termion::color::White.write_bg(f),
+ style::Color::DarkGray => termion::color::LightBlack.write_bg(f),
+ style::Color::LightRed => termion::color::LightRed.write_bg(f),
+ style::Color::LightGreen => termion::color::LightGreen.write_bg(f),
+ style::Color::LightBlue => termion::color::LightBlue.write_bg(f),
+ style::Color::LightYellow => termion::color::LightYellow.write_bg(f),
+ style::Color::LightMagenta => termion::color::LightMagenta.write_bg(f),
+ style::Color::LightCyan => termion::color::LightCyan.write_bg(f),
+ style::Color::White => termion::color::LightWhite.write_bg(f),
+ style::Color::Indexed(i) => termion::color::AnsiValue(i).write_bg(f),
+ style::Color::Rgb(r, g, b) => termion::color::Rgb(r, g, b).write_bg(f),
+ }
+ }
+}
+
+impl fmt::Display for ModifierDiff {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let remove = self.from - self.to;
+ if remove.contains(style::Modifier::REVERSED) {
+ write!(f, "{}", termion::style::NoInvert)?;
+ }
+ if remove.contains(style::Modifier::BOLD) {
+ // XXX: the termion NoBold flag actually enables double-underline on ECMA-48 compliant
+ // terminals, and NoFaint additionally disables bold... so we use this trick to get
+ // the right semantics.
+ write!(f, "{}", termion::style::NoFaint)?;
+
+ if self.to.contains(style::Modifier::DIM) {
+ write!(f, "{}", termion::style::Faint)?;
+ }
+ }
+ if remove.contains(style::Modifier::ITALIC) {
+ write!(f, "{}", termion::style::NoItalic)?;
+ }
+ if remove.contains(style::Modifier::UNDERLINED) {
+ write!(f, "{}", termion::style::NoUnderline)?;
+ }
+ if remove.contains(style::Modifier::DIM) {
+ write!(f, "{}", termion::style::NoFaint)?;
+
+ // XXX: the NoFaint flag additionally disables bold as well, so we need to re-enable it
+ // here if we want it.
+ if self.to.contains(style::Modifier::BOLD) {
+ write!(f, "{}", termion::style::Bold)?;
+ }
+ }
+ if remove.contains(style::Modifier::CROSSED_OUT) {
+ write!(f, "{}", termion::style::NoCrossedOut)?;
+ }
+ if remove.contains(style::Modifier::SLOW_BLINK)
+ || remove.contains(style::Modifier::RAPID_BLINK)
+ {
+ write!(f, "{}", termion::style::NoBlink)?;
+ }
+
+ let add = self.to - self.from;
+ if add.contains(style::Modifier::REVERSED) {
+ write!(f, "{}", termion::style::Invert)?;
+ }
+ if add.contains(style::Modifier::BOLD) {
+ write!(f, "{}", termion::style::Bold)?;
+ }
+ if add.contains(style::Modifier::ITALIC) {
+ write!(f, "{}", termion::style::Italic)?;
+ }
+ if add.contains(style::Modifier::UNDERLINED) {
+ write!(f, "{}", termion::style::Underline)?;
+ }
+ if add.contains(style::Modifier::DIM) {
+ write!(f, "{}", termion::style::Faint)?;
+ }
+ if add.contains(style::Modifier::CROSSED_OUT) {
+ write!(f, "{}", termion::style::CrossedOut)?;
+ }
+ if add.contains(style::Modifier::SLOW_BLINK) || add.contains(style::Modifier::RAPID_BLINK) {
+ write!(f, "{}", termion::style::Blink)?;
+ }
+
+ Ok(())
+ }
+}