diff options
author | Andrew Gallant <jamslam@gmail.com> | 2018-07-17 18:03:38 -0400 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2018-07-17 18:03:38 -0400 |
commit | df469fe1b4f723c98a9b4aa4cd96a85a7986fd2c (patch) | |
tree | 23fadaba59fabcbd9061cda063063eb4ee1c4c3e /termcolor | |
parent | b64475aeac00c430b58ff953a27d0d448161625e (diff) |
termcolor: moved to its own repository
We also move wincolor with it.
Fixes #924
Diffstat (limited to 'termcolor')
-rw-r--r-- | termcolor/COPYING | 3 | ||||
-rw-r--r-- | termcolor/Cargo.toml | 20 | ||||
-rw-r--r-- | termcolor/LICENSE-MIT | 21 | ||||
-rw-r--r-- | termcolor/README.md | 88 | ||||
-rw-r--r-- | termcolor/UNLICENSE | 24 | ||||
-rw-r--r-- | termcolor/src/lib.rs | 1832 |
6 files changed, 2 insertions, 1986 deletions
diff --git a/termcolor/COPYING b/termcolor/COPYING deleted file mode 100644 index bb9c20a0..00000000 --- a/termcolor/COPYING +++ /dev/null @@ -1,3 +0,0 @@ -This project is dual-licensed under the Unlicense and MIT licenses. - -You may use this code under the terms of either license. diff --git a/termcolor/Cargo.toml b/termcolor/Cargo.toml deleted file mode 100644 index d0a0ff4c..00000000 --- a/termcolor/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "termcolor" -version = "0.3.6" #:version -authors = ["Andrew Gallant <jamslam@gmail.com>"] -description = """ -A simple cross platform library for writing colored text to a terminal. -""" -documentation = "https://docs.rs/termcolor" -homepage = "https://github.com/BurntSushi/ripgrep/tree/master/termcolor" -repository = "https://github.com/BurntSushi/ripgrep/tree/master/termcolor" -readme = "README.md" -keywords = ["windows", "win", "color", "ansi", "console"] -license = "Unlicense/MIT" - -[lib] -name = "termcolor" -bench = false - -[target.'cfg(windows)'.dependencies] -wincolor = { version = "0.1.6", path = "../wincolor" } diff --git a/termcolor/LICENSE-MIT b/termcolor/LICENSE-MIT deleted file mode 100644 index 3b0a5dc0..00000000 --- a/termcolor/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Andrew Gallant - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/termcolor/README.md b/termcolor/README.md index 7317d431..f09ea149 100644 --- a/termcolor/README.md +++ b/termcolor/README.md @@ -1,86 +1,2 @@ -termcolor -========= -A simple cross platform library for writing colored text to a terminal. This -library writes colored text either using standard ANSI escape sequences or -by interacting with the Windows console. Several convenient abstractions -are provided for use in single-threaded or multi-threaded command line -applications. - -[![Linux build status](https://api.travis-ci.org/BurntSushi/ripgrep.png)](https://travis-ci.org/BurntSushi/ripgrep) -[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/ripgrep?svg=true)](https://ci.appveyor.com/project/BurntSushi/ripgrep) -[![](https://img.shields.io/crates/v/termcolor.svg)](https://crates.io/crates/termcolor) - -Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). - -### Documentation - -[https://docs.rs/termcolor](https://docs.rs/termcolor) - -### Usage - -Add this to your `Cargo.toml`: - -```toml -[dependencies] -termcolor = "0.3" -``` - -and this to your crate root: - -```rust -extern crate termcolor; -``` - -### Organization - -The `WriteColor` trait extends the `io::Write` trait with methods for setting -colors or resetting them. - -`StandardStream` and `StandardStreamLock` both satisfy `WriteColor` and are -analogous to `std::io::Stdout` and `std::io::StdoutLock`, or `std::io::Stderr` -and `std::io::StderrLock`. - -`Buffer` is an in memory buffer that supports colored text. In a parallel -program, each thread might write to its own buffer. A buffer can be printed to -stdout or stderr using a `BufferWriter`. The advantage of this design is that -each thread can work in parallel on a buffer without having to synchronize -access to global resources such as the Windows console. Moreover, this design -also prevents interleaving of buffer output. - -`Ansi` and `NoColor` both satisfy `WriteColor` for arbitrary implementors of -`io::Write`. These types are useful when you know exactly what you need. An -analogous type for the Windows console is not provided since it cannot exist. - -### Example: using `StandardStream` - -The `StandardStream` type in this crate works similarly to `std::io::Stdout`, -except it is augmented with methods for coloring by the `WriteColor` trait. -For example, to write some green text: - -```rust -use std::io::Write; -use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; - -let mut stdout = StandardStream::stdout(ColorChoice::Always); -stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; -writeln!(&mut stdout, "green text!")?; -``` - -### Example: using `BufferWriter` - -A `BufferWriter` can create buffers and write buffers to stdout or stderr. It -does *not* implement `io::Write` or `WriteColor` itself. Instead, `Buffer` -implements `io::Write` and `termcolor::WriteColor`. - -This example shows how to print some green text to stderr. - -```rust -use std::io::Write; -use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; - -let mut bufwtr = BufferWriter::stderr(ColorChoice::Always); -let mut buffer = bufwtr.buffer(); -buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; -writeln!(&mut buffer, "green text!")?; -bufwtr.print(&buffer)?; -``` +termcolor has moved to its own repository: +https://github.com/BurntSushi/termcolor diff --git a/termcolor/UNLICENSE b/termcolor/UNLICENSE deleted file mode 100644 index 68a49daa..00000000 --- a/termcolor/UNLICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to <http://unlicense.org/> diff --git a/termcolor/src/lib.rs b/termcolor/src/lib.rs deleted file mode 100644 index 7d904917..00000000 --- a/termcolor/src/lib.rs +++ /dev/null @@ -1,1832 +0,0 @@ -/*! -This crate provides a cross platform abstraction for writing colored text to -a terminal. Colors are written using either ANSI escape sequences or by -communicating with a Windows console. Much of this API was motivated by use -inside command line applications, where colors or styles can be configured -by the end user and/or the environment. - -This crate also provides platform independent support for writing colored text -to an in memory buffer. While this is easy to do with ANSI escape sequences -(because they are in the buffer themselves), it is trickier to do with the -Windows console API, which requires synchronous communication. - -# Organization - -The `WriteColor` trait extends the `io::Write` trait with methods for setting -colors or resetting them. - -`StandardStream` and `StandardStreamLock` both satisfy `WriteColor` and are -analogous to `std::io::Stdout` and `std::io::StdoutLock`, or `std::io::Stderr` -and `std::io::StderrLock`. - -`Buffer` is an in memory buffer that supports colored text. In a parallel -program, each thread might write to its own buffer. A buffer can be printed to -using a `BufferWriter`. The advantage of this design is that each thread can -work in parallel on a buffer without having to synchronize access to global -resources such as the Windows console. Moreover, this design also prevents -interleaving of buffer output. - -`Ansi` and `NoColor` both satisfy `WriteColor` for arbitrary implementors of -`io::Write`. These types are useful when you know exactly what you need. An -analogous type for the Windows console is not provided since it cannot exist. - -# Example: using `StandardStream` - -The `StandardStream` type in this crate works similarly to `std::io::Stdout`, -except it is augmented with methods for coloring by the `WriteColor` trait. -For example, to write some green text: - -```rust,no_run -# fn test() -> Result<(), Box<::std::error::Error>> { -use std::io::Write; -use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; - -let mut stdout = StandardStream::stdout(ColorChoice::Always); -stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; -writeln!(&mut stdout, "green text!")?; -# Ok(()) } -``` - -# Example: using `BufferWriter` - -A `BufferWriter` can create buffers and write buffers to stdout or stderr. It -does *not* implement `io::Write` or `WriteColor` itself. Instead, `Buffer` -implements `io::Write` and `io::WriteColor`. - -This example shows how to print some green text to stderr. - -```rust,no_run -# fn test() -> Result<(), Box<::std::error::Error>> { -use std::io::Write; -use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; - -let mut bufwtr = BufferWriter::stderr(ColorChoice::Always); -let mut buffer = bufwtr.buffer(); -buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; -writeln!(&mut buffer, "green text!")?; -bufwtr.print(&buffer)?; -# Ok(()) } -``` -*/ - -#![deny(missing_docs)] - -#[cfg(windows)] -extern crate wincolor; - -use std::env; -use std::error; -use std::fmt; -use std::io::{self, Write}; -use std::str::FromStr; -#[cfg(windows)] -use std::sync::{Mutex, MutexGuard}; -use std::sync::atomic::{AtomicBool, Ordering}; - -/// This trait describes the behavior of writers that support colored output. -pub trait WriteColor: io::Write { - /// Returns true if and only if the underlying writer supports colors. - fn supports_color(&self) -> bool; - - /// Set the color settings of the writer. - /// - /// Subsequent writes to this writer will use these settings until either - /// `reset` is called or new color settings are set. - /// - /// If there was a problem setting the color settings, then an error is - /// returned. - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()>; - - /// Reset the current color settings to their original settings. - /// - /// If there was a problem resetting the color settings, then an error is - /// returned. - fn reset(&mut self) -> io::Result<()>; - - /// Returns true if and only if the underlying writer must synchronously - /// interact with an end user's device in order to control colors. By - /// default, this always returns `false`. - /// - /// In practice, this should return `true` if the underlying writer is - /// manipulating colors using the Windows console APIs. - /// - /// This is useful for writing generic code (such as a buffered writer) - /// that can perform certain optimizations when the underlying writer - /// doesn't rely on synchronous APIs. For example, ANSI escape sequences - /// can be passed through to the end user's device as is. - fn is_synchronous(&self) -> bool { - false - } -} - -impl<'a, T: ?Sized + WriteColor> WriteColor for &'a mut T { - fn supports_color(&self) -> bool { (&**self).supports_color() } - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - (&mut **self).set_color(spec) - } - fn reset(&mut self) -> io::Result<()> { (&mut **self).reset() } - fn is_synchronous(&self) -> bool { (&**self).is_synchronous() } -} - -impl<T: ?Sized + WriteColor> WriteColor for Box<T> { - fn supports_color(&self) -> bool { (&**self).supports_color() } - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - (&mut **self).set_color(spec) - } - fn reset(&mut self) -> io::Result<()> { (&mut **self).reset() } - fn is_synchronous(&self) -> bool { (&**self).is_synchronous() } -} - -/// ColorChoice represents the color preferences of an end user. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum ColorChoice { - /// Try very hard to emit colors. This includes emitting ANSI colors - /// on Windows if the console API is unavailable. - Always, - /// AlwaysAnsi is like Always, except it never tries to use anything other - /// than emitting ANSI color codes. - AlwaysAnsi, - /// Try to use colors, but don't force the issue. If the console isn't - /// available on Windows, or if TERM=dumb, for example, then don't use - /// colors. - Auto, - /// Never emit colors. - Never, -} - -impl ColorChoice { - /// Returns true if we should attempt to write colored output. - #[cfg(not(windows))] - fn should_attempt_color(&self) -> bool { - match *self { - ColorChoice::Always => true, - ColorChoice::AlwaysAnsi => true, - ColorChoice::Never => false, - ColorChoice::Auto => { - match env::var("TERM") { - Err(_) => false, - Ok(k) => k != "dumb", - } - } - } - } - - /// Returns true if we should attempt to write colored output. - #[cfg(windows)] - fn should_attempt_color(&self) -> bool { - match *self { - ColorChoice::Always => true, - ColorChoice::AlwaysAnsi => true, - ColorChoice::Never => false, - ColorChoice::Auto => { - match env::var("TERM") { - Err(_) => true, - Ok(k) => k != "dumb", - } - } - } - } - - /// Returns true if this choice should forcefully use ANSI color codes. - /// - /// It's possible that ANSI is still the correct choice even if this - /// returns false. - #[cfg(windows)] - fn should_ansi(&self) -> bool { - match *self { - ColorChoice::Always => false, - ColorChoice::AlwaysAnsi => true, - ColorChoice::Never => false, - ColorChoice::Auto => { - match env::var("TERM") { - Err(_) => false, - // cygwin doesn't seem to support ANSI escape sequences - // and instead has its own variety. However, the Windows - // console API may be available. - Ok(k) => k != "dumb" && k != "cygwin", - } - } - } - } -} - -/// `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. - -enum StandardStreamType { - Stdout, - Stderr, - StdoutBuffered, - StderrBuffered, -} - -enum IoStandardStream { - Stdout(io::Stdout), - Stderr(io::Stderr), - StdoutBuffered(io::BufWriter<io::Stdout>), - StderrBuffered(io::BufWriter<io::Stderr>), -} - -impl IoStandardStream { - fn new(sty: StandardStreamType) -> IoStandardStream { - match sty { - StandardStreamType::Stdout => { - IoStandardStream::Stdout(io::stdout()) - } - StandardStreamType::Stderr => { - IoStandardStream::Stderr(io::stderr()) - } - StandardStreamType::StdoutBuffered => { - let wtr = io::BufWriter::new(io::stdout()); - IoStandardStream::StdoutBuffered(wtr) - } - StandardStreamType::StderrBuffered => { - let wtr = io::BufWriter::new(io::stderr()); - IoStandardStream::StderrBuffered(wtr) - } - } - } - - fn lock(&self) -> IoStandardStreamLock { - match *self { - IoStandardStream::Stdout(ref s) => { - IoStandardStreamLock::StdoutLock(s.lock()) - } - IoStandardStream::Stderr(ref s) => { - IoStandardStreamLock::StderrLock(s.lock()) - } - IoStandardStream::StdoutBuffered(_) - | IoStandardStream::StderrBuffered(_) => { - // We don't permit this case to ever occur in the public API, - // so it's OK to panic. - panic!("cannot lock a buffered standard stream") - } - } - } -} - -impl io::Write for IoStandardStream { - fn write(&mut self, b: &[u8]) -> io::Result<usize> { - match *self { - IoStandardStream::Stdout(ref mut s) => s.write(b), - IoStandardStream::Stderr(ref mut s) => s.write(b), - IoStandardStream::StdoutBuffered(ref mut s) => s.write(b), - IoStandardStream::StderrBuffered(ref mut s) => s.write(b), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - IoStandardStream::Stdout(ref mut s) => s.flush(), - IoStandardStream::Stderr(ref mut s) => s.flush(), - IoStandardStream::StdoutBuffered(ref mut s) => s.flush(), - IoStandardStream::StderrBuffered(ref mut s) => s.flush(), - } - } -} - -// Same rigmarole for the locked variants of the standard streams. - -enum IoStandardStreamLock<'a> { - StdoutLock(io::StdoutLock<'a>), - StderrLock(io::StderrLock<'a>), -} - -impl<'a> io::Write for IoStandardStreamLock<'a> { - fn write(&mut self, b: &[u8]) -> io::Result<usize> { - match *self { - IoStandardStreamLock::StdoutLock(ref mut s) => s.write(b), - IoStandardStreamLock::StderrLock(ref mut s) => s.write(b), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - IoStandardStreamLock::StdoutLock(ref mut s) => s.flush(), - IoStandardStreamLock::StderrLock(ref mut s) => s.flush(), - } - } -} - -/// Satisfies `io::Write` and `WriteColor`, and supports optional coloring -/// to either of the standard output streams, stdout and stderr. -pub struct StandardStream { - wtr: LossyStandardStream<WriterInner<IoStandardStream>>, -} - -/// `StandardStreamLock` is a locked reference to a `StandardStream`. -/// -/// This implements the `io::Write` and `WriteColor` traits, and is constructed -/// via the `Write::lock` method. -/// -/// The lifetime `'a` refers to the lifetime of the corresponding -/// `StandardStream`. -pub struct StandardStreamLock<'a> { - wtr: LossyStandardStream<WriterInnerLock<'a, IoStandardStreamLock<'a>>>, -} - -/// Like `StandardStream`, but does buffered writing. -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. -enum WriterInner<W> { - NoColor(NoColor<W>), - Ansi(Ansi<W>), - #[cfg(windows)] - Windows { wtr: W, console: Mutex<wincolor::Console> }, -} - -/// WriterInnerLock is a (limited) generic representation of a writer. It is -/// limited because W should only ever be stdout/stderr on Windows. -enum WriterInnerLock<'a, W> { - NoColor(NoColor<W>), - Ansi(Ansi<W>), - /// What a gross hack. On Windows, we need to specify a lifetime for the - /// console when in a locked state, but obviously don't need to do that - /// on Unix, which makes the `'a` unused. To satisfy the compiler, we need - /// a PhantomData. - #[allow(dead_code)] - Unreachable(::std::marker::PhantomData<&'a ()>), - #[cfg(windows)] - Windows { wtr: W, console: MutexGuard<'a, wincolor::Console> }, -} - -impl StandardStream { - /// Create a new `StandardStream` with the given color preferences that - /// writes to standard output. - /// - /// On Windows, if coloring is desired and a Windows console could not be - /// found, then ANSI escape sequences are used instead. - /// - /// The specific color/style settings can be configured when writing via - /// the `WriteColor` trait. - pub fn stdout(choice: ColorChoice) -> StandardStream { - let wtr = WriterInner::create(StandardStreamType::Stdout, choice); - StandardStream { wtr: LossyStandardStream::new(wtr) } - } - - /// Create a new `StandardStream` with the given color preferences that - /// writes to standard error. - /// - /// On Windows, if coloring is desired and a Windows console could not be - /// found, then ANSI escape sequences are used instead. - /// - /// The specific color/style settings can be configured when writing via - /// the `WriteColor` trait. - pub fn stderr(choice: ColorChoice) -> StandardStream { - let wtr = WriterInner::create(StandardStreamType::Stderr, choice); - StandardStream { wtr: LossyStandardStream::new(wtr) } - } - - /// Lock the underlying writer. - /// - /// The lock guard returned also satisfies `io::Write` and - /// `WriteColor`. - /// - /// This method is **not reentrant**. It may panic if `lock` is called - /// while a `StandardStreamLock` is still alive. - pub fn lock(&self) -> StandardStreamLock { - StandardStreamLock::from_stream(self) - } -} - -impl<'a> StandardStreamLock<'a> { - #[cfg(not(windows))] - fn from_stream(stream: &StandardStream) -> StandardStreamLock { - let locked = match *stream.wtr.get_ref() { - WriterInner::NoColor(ref w) => { - WriterInnerLock::NoColor(NoColor(w.0.lock())) - } - WriterInner::Ansi(ref w) => { - WriterInnerLock::Ansi(Ansi(w.0.lock())) - } - }; - StandardStreamLock { wtr: stream.wtr.wrap(locked) } - } - - #[cfg(windows)] - fn from_stream(stream: &StandardStream) -> StandardStreamLock { - let locked = match *stream.wtr.get_ref() { - WriterInner::NoColor(ref w) => { - WriterInnerLock::NoColor(NoColor(w.0.lock())) - } - WriterInner::Ansi(ref w) => { - WriterInnerLock::Ansi(Ansi(w.0.lock())) - } - #[cfg(windows)] - WriterInner::Windows { ref wtr, ref console } => { - WriterInnerLock::Windows { - wtr: wtr.lock(), - console: console.lock().unwrap(), - } - } - }; - StandardStreamLock { wtr: stream.wtr.wrap(locked) } - } -} - -impl BufferedStandardStream { - /// Create a new `BufferedStandardStream` with the given color preferences - /// that writes to standard output via a buffered writer. - /// - /// On Windows, if coloring is desired and a Windows console could not be - /// found, then ANSI escape sequences are used instead. - /// - /// The specific color/style settings can be configured when writing via - /// the `WriteColor` trait. - pub fn stdout(choice: ColorChoice) -> BufferedStandardStream { - let wtr = WriterInner::create( - StandardStreamType::StdoutBuffered, - choice, - ); - BufferedStandardStream { wtr: LossyStandardStream::new(wtr) } - } - - /// Create a new `BufferedStandardStream` with the given color preferences - /// that writes to standard error via a buffered writer. - /// - /// On Windows, if coloring is desired and a Windows console could not be - /// found, then ANSI escape sequences are used instead. - /// - /// The specific color/style settings can be configured when writing via - /// the `WriteColor` trait. - pub fn stderr(choice: ColorChoice) -> BufferedStandardStream { - let wtr = WriterInner::create( - StandardStreamType::StderrBuffered, - choice, - ); - BufferedStandardStream { wtr: LossyStandardStream::new(wtr) } - } -} - -impl WriterInner<IoStandardStream> { - /// Create a new inner writer for a standard stream with the given color - /// preferences. - #[cfg(not(windows))] - fn create( - sty: StandardStreamType, - choice: ColorChoice, - ) -> WriterInner<IoStandardStream> { - if choice.should_attempt_color() { - WriterInner::Ansi(Ansi(IoStandardStream::new(sty))) - } else { - WriterInner::NoColor(NoColor(IoStandardStream::new(sty))) - } - } - - /// Create a new inner writer for a standard stream with the given color - /// preferences. - /// - /// If coloring is desired and a Windows console could not be found, then - /// ANSI escape sequences are used instead. - #[cfg(windows)] - fn create( - sty: StandardStreamType, - choice: ColorChoice, - ) -> WriterInner<IoStandardStream> { - let mut con = match sty { - StandardStreamType::Stdout => wincolor::Console::stdout(), - StandardStreamType::Stderr => wincolor::Console::stderr(), - StandardStreamType::StdoutBuffered => wincolor::Console::stdout(), - StandardStreamType::StderrBuffered => wincolor::Console::stderr(), - }; - let is_console_virtual = con.as_mut().map(|con| { - con.set_virtual_terminal_processing(true).is_ok() - }).unwrap_or(false); - if choice.should_attempt_color() { - if choice.should_ansi() || is_console_virtual { - WriterInner::Ansi(Ansi(IoStandardStream::new(sty))) - } else if let Ok(console) = con { - WriterInner::Windows { - wtr: IoStandardStream::new(sty), - console: Mutex::new(console), - } - } else { - WriterInner::Ansi(Ansi(IoStandardStream::new(sty))) - } - } else { - WriterInner::NoColor(NoColor(IoStandardStream::new(sty))) - } - } -} - -impl io::Write for StandardStream { - fn write(&mut self, b: &[u8]) -> io::Result<usize> { self.wtr.write(b) } - fn flush(&mut self) -> io::Result<()> { self.wtr.flush() } -} - -impl WriteColor for StandardStream { - fn supports_color(&self) -> bool { self.wtr.supports_color() } - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - self.wtr.set_color(spec) - } - fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } - fn is_synchronous(&self) -> bool { self.wtr.is_synchronous() } -} - -impl<'a> io::Write for StandardStreamLock<'a> { - fn write(&mut self, b: &[u8]) -> io::Result<usize> { self.wtr.write(b) } - fn flush(&mut self) -> io::Result<()> { self.wtr.flush() } -} - -impl<'a> WriteColor for StandardStreamLock<'a> { - fn supports_color(&self) -> bool { self.wtr.supports_color() } - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - self.wtr.set_color(spec) - } - fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } - fn is_synchronous(&self) -> bool { self.wtr.is_synchronous() } -} - -impl io::Write for BufferedStandardStream { - fn write(&mut self, b: &[u8]) -> io::Result<usize> { self.wtr.write(b) } - fn flush(&mut self) -> io::Result<()> { self.wtr.flush() } -} - -impl WriteColor for BufferedStandardStream { - fn supports_color(&self) -> bool { self.wtr.supports_color() } - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - if self.is_synchronous() { - self.wtr.flush()?; - } - self.wtr.set_color(spec) - } - fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } - fn is_synchronous(&self) -> bool { self.wtr.is_synchronous() } -} - -impl<W: io::Write> io::Write for WriterInner<W> { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - match *self { - WriterInner::NoColor(ref mut wtr) => wtr.write(buf), - WriterInner::Ansi(ref mut wtr) => wtr.write(buf), - #[cfg(windows)] - WriterInner::Windows { ref mut wtr, .. } => wtr.write(buf), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - WriterInner::NoColor(ref mut wtr) => wtr.flush(), - WriterInner::Ansi(ref mut wtr) => wtr.flush(), - #[cfg(windows)] - WriterInner::Windows { ref mut wtr, .. } => wtr.flush(), - } - } -} - -impl<W: io::Write> WriteColor for WriterInner<W> { - fn supports_color(&self) -> bool { - match *self { - WriterInner::NoColor(_) => false, - WriterInner::Ansi(_) => true, - #[cfg(windows)] - WriterInner::Windows { .. } => true, - } - } - - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - match *self { - WriterInner::NoColor(ref mut wtr) => wtr.set_color(spec), - WriterInner::Ansi(ref mut wtr) => wtr.set_color(spec), - #[cfg(windows)] - WriterInner::Windows { ref mut wtr, ref console } => { - wtr.flush()?; - let mut console = console.lock().unwrap(); - spec.write_console(&mut *console) - } - } - } - - fn reset(&mut self) -> io::Result<()> { - match *self { - WriterInner::NoColor(ref mut wtr) => wtr.reset(), - WriterInner::Ansi(ref mut wtr) => wtr.reset(), - #[cfg(windows)] - WriterInner::Windows { ref mut wtr, ref mut console } => { - wtr.flush()?; - console.lock().unwrap().reset()?; - Ok(()) - } - } - } - - fn is_synchronous(&self) -> bool { - match *self { - WriterInner::NoColor(_) => false, - WriterInner::Ansi(_) => false, - #[cfg(windows)] - WriterInner::Windows {..} => true, - } - } -} - -impl<'a, W: io::Write> io::Write for WriterInnerLock<'a, W> { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - match *self { - WriterInnerLock::Unreachable(_) => unreachable!(), - WriterInnerLock::NoColor(ref mut wtr) => wtr.write(buf), - WriterInnerLock::Ansi(ref mut wtr) => wtr.write(buf), - #[cfg(windows)] - WriterInnerLock::Windows { ref mut wtr, .. } => wtr.write(buf), - } - } - - fn flush(&mut self) -> io::Result<()> { - match *self { - WriterInnerLock::Unreachable(_) => unreachable!(), - WriterInnerLock::NoColor(ref mut wtr) => wtr.flush(), - WriterInnerLock::Ansi(ref mut wtr) => wtr.flush(), - #[cfg(windows)] - WriterInnerLock::Windows { ref mut wtr, .. } => wtr.flush(), - } - } -} - -impl<'a, W: io::Write> WriteColor for WriterInnerLock<'a, W> { - fn supports_color(&self) -> bool { - match *self { - WriterInnerLock::Unreachable(_) => unreachable!(), - WriterInnerLock::NoColor(_) => false, - WriterInnerLock::Ansi(_) => true, - #[cfg(windows)] - WriterInnerLock::Windows { .. } => true, - } - } - - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - match *self { - WriterInnerLock::Unreachable(_) => unreachable!(), - WriterInnerLock::NoColor(ref mut wtr) => wtr.set_color(spec), - WriterInnerLock::Ansi(ref mut wtr) => wtr.set_color(spec), - #[cfg(windows)] - WriterInnerLock::Windows { ref mut wtr, ref mut console } => { - wtr.flush()?; - spec.write_console(console) - } - } - } - - fn reset(&mut self) -> io::Result<()> { - match *self { - WriterInnerLock::Unreachable(_) => unreachable!(), - WriterInnerLock::NoColor(ref mut wtr) => wtr.reset(), - WriterInnerLock::Ansi(ref mut wtr) => wtr.reset(), - #[cfg(windows)] - WriterInnerLock::Windows { ref mut wtr, ref mut console } => { - wtr.flush()?; - console.reset()?; - Ok(()) - } - } - } - - fn is_synchronous(&self) -> bool { - match *self { - WriterInnerLock::Unreachable(_) => unreachable!(), - WriterInnerLock::NoColor(_) => false, - WriterInnerLock::Ansi(_) => false, - #[cfg(windows)] - WriterInnerLock::Windows {..} => true, - } - } -} - -/// Writes colored buffers to stdout or stderr. -/// -/// Writable buffers can be obtained by calling `buffer` on a `BufferWriter`. -/// -/// This writer works with terminals that support ANSI escape sequences or -/// with a Windows console. -/// -/// It is intended for a `BufferWriter` to be put in an `Arc` and written to -/// from multiple threads simultaneously. -pub struct BufferWriter { - stream: LossyStandardStream<IoStandardStream>, - printed: AtomicBool, - separator: Option<Vec<u8>>, - color_choice: ColorChoice, - #[cfg(windows)] - console: Option<Mutex<wincolor::Console>>, -} - -impl BufferWriter { - /// Create a new `BufferWriter` that writes to a standard stream with the - /// given color preferences. - /// |