-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #520 - kbknapp:issues-512,518,519, r=kbknapp
Issues 512,518,519
- Loading branch information
Showing
16 changed files
with
802 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
use std::fmt; | ||
|
||
#[cfg(all(feature = "color", not(target_os = "windows")))] | ||
use ansi_term::Colour::{Green, Red, Yellow}; | ||
#[cfg(all(feature = "color", not(target_os = "windows")))] | ||
use ansi_term::ANSIString; | ||
|
||
#[cfg(color)] | ||
use libc; | ||
|
||
#[cfg(color)] | ||
const STDERR: i32 = libc::STDERR_FILENO; | ||
#[cfg(color)] | ||
const STDOUT: i32 = libc::STDOUT_FILENO; | ||
#[cfg(not(color))] | ||
const STDERR: i32 = 0; | ||
#[cfg(not(color))] | ||
const STDOUT: i32 = 0; | ||
|
||
#[doc(hidden)] | ||
#[derive(Debug, PartialEq)] | ||
pub enum ColorWhen { | ||
Auto, // Default | ||
Always, | ||
Never | ||
} | ||
|
||
#[cfg(color)] | ||
pub fn is_a_tty(stderr: bool) -> bool { | ||
let fd = if stderr { STDERR } else { STDOUT }; | ||
unsafe { libc::isatty(fd) != 0 } | ||
} | ||
|
||
#[cfg(not(color))] | ||
pub fn is_a_tty(stderr: bool) -> bool { | ||
false | ||
} | ||
|
||
#[doc(hidden)] | ||
pub struct Colorizer { | ||
use_stderr: bool, | ||
when: ColorWhen | ||
} | ||
|
||
macro_rules! color { | ||
($_self:ident, $c:ident, $m:expr) => { | ||
match $_self.when { | ||
ColorWhen::Auto => if is_a_tty($_self.use_stderr) { | ||
Format::$c($m) | ||
} else { | ||
$m | ||
}, | ||
ColorWhen::Always => Format::$c($m), | ||
ColorWhen::Never => $m, | ||
} | ||
}; | ||
} | ||
|
||
impl Colorizer { | ||
pub fn good<T>(&self, msg: T) -> &fmt::Display where T: fmt::Display { | ||
use Format::Good; | ||
color!(self, Good, msg) | ||
} | ||
pub fn warning<T>(&self, msg: T) -> &fmt::Display where T: fmt::Display { | ||
use Format::Warning; | ||
color!(self, Warning, msg) | ||
} | ||
pub fn error<T>(&self, msg: T) -> &fmt::Display where T: fmt::Display { | ||
use Format::Error; | ||
color!(self, Error, msg) | ||
} | ||
} | ||
|
||
impl Default for Colorizer { | ||
fn default() -> Self { | ||
Colorizer { | ||
use_stderr: true, | ||
when: ColorWhen::Auto | ||
} | ||
} | ||
} | ||
|
||
/// Defines styles for different types of error messages. Defaults to Error=Red, Warning=Yellow, | ||
/// and Good=Green | ||
#[derive(Debug)] | ||
#[doc(hidden)] | ||
pub enum Format<T> { | ||
/// Defines the style used for errors, defaults to Red | ||
Error(T), | ||
/// Defines the style used for warnings, defaults to Yellow | ||
Warning(T), | ||
/// Defines the style used for good values, defaults to Green | ||
Good(T), | ||
} | ||
|
||
#[cfg(all(feature = "color", not(target_os = "windows")))] | ||
impl<T: AsRef<str>> Format<T> { | ||
fn format(&self) -> ANSIString { | ||
match *self { | ||
Format::Error(ref e) => Red.bold().paint(e.as_ref()), | ||
Format::Warning(ref e) => Yellow.paint(e.as_ref()), | ||
Format::Good(ref e) => Green.paint(e.as_ref()), | ||
} | ||
} | ||
} | ||
|
||
#[cfg(all(feature = "color", not(target_os = "windows")))] | ||
impl<T: AsRef<str>> fmt::Display for Format<T> { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "{}", &self.format()) | ||
} | ||
} | ||
|
||
#[cfg(any(not(feature = "color"), target_os = "windows"))] | ||
impl<T: fmt::Display> Format<T> { | ||
fn format(&self) -> &T { | ||
match *self { | ||
Format::Error(ref e) => e, | ||
Format::Warning(ref e) => e, | ||
Format::Good(ref e) => e, | ||
} | ||
} | ||
} | ||
|
||
#[cfg(any(not(feature = "color"), target_os = "windows"))] | ||
impl<T: fmt::Display> fmt::Display for Format<T> { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
write!(f, "{}", &self.format()) | ||
} | ||
} | ||
|
||
#[cfg(all(test, feature = "color", not(target_os = "windows")))] | ||
mod test { | ||
use super::Format; | ||
use ansi_term::Colour::{Green, Red, Yellow}; | ||
|
||
#[test] | ||
fn colored_output() { | ||
let err = Format::Error("error"); | ||
assert_eq!(&*format!("{}", err), | ||
&*format!("{}", Red.bold().paint("error"))); | ||
let good = Format::Good("good"); | ||
assert_eq!(&*format!("{}", good), &*format!("{}", Green.paint("good"))); | ||
let warn = Format::Warning("warn"); | ||
assert_eq!(&*format!("{}", warn), &*format!("{}", Yellow.paint("warn"))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.