diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 742b36f37b3023ab428c817fc798e9d098e2a686..90d5e9a3ea193da203b65b8ab3ee5b627497ad18 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index a4dca1d1d2c37e73f7c741f52af06cdaf14bfbb3..6e88e81f2aac5daf2753fad3a00c5c2bfdefcc9c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
 
diff --git a/src/color.rs b/src/color.rs
index 6f3fd881385c4211632c4d1e24596580ef7cfe8f..73776c22ebdc929377234589c467a900715f0df0 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -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)
     }
 }
 
diff --git a/src/cursor.rs b/src/cursor.rs
index cf8dc86182a2966e2e98a80c6f596095329db493..b9791a2760c0c7b69518951a686692669f652fed 100644
--- a/src/cursor.rs
+++ b/src/cursor.rs
@@ -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."));
         }
 
diff --git a/src/lib.rs b/src/lib.rs
index 2cb49fa6f076d8075be0bd47c97c85bbee502ad9..1d8f66fa1622d71cc5cb9e36a3cdec4ed68c97f8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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;
diff --git a/src/macros.rs b/src/macros.rs
index 28370e36b4c29a760886e10d7ea016a5e8c5828e..5fd70b933a9e23eafdd2eae8d0548766eb805db2 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -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) }
+        }
     };
 }