Extra derives & performance optimizations

This commit is contained in:
Michael Aaron Murphy 2018-08-20 22:11:58 +00:00
parent 130fc9acf5
commit acd94a3625
6 changed files with 133 additions and 22 deletions

View File

@ -7,19 +7,19 @@ before_script:
stable: stable:
script: script:
- cargo +stable build --verbose - cargo +stable build --verbose
- cargo +stable test --verbose - script -q -c "cargo +stable test --verbose"
- cargo +stable test --release --verbose - script -q -c "cargo +stable test --release --verbose"
beta: beta:
script: script:
- rustup toolchain add beta - rustup toolchain add beta
- cargo +beta build --verbose - cargo +beta build --verbose
- cargo +beta test --verbose - script -q -c "cargo +beta test --verbose"
- cargo +beta test --release --verbose - script -q -c "cargo +beta test --release --verbose"
nightly: nightly:
script: script:
- rustup toolchain add nightly - rustup toolchain add nightly
- cargo +nightly build --verbose - cargo +nightly build --verbose
- cargo +nightly test --verbose - script -q -c "cargo +nightly test --verbose"
- cargo +nightly test --release --verbose - script -q -c "cargo +nightly test --release --verbose"

View File

@ -9,6 +9,9 @@ license = "MIT"
keywords = ["tty", "color", "terminal", "password", "tui"] keywords = ["tty", "color", "terminal", "password", "tui"]
exclude = ["target", "CHANGELOG.md", "image.png", "Cargo.lock"] exclude = ["target", "CHANGELOG.md", "image.png", "Cargo.lock"]
[dependencies]
numtoa = { version = "0.1.0", features = ["std"]}
[target.'cfg(not(target_os = "redox"))'.dependencies] [target.'cfg(not(target_os = "redox"))'.dependencies]
libc = "0.2.8" libc = "0.2.8"

View File

@ -18,6 +18,7 @@ use std::io::{self, Write, Read};
use std::time::{SystemTime, Duration}; use std::time::{SystemTime, Duration};
use async::async_stdin; use async::async_stdin;
use std::env; use std::env;
use numtoa::NumToA;
/// A terminal color. /// A terminal color.
pub trait Color { pub trait Color {
@ -36,14 +37,24 @@ macro_rules! derive_color {
impl Color for $name { impl Color for $name {
#[inline] #[inline]
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("38;5;", $value, "m")) f.write_str(self.fg_str())
} }
#[inline] #[inline]
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("48;5;", $value, "m")) f.write_str(self.bg_str())
} }
} }
impl $name {
#[inline]
/// Returns the ANSI escape sequence as a string.
pub fn fg_str(&self) -> &'static str { csi!("38;5;", $value, "m") }
#[inline]
/// Returns the ANSI escape sequences as a string.
pub fn bg_str(&self) -> &'static str { csi!("48;5;", $value, "m") }
}
}; };
} }
@ -110,15 +121,31 @@ impl AnsiValue {
} }
} }
impl AnsiValue {
/// Returns the ANSI sequence as a string.
pub fn fg_string(self) -> String {
let mut x = [0u8; 20];
let x = self.0.numtoa_str(10, &mut x);
[csi!("38;5;"), x, "m"].concat()
}
/// Returns the ANSI sequence as a string.
pub fn bg_string(self) -> String {
let mut x = [0u8; 20];
let x = self.0.numtoa_str(10, &mut x);
[csi!("48;5;"), x, "m"].concat()
}
}
impl Color for AnsiValue { impl Color for AnsiValue {
#[inline] #[inline]
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("38;5;{}m"), self.0) f.write_str(&self.fg_string())
} }
#[inline] #[inline]
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("48;5;{}m"), self.0) f.write_str(&self.bg_string())
} }
} }
@ -126,15 +153,41 @@ impl Color for AnsiValue {
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Rgb(pub u8, pub u8, pub u8); pub struct Rgb(pub u8, pub u8, pub u8);
impl Rgb {
/// Returns the ANSI sequence as a string.
pub fn fg_string(self) -> String {
let (mut x, mut y, mut z) = ([0u8; 20], [0u8; 20], [0u8; 20]);
let (x, y, z) = (
self.0.numtoa_str(10, &mut x),
self.1.numtoa_str(10, &mut y),
self.2.numtoa_str(10, &mut z),
);
[csi!("38;2;"), x, ";", y, ";", z, "m"].concat()
}
/// Returns the ANSI sequence as a string.
pub fn bg_string(self) -> String {
let (mut x, mut y, mut z) = ([0u8; 20], [0u8; 20], [0u8; 20]);
let (x, y, z) = (
self.0.numtoa_str(10, &mut x),
self.1.numtoa_str(10, &mut y),
self.2.numtoa_str(10, &mut z),
);
[csi!("48;2;"), x, ";", y, ";", z, "m"].concat()
}
}
impl Color for Rgb { impl Color for Rgb {
#[inline] #[inline]
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("38;2;{};{};{}m"), self.0, self.1, self.2) f.write_str(&self.fg_string())
} }
#[inline] #[inline]
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("48;2;{};{};{}m"), self.0, self.1, self.2) f.write_str(&self.bg_string())
} }
} }
@ -142,15 +195,25 @@ impl Color for Rgb {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Reset; pub struct Reset;
const RESET_FG: &str = csi!("39m");
const RESET_BG: &str = csi!("49m");
impl Reset {
/// Returns the ANSI sequence as a string.
pub fn fg_str(self) -> &'static str { RESET_FG }
/// Returns the ANSI sequence as a string.
pub fn bg_str(self) -> &'static str { RESET_BG }
}
impl Color for Reset { impl Color for Reset {
#[inline] #[inline]
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("39m")) f.write_str(RESET_FG)
} }
#[inline] #[inline]
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result { fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("49m")) f.write_str(RESET_BG)
} }
} }

View File

@ -5,6 +5,7 @@ use std::io::{self, Write, Error, ErrorKind, Read};
use async::async_stdin_until; use async::async_stdin_until;
use std::time::{SystemTime, Duration}; use std::time::{SystemTime, Duration};
use raw::CONTROL_SEQUENCE_TIMEOUT; use raw::CONTROL_SEQUENCE_TIMEOUT;
use numtoa::NumToA;
derive_csi_sequence!("Hide the cursor.", Hide, "?25l"); derive_csi_sequence!("Hide the cursor.", Hide, "?25l");
derive_csi_sequence!("Show the cursor.", Show, "?25h"); derive_csi_sequence!("Show the cursor.", Show, "?25h");
@ -32,6 +33,13 @@ derive_csi_sequence!("Save the cursor.", Save, "s");
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Goto(pub u16, pub u16); pub struct Goto(pub u16, pub u16);
impl From<Goto> for String {
fn from(this: Goto) -> String {
let (mut x, mut y) = ([0u8; 20], [0u8; 20]);
["\x1B[", this.1.numtoa_str(10, &mut x), ";", this.0.numtoa_str(10, &mut y), "H"].concat()
}
}
impl Default for Goto { impl Default for Goto {
fn default() -> Goto { fn default() -> Goto {
Goto(1, 1) Goto(1, 1)
@ -41,8 +49,7 @@ impl Default for Goto {
impl fmt::Display for Goto { impl fmt::Display for Goto {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
debug_assert!(self != &Goto(0, 0), "Goto is one-based."); debug_assert!(self != &Goto(0, 0), "Goto is one-based.");
f.write_str(&String::from(*self))
write!(f, csi!("{};{}H"), self.1, self.0)
} }
} }
@ -50,9 +57,16 @@ impl fmt::Display for Goto {
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Left(pub u16); pub struct Left(pub u16);
impl From<Left> for String {
fn from(this: Left) -> String {
let mut buf = [0u8; 20];
["\x1B[", this.0.numtoa_str(10, &mut buf), "D"].concat()
}
}
impl fmt::Display for Left { impl fmt::Display for Left {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("{}D"), self.0) f.write_str(&String::from(*self))
} }
} }
@ -60,9 +74,16 @@ impl fmt::Display for Left {
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Right(pub u16); pub struct Right(pub u16);
impl From<Right> for String {
fn from(this: Right) -> String {
let mut buf = [0u8; 20];
["\x1B[", this.0.numtoa_str(10, &mut buf), "C"].concat()
}
}
impl fmt::Display for Right { impl fmt::Display for Right {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("{}C"), self.0) f.write_str(&String::from(*self))
} }
} }
@ -70,9 +91,16 @@ impl fmt::Display for Right {
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Up(pub u16); pub struct Up(pub u16);
impl From<Up> for String {
fn from(this: Up) -> String {
let mut buf = [0u8; 20];
["\x1B[", this.0.numtoa_str(10, &mut buf), "A"].concat()
}
}
impl fmt::Display for Up { impl fmt::Display for Up {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("{}A"), self.0) f.write_str(&String::from(*self))
} }
} }
@ -80,9 +108,16 @@ impl fmt::Display for Up {
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub struct Down(pub u16); pub struct Down(pub u16);
impl From<Down> for String {
fn from(this: Down) -> String {
let mut buf = [0u8; 20];
["\x1B[", this.0.numtoa_str(10, &mut buf), "B"].concat()
}
}
impl fmt::Display for Down { impl fmt::Display for Down {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("{}B"), self.0) f.write_str(&String::from(*self))
} }
} }
@ -115,7 +150,7 @@ impl<W: Write> DetectCursorPos for W {
} }
} }
if read_chars.len() == 0 { if read_chars.is_empty() {
return Err(Error::new(ErrorKind::Other, "Cursor position detection timed out.")); return Err(Error::new(ErrorKind::Other, "Cursor position detection timed out."));
} }

View File

@ -11,6 +11,8 @@
//! For more information refer to the [README](https://github.com/redox-os/termion). //! For more information refer to the [README](https://github.com/redox-os/termion).
#![warn(missing_docs)] #![warn(missing_docs)]
extern crate numtoa;
#[cfg(target_os = "redox")] #[cfg(target_os = "redox")]
#[path="sys/redox/mod.rs"] #[path="sys/redox/mod.rs"]
mod sys; mod sys;

View File

@ -15,5 +15,13 @@ macro_rules! derive_csi_sequence {
write!(f, csi!($value)) write!(f, csi!($value))
} }
} }
impl AsRef<[u8]> for $name {
fn as_ref(&self) -> &'static [u8] { csi!($value).as_bytes() }
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &'static str { csi!($value) }
}
}; };
} }