diff options
Diffstat (limited to 'vendor/termcolor/src/lib.rs')
-rw-r--r-- | vendor/termcolor/src/lib.rs | 144 |
1 files changed, 117 insertions, 27 deletions
diff --git a/vendor/termcolor/src/lib.rs b/vendor/termcolor/src/lib.rs index c93cf7bc8..062df1801 100644 --- a/vendor/termcolor/src/lib.rs +++ b/vendor/termcolor/src/lib.rs @@ -98,18 +98,10 @@ use atty; use termcolor::{ColorChoice, StandardStream}; let preference = argv.get_flag("color").unwrap_or("auto"); -let choice = match preference { - "always" => ColorChoice::Always, - "ansi" => ColorChoice::AlwaysAnsi, - "auto" => { - if atty::is(atty::Stream::Stdout) { - ColorChoice::Auto - } else { - ColorChoice::Never - } - } - _ => ColorChoice::Never, -}; +let mut choice = preference.parse::<ColorChoice>()?; +if choice == ColorChoice::Auto && !atty::is(atty::Stream::Stdout) { + choice = ColorChoice::Never; +} let stdout = StandardStream::stdout(choice); // ... write to stdout ``` @@ -117,7 +109,7 @@ let stdout = StandardStream::stdout(choice); Currently, `termcolor` does not provide anything to do this for you. */ -#![deny(missing_docs)] +#![deny(missing_debug_implementations, missing_docs)] // #[cfg(doctest)] // use doc_comment::doctest; @@ -203,6 +195,13 @@ impl<T: ?Sized + WriteColor> WriteColor for Box<T> { } /// ColorChoice represents the color preferences of an end user. +/// +/// The `Default` implementation for this type will select `Auto`, which tries +/// to do the right thing based on the current environment. +/// +/// The `FromStr` implementation for this type converts a lowercase kebab-case +/// string of the variant name to the corresponding variant. Any other string +/// results in an error. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ColorChoice { /// Try very hard to emit colors. This includes emitting ANSI colors @@ -219,6 +218,29 @@ pub enum ColorChoice { Never, } +/// The default is `Auto`. +impl Default for ColorChoice { + fn default() -> ColorChoice { + ColorChoice::Auto + } +} + +impl FromStr for ColorChoice { + type Err = ColorChoiceParseError; + + fn from_str(s: &str) -> Result<ColorChoice, ColorChoiceParseError> { + match s.to_lowercase().as_str() { + "always" => Ok(ColorChoice::Always), + "always-ansi" => Ok(ColorChoice::AlwaysAnsi), + "never" => Ok(ColorChoice::Never), + "auto" => Ok(ColorChoice::Auto), + unknown => Err(ColorChoiceParseError { + unknown_choice: unknown.to_string(), + }), + } + } +} + impl ColorChoice { /// Returns true if we should attempt to write colored output. fn should_attempt_color(&self) -> bool { @@ -291,6 +313,25 @@ impl ColorChoice { } } +/// An error that occurs when parsing a `ColorChoice` fails. +#[derive(Clone, Debug)] +pub struct ColorChoiceParseError { + unknown_choice: String, +} + +impl std::error::Error for ColorChoiceParseError {} + +impl fmt::Display for ColorChoiceParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "unrecognized color choice '{}': valid choices are: \ + always, always-ansi, never, auto", + self.unknown_choice, + ) + } +} + /// `std::io` implements `Stdout` and `Stderr` (and their `Lock` variants) as /// separate types, which makes it difficult to abstract over them. We use /// some simple internal enum types to work around this. @@ -302,6 +343,7 @@ enum StandardStreamType { StderrBuffered, } +#[derive(Debug)] enum IoStandardStream { Stdout(io::Stdout), Stderr(io::Stderr), @@ -371,6 +413,7 @@ impl io::Write for IoStandardStream { // Same rigmarole for the locked variants of the standard streams. +#[derive(Debug)] enum IoStandardStreamLock<'a> { StdoutLock(io::StdoutLock<'a>), StderrLock(io::StderrLock<'a>), @@ -396,6 +439,7 @@ impl<'a> io::Write for IoStandardStreamLock<'a> { /// Satisfies `io::Write` and `WriteColor`, and supports optional coloring /// to either of the standard output streams, stdout and stderr. +#[derive(Debug)] pub struct StandardStream { wtr: LossyStandardStream<WriterInner<IoStandardStream>>, } @@ -407,17 +451,20 @@ pub struct StandardStream { /// /// The lifetime `'a` refers to the lifetime of the corresponding /// `StandardStream`. +#[derive(Debug)] pub struct StandardStreamLock<'a> { wtr: LossyStandardStream<WriterInnerLock<'a, IoStandardStreamLock<'a>>>, } /// Like `StandardStream`, but does buffered writing. +#[derive(Debug)] pub struct BufferedStandardStream { wtr: LossyStandardStream<WriterInner<IoStandardStream>>, } /// WriterInner is a (limited) generic representation of a writer. It is /// limited because W should only ever be stdout/stderr on Windows. +#[derive(Debug)] enum WriterInner<W> { NoColor(NoColor<W>), Ansi(Ansi<W>), @@ -430,6 +477,7 @@ enum WriterInner<W> { /// WriterInnerLock is a (limited) generic representation of a writer. It is /// limited because W should only ever be stdout/stderr on Windows. +#[derive(Debug)] enum WriterInnerLock<'a, W> { NoColor(NoColor<W>), Ansi(Ansi<W>), @@ -855,6 +903,7 @@ impl<'a, W: io::Write> WriteColor for WriterInnerLock<'a, W> { /// /// It is intended for a `BufferWriter` to be put in an `Arc` and written to /// from multiple threads simultaneously. +#[derive(Debug)] pub struct BufferWriter { stream: LossyStandardStream<IoStandardStream>, printed: AtomicBool, @@ -908,7 +957,7 @@ impl BufferWriter { } let stream = LossyStandardStream::new(IoStandardStream::new(sty)); BufferWriter { - stream: stream, + stream, printed: AtomicBool::new(false), separator: None, color_choice: choice, @@ -1013,9 +1062,11 @@ impl BufferWriter { /// method, which will take color preferences and the environment into /// account. However, buffers can also be manually created using `no_color`, /// `ansi` or `console` (on Windows). +#[derive(Debug)] pub struct Buffer(BufferInner); /// BufferInner is an enumeration of different buffer types. +#[derive(Debug)] enum BufferInner { /// No coloring information should be applied. This ignores all coloring /// directives. @@ -1195,6 +1246,7 @@ impl WriteColor for Buffer { } /// Satisfies `WriteColor` but ignores all color options. +#[derive(Debug)] pub struct NoColor<W>(W); impl<W: Write> NoColor<W> { @@ -1255,6 +1307,7 @@ impl<W: io::Write> WriteColor for NoColor<W> { } /// Satisfies `WriteColor` using standard ANSI escape sequences. +#[derive(Debug)] pub struct Ansi<W>(W); impl<W: Write> Ansi<W> { @@ -1286,6 +1339,17 @@ impl<W: io::Write> io::Write for Ansi<W> { self.0.write(buf) } + // Adding this method here is not required because it has a default impl, + // but it seems to provide a perf improvement in some cases when using + // a `BufWriter` with lots of writes. + // + // See https://github.com/BurntSushi/termcolor/pull/56 for more details + // and a minimized example. + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + self.0.write_all(buf) + } + #[inline] fn flush(&mut self) -> io::Result<()> { self.0.flush() @@ -1315,6 +1379,9 @@ impl<W: io::Write> WriteColor for Ansi<W> { if spec.underline { self.write_str("\x1B[4m")?; } + if spec.strikethrough { + self.write_str("\x1B[9m")?; + } if let Some(ref c) = spec.fg_color { self.write_color(true, c, spec.intense)?; } @@ -1586,6 +1653,7 @@ pub struct ColorSpec { dimmed: bool, italic: bool, reset: bool, + strikethrough: bool, } impl Default for ColorSpec { @@ -1599,6 +1667,7 @@ impl Default for ColorSpec { dimmed: false, italic: false, reset: true, + strikethrough: false, } } } @@ -1691,6 +1760,21 @@ impl ColorSpec { self } + /// Get whether this is strikethrough or not. + /// + /// Note that the strikethrough setting has no effect in a Windows console. + pub fn strikethrough(&self) -> bool { + self.strikethrough + } + + /// Set whether the text is strikethrough or not. + /// + /// Note that the strikethrough setting has no effect in a Windows console. + pub fn set_strikethrough(&mut self, yes: bool) -> &mut ColorSpec { + self.strikethrough = yes; + self + } + /// Get whether reset is enabled or not. /// /// reset is enabled by default. When disabled and using ANSI escape @@ -1752,6 +1836,7 @@ impl ColorSpec { && !self.dimmed && !self.italic && !self.intense + && !self.strikethrough } /// Clears this color specification so that it has no color/style settings. @@ -1763,6 +1848,7 @@ impl ColorSpec { self.intense = false; self.dimmed = false; self.italic = false; + self.strikethrough = false; } /// Writes this color spec to the given Windows console. @@ -1999,6 +2085,7 @@ impl FromStr for Color { } } +#[derive(Debug)] struct LossyStandardStream<W> { wtr: W, #[cfg(windows)] @@ -2008,14 +2095,14 @@ struct LossyStandardStream<W> { impl<W: io::Write> LossyStandardStream<W> { #[cfg(not(windows))] fn new(wtr: W) -> LossyStandardStream<W> { - LossyStandardStream { wtr: wtr } + LossyStandardStream { wtr } } #[cfg(windows)] fn new(wtr: W) -> LossyStandardStream<W> { let is_console = wincon::Console::stdout().is_ok() || wincon::Console::stderr().is_ok(); - LossyStandardStream { wtr: wtr, is_console: is_console } + LossyStandardStream { wtr, is_console } } #[cfg(not(windows))] @@ -2025,7 +2112,7 @@ impl<W: io::Write> LossyStandardStream<W> { #[cfg(windows)] fn wrap<Q: io::Write>(&self, wtr: Q) -> LossyStandardStream<Q> { - LossyStandardStream { wtr: wtr, is_console: self.is_console } + LossyStandardStream { wtr, is_console: self.is_console } } fn get_ref(&self) -> &W { @@ -2216,16 +2303,19 @@ mod tests { for underline in vec![false, true] { for intense in vec![false, true] { for italic in vec![false, true] { - for dimmed in vec![false, true] { - let mut color = ColorSpec::new(); - color.set_fg(fg); - color.set_bg(bg); - color.set_bold(bold); - color.set_underline(underline); - color.set_intense(intense); - color.set_dimmed(dimmed); - color.set_italic(italic); - result.push(color); + for strikethrough in vec![false, true] { + for dimmed in vec![false, true] { + let mut color = ColorSpec::new(); + color.set_fg(fg); + color.set_bg(bg); + color.set_bold(bold); + color.set_underline(underline); + color.set_intense(intense); + color.set_italic(italic); + color.set_dimmed(dimmed); + color.set_strikethrough(strikethrough); + result.push(color); + } } } } |