1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//! Escape Sequence for the terminal.
//!
//! There are a variety of escape sequences (see [ANSI escape
//! codes](http://ascii-table.com/ansi-escape-sequences.php)) for the
//! terminal but we currently have only implemented "Set Graphics
//! Mode". More can be added to the enum as needed.
//!
//! # Examples
//!
//! ```
//! # #[macro_use]
//! # use dinglebit_terminal::escape_sequence::EscapeSequence;
//! # use dinglebit_terminal::consts::*;
//! # fn main() {
//! let s = EscapeSequence::SetGraphicsMode(vec![OP_BOLD, FG_BLACK, BG_WHITE]).to_string();
//! assert_eq!(s, "\x1b[1;30;47m");
//! # }
//! ```
use std::fmt;
/// An escape sequence for the terminal.
pub enum EscapeSequence {
/// Change the foreground, background, and attributes of terminal
/// text using the given values.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # use dinglebit_terminal::escape_sequence::EscapeSequence;
/// # use dinglebit_terminal::consts::*;
/// # fn main() {
/// let s = EscapeSequence::SetGraphicsMode(vec![OP_BOLD, FG_BLACK, BG_WHITE]).to_string();
/// assert_eq!(s, "\x1b[1;30;47m");
/// # }
/// ```
SetGraphicsMode(Vec<u8>),
}
impl fmt::Display for EscapeSequence {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
EscapeSequence::SetGraphicsMode(v) => {
// This seems "faster" per an article I found, but we
// could also just map/collect/join to a string.
let mut s = String::with_capacity(100);
if v.len() > 0 {
s.push_str(v[0].to_string().as_str());
for i in v[1..].into_iter() {
s.push_str(";");
s.push_str(i.to_string().as_str());
}
}
write!(f, "{}", format!("\x1b[{}m", s))
}
}
}
}
/// Create a reset escape sequence for the graphics mode.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # use dinglebit_terminal::reset;
/// # fn main() {
/// let s = reset!().to_string();
/// assert_eq!(s, "\x1b[0m");
/// # }
/// ```
#[macro_export]
macro_rules! reset {
() => {
$crate::escape_sequence::EscapeSequence::SetGraphicsMode(vec![$crate::consts::OP_RESET])
};
}
/// Create a SetGraphicsMode using the given vector.
///
/// # Examples
///
/// ```
/// # #[macro_use]
/// # use dinglebit_terminal::sgm;
/// # use dinglebit_terminal::consts::*;
/// # fn main() {
/// let s = sgm!(vec![OP_BOLD, FG_BLACK, BG_WHITE]).to_string();
/// assert_eq!(s, "\x1b[1;30;47m");
/// # }
/// ```
#[macro_export]
macro_rules! sgm {
($e:expr) => {
$crate::escape_sequence::EscapeSequence::SetGraphicsMode(($e))
};
}
#[cfg(test)]
mod tests {
pub use super::*;
pub use crate::consts::*;
#[test]
fn display() {
let s = sgm!(vec![OP_BOLD, FG_BLACK, BG_WHITE]);
assert_eq!("test: \x1b[1;30;47m", format!("test: {}", s));
}
}