test/term.rs
1//! Terminal formatting module.
2//!
3//! This module provides the `Terminal` trait, which abstracts over an [ANSI
4//! Terminal][ansi] to provide color printing, among other things. There are two
5//! implementations, the `TerminfoTerminal`, which uses control characters from
6//! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
7//! API][win].
8//!
9//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
10//! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications
11//! [ti]: https://en.wikipedia.org/wiki/Terminfo
12
13#![deny(missing_docs)]
14
15use std::io::prelude::*;
16use std::io::{self};
17
18pub(crate) use terminfo::TerminfoTerminal;
19#[cfg(windows)]
20pub(crate) use win::WinConsole;
21
22pub(crate) mod terminfo;
23
24#[cfg(windows)]
25mod win;
26
27/// Alias for stdout terminals.
28pub(crate) type StdoutTerminal = dyn Terminal + Send;
29
30#[cfg(not(windows))]
31/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
32/// opened.
33pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
34 TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box<StdoutTerminal>)
35}
36
37#[cfg(windows)]
38/// Returns a Terminal wrapping stdout, or None if a terminal couldn't be
39/// opened.
40pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
41 TerminfoTerminal::new(io::stdout())
42 .map(|t| Box::new(t) as Box<StdoutTerminal>)
43 .or_else(|| Some(Box::new(WinConsole::new(io::stdout())) as Box<StdoutTerminal>))
44}
45
46/// Terminal color definitions
47#[allow(missing_docs)]
48#[cfg_attr(not(windows), allow(dead_code))]
49pub(crate) mod color {
50 /// Number for a terminal color
51 pub(crate) type Color = u32;
52
53 pub(crate) const BLACK: Color = 0;
54 pub(crate) const RED: Color = 1;
55 pub(crate) const GREEN: Color = 2;
56 pub(crate) const YELLOW: Color = 3;
57 pub(crate) const BLUE: Color = 4;
58 pub(crate) const MAGENTA: Color = 5;
59 pub(crate) const CYAN: Color = 6;
60 pub(crate) const WHITE: Color = 7;
61}
62
63/// A terminal with similar capabilities to an ANSI Terminal
64/// (foreground/background colors etc).
65pub(crate) trait Terminal: Write {
66 /// Sets the foreground color to the given color.
67 ///
68 /// If the color is a bright color, but the terminal only supports 8 colors,
69 /// the corresponding normal color will be used instead.
70 ///
71 /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
72 /// if there was an I/O error.
73 fn fg(&mut self, color: color::Color) -> io::Result<bool>;
74
75 /// Resets all terminal attributes and colors to their defaults.
76 ///
77 /// Returns `Ok(true)` if the terminal was reset, `Ok(false)` otherwise, and `Err(e)` if there
78 /// was an I/O error.
79 ///
80 /// *Note: This does not flush.*
81 ///
82 /// That means the reset command may get buffered so, if you aren't planning on doing anything
83 /// else that might flush stdout's buffer (e.g., writing a line of text), you should flush after
84 /// calling reset.
85 fn reset(&mut self) -> io::Result<bool>;
86}