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}