Commit acd94a36 authored by Michael Aaron Murphy's avatar Michael Aaron Murphy

Extra derives & performance optimizations

parent 130fc9ac
......@@ -7,19 +7,19 @@ before_script:
stable:
script:
- cargo +stable build --verbose
- cargo +stable test --verbose
- cargo +stable test --release --verbose
- script -q -c "cargo +stable test --verbose"
- script -q -c "cargo +stable test --release --verbose"
beta:
script:
- rustup toolchain add beta
- cargo +beta build --verbose
- cargo +beta test --verbose
- cargo +beta test --release --verbose
- script -q -c "cargo +beta test --verbose"
- script -q -c "cargo +beta test --release --verbose"
nightly:
script:
- rustup toolchain add nightly
- cargo +nightly build --verbose
- cargo +nightly test --verbose
- cargo +nightly test --release --verbose
\ No newline at end of file
- cargo +nightly build --verbose
- script -q -c "cargo +nightly test --verbose"
- script -q -c "cargo +nightly test --release --verbose"
......@@ -9,6 +9,9 @@ license = "MIT"
keywords = ["tty", "color", "terminal", "password", "tui"]
exclude = ["target", "CHANGELOG.md", "image.png", "Cargo.lock"]
[dependencies]
numtoa = { version = "0.1.0", features = ["std"]}
[target.'cfg(not(target_os = "redox"))'.dependencies]
libc = "0.2.8"
......
......@@ -18,6 +18,7 @@ use std::io::{self, Write, Read};
use std::time::{SystemTime, Duration};
use async::async_stdin;
use std::env;
use numtoa::NumToA;
/// A terminal color.
pub trait Color {
......@@ -36,14 +37,24 @@ macro_rules! derive_color {
impl Color for $name {
#[inline]
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("38;5;", $value, "m"))
f.write_str(self.fg_str())
}
#[inline]
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 {
#[inline]
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]
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)]
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 {
#[inline]
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]
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)]
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 {
#[inline]
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("39m"))
f.write_str(RESET_FG)
}
#[inline]
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, csi!("49m"))
f.write_str(RESET_BG)
}
}
......
......@@ -5,6 +5,7 @@ use std::io::{self, Write, Error, ErrorKind, Read};
use async::async_stdin_until;
use std::time::{SystemTime, Duration};
use raw::CONTROL_SEQUENCE_TIMEOUT;
use numtoa::NumToA;
derive_csi_sequence!("Hide the cursor.", Hide, "?25l");
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)]
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 {
fn default() -> Goto {
Goto(1, 1)
......@@ -41,8 +49,7 @@ impl Default for Goto {
impl fmt::Display for Goto {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
debug_assert!(self != &Goto(0, 0), "Goto is one-based.");
write!(f, csi!("{};{}H"), self.1, self.0)
f.write_str(&String::from(*self))
}
}
......@@ -50,9 +57,16 @@ impl fmt::Display for Goto {
#[derive(Copy, Clone, PartialEq, Eq)]
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 {
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)]
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 {
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)]
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 {
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)]
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 {
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."));
}
......
......@@ -11,6 +11,8 @@
//! For more information refer to the [README](https://github.com/redox-os/termion).
#![warn(missing_docs)]
extern crate numtoa;
#[cfg(target_os = "redox")]
#[path="sys/redox/mod.rs"]
mod sys;
......
......@@ -15,5 +15,13 @@ macro_rules! derive_csi_sequence {
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) }
}
};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment