diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.cargo-ok b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.cargo-ok new file mode 100644 index 0000000000..b5754e2037 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.cargo-ok @@ -0,0 +1 @@ +ok \ No newline at end of file diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.cargo_vcs_info.json b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.cargo_vcs_info.json new file mode 100644 index 0000000000..b03f293bb0 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.cargo_vcs_info.json @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "a250e4650a4cc5a4d418acab57d3cf44d522b2ec" + } +} diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.gitignore b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.gitignore new file mode 100644 index 0000000000..2f2825f4e7 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/.gitignore @@ -0,0 +1,5 @@ +.*.swp +tags +target +/Cargo.lock +/wincolor/Cargo.lock diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/COPYING b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/COPYING new file mode 100644 index 0000000000..bb9c20a094 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/COPYING @@ -0,0 +1,3 @@ +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/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/Cargo.toml b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/Cargo.toml new file mode 100644 index 0000000000..812cab133b --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/Cargo.toml @@ -0,0 +1,30 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "termcolor" +version = "1.0.4" +authors = ["Andrew Gallant "] +exclude = ["/.travis.yml", "/appveyor.yml", "/ci/**"] +description = "A simple cross platform library for writing colored text to a terminal.\n" +homepage = "https://github.com/BurntSushi/termcolor" +documentation = "https://docs.rs/termcolor" +readme = "README.md" +keywords = ["windows", "win", "color", "ansi", "console"] +license = "Unlicense OR MIT" +repository = "https://github.com/BurntSushi/termcolor" + +[lib] +name = "termcolor" +bench = false +[target."cfg(windows)".dependencies.wincolor] +version = "1" diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/Cargo.toml.orig b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/Cargo.toml.orig new file mode 100644 index 0000000000..466845be6b --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/Cargo.toml.orig @@ -0,0 +1,21 @@ +[package] +name = "termcolor" +version = "1.0.4" #:version +authors = ["Andrew Gallant "] +description = """ +A simple cross platform library for writing colored text to a terminal. +""" +documentation = "https://docs.rs/termcolor" +homepage = "https://github.com/BurntSushi/termcolor" +repository = "https://github.com/BurntSushi/termcolor" +readme = "README.md" +keywords = ["windows", "win", "color", "ansi", "console"] +license = "Unlicense OR MIT" +exclude = ["/.travis.yml", "/appveyor.yml", "/ci/**"] + +[lib] +name = "termcolor" +bench = false + +[target.'cfg(windows)'.dependencies] +wincolor = { version = "1", path = "wincolor" } diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/LICENSE-MIT b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/LICENSE-MIT new file mode 100644 index 0000000000..3b0a5dc09c --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/LICENSE-MIT @@ -0,0 +1,21 @@ +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/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/README.md b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/README.md new file mode 100644 index 0000000000..faf3edb2da --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/README.md @@ -0,0 +1,86 @@ +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/termcolor.png)](https://travis-ci.org/BurntSushi/termcolor) +[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/termcolor?svg=true)](https://ci.appveyor.com/project/BurntSushi/termcolor) +[![](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 = "1" +``` + +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)?; +``` diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/UNLICENSE b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/UNLICENSE new file mode 100644 index 0000000000..68a49daad8 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/UNLICENSE @@ -0,0 +1,24 @@ +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 diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/src/lib.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/src/lib.rs new file mode 100644 index 0000000000..1e9cef0d1f --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/termcolor-1.0.4/src/lib.rs @@ -0,0 +1,1895 @@ +/*! +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 WriteColor for Box { + 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), + StderrBuffered(io::BufWriter), +} + +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 { + #[inline(always)] + fn write(&mut self, b: &[u8]) -> io::Result { + 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), + } + } + + #[inline(always)] + 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> { + #[inline(always)] + fn write(&mut self, b: &[u8]) -> io::Result { + match *self { + IoStandardStreamLock::StdoutLock(ref mut s) => s.write(b), + IoStandardStreamLock::StderrLock(ref mut s) => s.write(b), + } + } + + #[inline(always)] + 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>, +} + +/// `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>>, +} + +/// Like `StandardStream`, but does buffered writing. +pub struct BufferedStandardStream { + wtr: LossyStandardStream>, +} + +/// WriterInner is a (limited) generic representation of a writer. It is +/// limited because W should only ever be stdout/stderr on Windows. +enum WriterInner { + NoColor(NoColor), + Ansi(Ansi), + #[cfg(windows)] + Windows { wtr: W, console: Mutex }, +} + +/// 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), + Ansi(Ansi), + /// 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 { + /// Create a new inner writer for a standard stream with the given color + /// preferences. + #[cfg(not(windows))] + fn create( + sty: StandardStreamType, + choice: ColorChoice, + ) -> WriterInner { + 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 { + 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 { + #[inline] + fn write(&mut self, b: &[u8]) -> io::Result { self.wtr.write(b) } + + #[inline] + fn flush(&mut self) -> io::Result<()> { self.wtr.flush() } +} + +impl WriteColor for StandardStream { + #[inline] + fn supports_color(&self) -> bool { self.wtr.supports_color() } + + #[inline] + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + self.wtr.set_color(spec) + } + + #[inline] + fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } + + #[inline] + fn is_synchronous(&self) -> bool { self.wtr.is_synchronous() } +} + +impl<'a> io::Write for StandardStreamLock<'a> { + #[inline] + fn write(&mut self, b: &[u8]) -> io::Result { self.wtr.write(b) } + + #[inline] + fn flush(&mut self) -> io::Result<()> { self.wtr.flush() } +} + +impl<'a> WriteColor for StandardStreamLock<'a> { + #[inline] + fn supports_color(&self) -> bool { self.wtr.supports_color() } + + #[inline] + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + self.wtr.set_color(spec) + } + + #[inline] + fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } + + #[inline] + fn is_synchronous(&self) -> bool { self.wtr.is_synchronous() } +} + +impl io::Write for BufferedStandardStream { + #[inline] + fn write(&mut self, b: &[u8]) -> io::Result { self.wtr.write(b) } + + #[inline] + fn flush(&mut self) -> io::Result<()> { self.wtr.flush() } +} + +impl WriteColor for BufferedStandardStream { + #[inline] + fn supports_color(&self) -> bool { self.wtr.supports_color() } + + #[inline] + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + if self.is_synchronous() { + self.wtr.flush()?; + } + self.wtr.set_color(spec) + } + + #[inline] + fn reset(&mut self) -> io::Result<()> { self.wtr.reset() } + + #[inline] + fn is_synchronous(&self) -> bool { self.wtr.is_synchronous() } +} + +impl io::Write for WriterInner { + #[inline(always)] + fn write(&mut self, buf: &[u8]) -> io::Result { + 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), + } + } + + #[inline(always)] + 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 WriteColor for WriterInner { + 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 { + 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, + printed: AtomicBool, + separator: Option>, + color_choice: ColorChoice, + #[cfg(windows)] + console: Option>, +} + +impl BufferWriter { + /// Create a new `BufferWriter` that writes to a standard stream with the + /// given color preferences. + /// + /// The specific color/style settings can be configured when writing to + /// the buffers themselves. + #[cfg(not(windows))] + fn create(sty: StandardStreamType, choice: ColorChoice) -> BufferWriter { + BufferWriter { + stream: LossyStandardStream::new(IoStandardStream::new(sty)), + printed: AtomicBool::new(false), + separator: None, + color_choice: choice, + } + } + + /// Create a new `BufferWriter` that writes to 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. + /// + /// The specific color/style settings can be configured when writing to + /// the buffers themselves. + #[cfg(windows)] + fn create(sty: StandardStreamType, choice: ColorChoice) -> BufferWriter { + 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(), + }.ok(); + let is_console_virtual = con.as_mut().map(|con| { + con.set_virtual_terminal_processing(true).is_ok() + }).unwrap_or(false); + // If we can enable ANSI on Windows, then we don't need the console + // anymore. + if is_console_virtual { + con = None; + } + let stream = LossyStandardStream::new(IoStandardStream::new(sty)); + BufferWriter { + stream: stream, + printed: AtomicBool::new(false), + separator: None, + color_choice: choice, + console: con.map(Mutex::new), + } + } + + /// Create a new `BufferWriter` that writes to stdout with the given + /// color preferences. + /// + /// 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 to + /// the buffers themselves. + pub fn stdout(choice: ColorChoice) -> BufferWriter { + BufferWriter::create(StandardStreamType::Stdout, choice) + } + + /// Create a new `BufferWriter` that writes to stderr with the given + /// color preferences. + /// + /// 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 to + /// the buffers themselves. + pub fn stderr(choice: ColorChoice) -> BufferWriter { + BufferWriter::create(StandardStreamType::Stderr, choice) + } + + /// If set, the separator given is printed between buffers. By default, no + /// separator is printed. + /// + /// The default value is `None`. + pub fn separator(&mut self, sep: Option>) { + self.separator = sep; + } + + /// Creates a new `Buffer` with the current color preferences. + /// + /// A `Buffer` satisfies both `io::Write` and `WriteColor`. A `Buffer` can + /// be printed using the `print` method. + #[cfg(not(windows))] + pub fn buffer(&self) -> Buffer { + Buffer::new(self.color_choice) + } + + /// Creates a new `Buffer` with the current color preferences. + /// + /// A `Buffer` satisfies both `io::Write` and `WriteColor`. A `Buffer` can + /// be printed using the `print` method. + #[cfg(windows)] + pub fn buffer(&self) -> Buffer { + Buffer::new(self.color_choice, self.console.is_some()) + } + + /// Prints the contents of the given buffer. + /// + /// It is safe to call this from multiple threads simultaneously. In + /// particular, all buffers are written atomically. No interleaving will + /// occur. + pub fn print(&self, buf: &Buffer) -> io::Result<()> { + if buf.is_empty() { + return Ok(()); + } + let mut stream = self.stream.wrap(self.stream.get_ref().lock()); + if let Some(ref sep) = self.separator { + if self.printed.load(Ordering::SeqCst) { + stream.write_all(sep)?; + stream.write_all(b"\n")?; + } + } + match buf.0 { + BufferInner::NoColor(ref b) => stream.write_all(&b.0)?, + BufferInner::Ansi(ref b) => stream.write_all(&b.0)?, + #[cfg(windows)] + BufferInner::Windows(ref b) => { + // We guarantee by construction that we have a console here. + // Namely, a BufferWriter is the only way to produce a Buffer. + let console_mutex = self.console.as_ref() + .expect("got Windows buffer but have no Console"); + let mut console = console_mutex.lock().unwrap(); + b.print(&mut *console, &mut stream)?; + } + } + self.printed.store(true, Ordering::SeqCst); + Ok(()) + } +} + +/// Write colored text to memory. +/// +/// `Buffer` is a platform independent abstraction for printing colored text to +/// an in memory buffer. When the buffer is printed using a `BufferWriter`, the +/// color information will be applied to the output device (a tty on Unix and a +/// console on Windows). +/// +/// A `Buffer` is typically created by calling the `BufferWriter.buffer` +/// 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). +pub struct Buffer(BufferInner); + +/// BufferInner is an enumeration of different buffer types. +enum BufferInner { + /// No coloring information should be applied. This ignores all coloring + /// directives. + NoColor(NoColor>), + /// Apply coloring using ANSI escape sequences embedded into the buffer. + Ansi(Ansi>), + /// Apply coloring using the Windows console APIs. This buffer saves + /// color information in memory and only interacts with the console when + /// the buffer is printed. + #[cfg(windows)] + Windows(WindowsBuffer), +} + +impl Buffer { + /// Create a new buffer with the given color settings. + #[cfg(not(windows))] + fn new(choice: ColorChoice) -> Buffer { + if choice.should_attempt_color() { + Buffer::ansi() + } else { + Buffer::no_color() + } + } + + /// Create a new buffer with the given color settings. + /// + /// On Windows, one can elect to create a buffer capable of being written + /// to a console. Only enable it if a console is available. + /// + /// If coloring is desired and `console` is false, then ANSI escape + /// sequences are used instead. + #[cfg(windows)] + fn new(choice: ColorChoice, console: bool) -> Buffer { + if choice.should_attempt_color() { + if !console || choice.should_ansi() { + Buffer::ansi() + } else { + Buffer::console() + } + } else { + Buffer::no_color() + } + } + + /// Create a buffer that drops all color information. + pub fn no_color() -> Buffer { + Buffer(BufferInner::NoColor(NoColor(vec![]))) + } + + /// Create a buffer that uses ANSI escape sequences. + pub fn ansi() -> Buffer { + Buffer(BufferInner::Ansi(Ansi(vec![]))) + } + + /// Create a buffer that can be written to a Windows console. + #[cfg(windows)] + pub fn console() -> Buffer { + Buffer(BufferInner::Windows(WindowsBuffer::new())) + } + + /// Returns true if and only if this buffer is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns the length of this buffer in bytes. + pub fn len(&self) -> usize { + match self.0 { + BufferInner::NoColor(ref b) => b.0.len(), + BufferInner::Ansi(ref b) => b.0.len(), + #[cfg(windows)] + BufferInner::Windows(ref b) => b.buf.len(), + } + } + + /// Clears this buffer. + pub fn clear(&mut self) { + match self.0 { + BufferInner::NoColor(ref mut b) => b.0.clear(), + BufferInner::Ansi(ref mut b) => b.0.clear(), + #[cfg(windows)] + BufferInner::Windows(ref mut b) => b.clear(), + } + } + + /// Consume this buffer and return the underlying raw data. + /// + /// On Windows, this unrecoverably drops all color information associated + /// with the buffer. + pub fn into_inner(self) -> Vec { + match self.0 { + BufferInner::NoColor(b) => b.0, + BufferInner::Ansi(b) => b.0, + #[cfg(windows)] + BufferInner::Windows(b) => b.buf, + } + } + + /// Return the underlying data of the buffer. + pub fn as_slice(&self) -> &[u8] { + match self.0 { + BufferInner::NoColor(ref b) => &b.0, + BufferInner::Ansi(ref b) => &b.0, + #[cfg(windows)] + BufferInner::Windows(ref b) => &b.buf, + } + } + + /// Return the underlying data of the buffer as a mutable slice. + pub fn as_mut_slice(&mut self) -> &mut [u8] { + match self.0 { + BufferInner::NoColor(ref mut b) => &mut b.0, + BufferInner::Ansi(ref mut b) => &mut b.0, + #[cfg(windows)] + BufferInner::Windows(ref mut b) => &mut b.buf, + } + } +} + +impl io::Write for Buffer { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + match self.0 { + BufferInner::NoColor(ref mut w) => w.write(buf), + BufferInner::Ansi(ref mut w) => w.write(buf), + #[cfg(windows)] + BufferInner::Windows(ref mut w) => w.write(buf), + } + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + match self.0 { + BufferInner::NoColor(ref mut w) => w.flush(), + BufferInner::Ansi(ref mut w) => w.flush(), + #[cfg(windows)] + BufferInner::Windows(ref mut w) => w.flush(), + } + } +} + +impl WriteColor for Buffer { + #[inline] + fn supports_color(&self) -> bool { + match self.0 { + BufferInner::NoColor(_) => false, + BufferInner::Ansi(_) => true, + #[cfg(windows)] + BufferInner::Windows(_) => true, + } + } + + #[inline] + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + match self.0 { + BufferInner::NoColor(ref mut w) => w.set_color(spec), + BufferInner::Ansi(ref mut w) => w.set_color(spec), + #[cfg(windows)] + BufferInner::Windows(ref mut w) => w.set_color(spec), + } + } + + #[inline] + fn reset(&mut self) -> io::Result<()> { + match self.0 { + BufferInner::NoColor(ref mut w) => w.reset(), + BufferInner::Ansi(ref mut w) => w.reset(), + #[cfg(windows)] + BufferInner::Windows(ref mut w) => w.reset(), + } + } + + #[inline] + fn is_synchronous(&self) -> bool { + false + } +} + +/// Satisfies `WriteColor` but ignores all color options. +pub struct NoColor(W); + +impl NoColor { + /// Create a new writer that satisfies `WriteColor` but drops all color + /// information. + pub fn new(wtr: W) -> NoColor { NoColor(wtr) } + + /// Consume this `NoColor` value and return the inner writer. + pub fn into_inner(self) -> W { self.0 } + + /// Return a reference to the inner writer. + pub fn get_ref(&self) -> &W { &self.0 } + + /// Return a mutable reference to the inner writer. + pub fn get_mut(&mut self) -> &mut W { &mut self.0 } +} + +impl io::Write for NoColor { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } +} + +impl WriteColor for NoColor { + #[inline] + fn supports_color(&self) -> bool { false } + + #[inline] + fn set_color(&mut self, _: &ColorSpec) -> io::Result<()> { Ok(()) } + + #[inline] + fn reset(&mut self) -> io::Result<()> { Ok(()) } + + #[inline] + fn is_synchronous(&self) -> bool { false } +} + +/// Satisfies `WriteColor` using standard ANSI escape sequences. +pub struct Ansi(W); + +impl Ansi { + /// Create a new writer that satisfies `WriteColor` using standard ANSI + /// escape sequences. + pub fn new(wtr: W) -> Ansi { Ansi(wtr) } + + /// Consume this `Ansi` value and return the inner writer. + pub fn into_inner(self) -> W { self.0 } + + /// Return a reference to the inner writer. + pub fn get_ref(&self) -> &W { &self.0 } + + /// Return a mutable reference to the inner writer. + pub fn get_mut(&mut self) -> &mut W { &mut self.0 } +} + +impl io::Write for Ansi { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.write(buf) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + self.0.flush() + } +} + +impl WriteColor for Ansi { + #[inline] + fn supports_color(&self) -> bool { true } + + #[inline] + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + self.reset()?; + if spec.bold { + self.write_str("\x1B[1m")?; + } + if spec.underline { + self.write_str("\x1B[4m")?; + } + if let Some(ref c) = spec.fg_color { + self.write_color(true, c, spec.intense)?; + } + if let Some(ref c) = spec.bg_color { + self.write_color(false, c, spec.intense)?; + } + Ok(()) + } + + #[inline] + fn reset(&mut self) -> io::Result<()> { + self.write_str("\x1B[0m") + } + + #[inline] + fn is_synchronous(&self) -> bool { false } +} + +impl Ansi { + fn write_str(&mut self, s: &str) -> io::Result<()> { + self.write_all(s.as_bytes()) + } + + fn write_color( + &mut self, + fg: bool, + c: &Color, + intense: bool, + ) -> io::Result<()> { + macro_rules! write_intense { + ($clr:expr) => { + if fg { + self.write_str(concat!("\x1B[38;5;", $clr, "m")) + } else { + self.write_str(concat!("\x1B[48;5;", $clr, "m")) + } + } + } + macro_rules! write_normal { + ($clr:expr) => { + if fg { + self.write_str(concat!("\x1B[3", $clr, "m")) + } else { + self.write_str(concat!("\x1B[4", $clr, "m")) + } + } + } + macro_rules! write_var_ansi_code { + ($pre:expr, $($code:expr),+) => {{ + // The loop generates at worst a literal of the form + // '255,255,255m' which is 12-bytes. + // The largest `pre` expression we currently use is 7 bytes. + // This gives us the maximum of 19-bytes for our work buffer. + let pre_len = $pre.len(); + assert!(pre_len <= 7); + let mut fmt = [0u8; 19]; + fmt[..pre_len].copy_from_slice($pre); + let mut i = pre_len - 1; + $( + let c1: u8 = ($code / 100) % 10; + let c2: u8 = ($code / 10) % 10; + let c3: u8 = $code % 10; + let mut printed = false; + + if c1 != 0 { + printed = true; + i += 1; + fmt[i] = b'0' + c1; + } + if c2 != 0 || printed { + i += 1; + fmt[i] = b'0' + c2; + } + // If we received a zero value we must still print a value. + i += 1; + fmt[i] = b'0' + c3; + i += 1; + fmt[i] = b';'; + )+ + + fmt[i] = b'm'; + self.write_all(&fmt[0..i+1]) + }} + } + macro_rules! write_custom { + ($ansi256:expr) => { + if fg { + write_var_ansi_code!(b"\x1B[38;5;", $ansi256) + } else { + write_var_ansi_code!(b"\x1B[48;5;", $ansi256) + } + }; + + ($r:expr, $g:expr, $b:expr) => {{ + if fg { + write_var_ansi_code!(b"\x1B[38;2;", $r, $g, $b) + } else { + write_var_ansi_code!(b"\x1B[48;2;", $r, $g, $b) + } + }}; + } + if intense { + match *c { + Color::Black => write_intense!("8"), + Color::Blue => write_intense!("12"), + Color::Green => write_intense!("10"), + Color::Red => write_intense!("9"), + Color::Cyan => write_intense!("14"), + Color::Magenta => write_intense!("13"), + Color::Yellow => write_intense!("11"), + Color::White => write_intense!("15"), + Color::Ansi256(c) => write_custom!(c), + Color::Rgb(r, g, b) => write_custom!(r, g, b), + Color::__Nonexhaustive => unreachable!(), + } + } else { + match *c { + Color::Black => write_normal!("0"), + Color::Blue => write_normal!("4"), + Color::Green => write_normal!("2"), + Color::Red => write_normal!("1"), + Color::Cyan => write_normal!("6"), + Color::Magenta => write_normal!("5"), + Color::Yellow => write_normal!("3"), + Color::White => write_normal!("7"), + Color::Ansi256(c) => write_custom!(c), + Color::Rgb(r, g, b) => write_custom!(r, g, b), + Color::__Nonexhaustive => unreachable!(), + } + } + } +} + +/// An in-memory buffer that provides Windows console coloring. +/// +/// This doesn't actually communicate with the Windows console. Instead, it +/// acts like a normal buffer but also saves the color information associated +/// with positions in the buffer. It is only when the buffer is written to the +/// console that coloring is actually applied. +/// +/// This is roughly isomorphic to the ANSI based approach (i.e., +/// `Ansi>`), except with ANSI, the color information is embedded +/// directly into the buffer. +/// +/// Note that there is no way to write something generic like +/// `WindowsConsole` since coloring on Windows is tied +/// specifically to the console APIs, and therefore can't work on arbitrary +/// writers. +#[cfg(windows)] +#[derive(Clone, Debug)] +struct WindowsBuffer { + /// The actual content that should be printed. + buf: Vec, + /// A sequence of position oriented color specifications. Namely, each + /// element is a position and a color spec, where the color spec should + /// be applied at the position inside of `buf`. + /// + /// A missing color spec implies the underlying console should be reset. + colors: Vec<(usize, Option)>, +} + +#[cfg(windows)] +impl WindowsBuffer { + /// Create a new empty buffer for Windows console coloring. + fn new() -> WindowsBuffer { + WindowsBuffer { + buf: vec![], + colors: vec![], + } + } + + /// Push the given color specification into this buffer. + /// + /// This has the effect of setting the given color information at the + /// current position in the buffer. + fn push(&mut self, spec: Option) { + let pos = self.buf.len(); + self.colors.push((pos, spec)); + } + + /// Print the contents to the given stream handle, and use the console + /// for coloring. + fn print( + &self, + console: &mut wincolor::Console, + stream: &mut LossyStandardStream, + ) -> io::Result<()> { + let mut last = 0; + for &(pos, ref spec) in &self.colors { + stream.write_all(&self.buf[last..pos])?; + stream.flush()?; + last = pos; + match *spec { + None => console.reset()?, + Some(ref spec) => spec.write_console(console)?, + } + } + stream.write_all(&self.buf[last..])?; + stream.flush() + } + + /// Clear the buffer. + fn clear(&mut self) { + self.buf.clear(); + self.colors.clear(); + } +} + +#[cfg(windows)] +impl io::Write for WindowsBuffer { + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.buf.extend_from_slice(buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[cfg(windows)] +impl WriteColor for WindowsBuffer { + #[inline] + fn supports_color(&self) -> bool { true } + + #[inline] + fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { + self.push(Some(spec.clone())); + Ok(()) + } + + #[inline] + fn reset(&mut self) -> io::Result<()> { + self.push(None); + Ok(()) + } + + #[inline] + fn is_synchronous(&self) -> bool { + false + } +} + +/// A color specification. +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct ColorSpec { + fg_color: Option, + bg_color: Option, + bold: bool, + intense: bool, + underline: bool, +} + +impl ColorSpec { + /// Create a new color specification that has no colors or styles. + pub fn new() -> ColorSpec { + ColorSpec::default() + } + + /// Get the foreground color. + pub fn fg(&self) -> Option<&Color> { self.fg_color.as_ref() } + + /// Set the foreground color. + pub fn set_fg(&mut self, color: Option) -> &mut ColorSpec { + self.fg_color = color; + self + } + + /// Get the background color. + pub fn bg(&self) -> Option<&Color> { self.bg_color.as_ref() } + + /// Set the background color. + pub fn set_bg(&mut self, color: Option) -> &mut ColorSpec { + self.bg_color = color; + self + } + + /// Get whether this is bold or not. + /// + /// Note that the bold setting has no effect in a Windows console. + pub fn bold(&self) -> bool { self.bold } + + /// Set whether the text is bolded or not. + /// + /// Note that the bold setting has no effect in a Windows console. + pub fn set_bold(&mut self, yes: bool) -> &mut ColorSpec { + self.bold = yes; + self + } + + /// Get whether this is underline or not. + /// + /// Note that the underline setting has no effect in a Windows console. + pub fn underline(&self) -> bool { self.underline } + + /// Set whether the text is underlined or not. + /// + /// Note that the underline setting has no effect in a Windows console. + pub fn set_underline(&mut self, yes: bool) -> &mut ColorSpec { + self.underline = yes; + self + } + + /// Get whether this is intense or not. + /// + /// On Unix-like systems, this will output the ANSI escape sequence + /// that will print a high-intensity version of the color + /// specified. + /// + /// On Windows systems, this will output the ANSI escape sequence + /// that will print a brighter version of the color specified. + pub fn intense(&self) -> bool { self.intense } + + /// Set whether the text is intense or not. + /// + /// On Unix-like systems, this will output the ANSI escape sequence + /// that will print a high-intensity version of the color + /// specified. + /// + /// On Windows systems, this will output the ANSI escape sequence + /// that will print a brighter version of the color specified. + pub fn set_intense(&mut self, yes: bool) -> &mut ColorSpec { + self.intense = yes; + self + } + + /// Returns true if this color specification has no colors or styles. + pub fn is_none(&self) -> bool { + self.fg_color.is_none() && self.bg_color.is_none() + && !self.bold && !self.underline + } + + /// Clears this color specification so that it has no color/style settings. + pub fn clear(&mut self) { + self.fg_color = None; + self.bg_color = None; + self.bold = false; + self.underline = false; + } + + /// Writes this color spec to the given Windows console. + #[cfg(windows)] + fn write_console( + &self, + console: &mut wincolor::Console, + ) -> io::Result<()> { + use wincolor::Intense; + + let intense = if self.intense { Intense::Yes } else { Intense::No }; + + let fg_color = self.fg_color.as_ref().and_then(|c| c.to_windows()); + if let Some(color) = fg_color { + console.fg(intense, color)?; + } + + let bg_color = self.bg_color.as_ref().and_then(|c| c.to_windows()); + if let Some(color) = bg_color { + console.bg(intense, color)?; + } + Ok(()) + } +} + +/// The set of available colors for the terminal foreground/background. +/// +/// The `Ansi256` and `Rgb` colors will only output the correct codes when +/// paired with the `Ansi` `WriteColor` implementation. +/// +/// The `Ansi256` and `Rgb` color types are not supported when writing colors +/// on Windows using the console. If they are used on Windows, then they are +/// silently ignored and no colors will be emitted. +/// +/// This set may expand over time. +/// +/// This type has a `FromStr` impl that can parse colors from their human +/// readable form. The format is as follows: +/// +/// 1. Any of the explicitly listed colors in English. They are matched +/// case insensitively. +/// 2. A single 8-bit integer, in either decimal or hexadecimal format. +/// 3. A triple of 8-bit integers separated by a comma, where each integer is +/// in decimal or hexadecimal format. +/// +/// Hexadecimal numbers are written with a `0x` prefix. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Color { + Black, + Blue, + Green, + Red, + Cyan, + Magenta, + Yellow, + White, + Ansi256(u8), + Rgb(u8, u8, u8), + #[doc(hidden)] + __Nonexhaustive, +} + +impl Color { + /// Translate this color to a wincolor::Color. + #[cfg(windows)] + fn to_windows(&self) -> Option { + match *self { + Color::Black => Some(wincolor::Color::Black), + Color::Blue => Some(wincolor::Color::Blue), + Color::Green => Some(wincolor::Color::Green), + Color::Red => Some(wincolor::Color::Red), + Color::Cyan => Some(wincolor::Color::Cyan), + Color::Magenta => Some(wincolor::Color::Magenta), + Color::Yellow => Some(wincolor::Color::Yellow), + Color::White => Some(wincolor::Color::White), + Color::Ansi256(_) => None, + Color::Rgb(_, _, _) => None, + Color::__Nonexhaustive => unreachable!(), + } + } + + /// Parses a numeric color string, either ANSI or RGB. + fn from_str_numeric(s: &str) -> Result { + // The "ansi256" format is a single number (decimal or hex) + // corresponding to one of 256 colors. + // + // The "rgb" format is a triple of numbers (decimal or hex) delimited + // by a comma corresponding to one of 256^3 colors. + + fn parse_number(s: &str) -> Option { + use std::u8; + + if s.starts_with("0x") { + u8::from_str_radix(&s[2..], 16).ok() + } else { + u8::from_str_radix(s, 10).ok() + } + } + + let codes: Vec<&str> = s.split(',').collect(); + if codes.len() == 1 { + if let Some(n) = parse_number(&codes[0]) { + Ok(Color::Ansi256(n)) + } else { + if s.chars().all(|c| c.is_digit(16)) { + Err(ParseColorError { + kind: ParseColorErrorKind::InvalidAnsi256, + given: s.to_string(), + }) + } else { + Err(ParseColorError { + kind: ParseColorErrorKind::InvalidName, + given: s.to_string(), + }) + } + } + } else if codes.len() == 3 { + let mut v = vec![]; + for code in codes { + let n = parse_number(code).ok_or_else(|| { + ParseColorError { + kind: ParseColorErrorKind::InvalidRgb, + given: s.to_string(), + } + })?; + v.push(n); + } + Ok(Color::Rgb(v[0], v[1], v[2])) + } else { + Err(if s.contains(",") { + ParseColorError { + kind: ParseColorErrorKind::InvalidRgb, + given: s.to_string(), + } + } else { + ParseColorError { + kind: ParseColorErrorKind::InvalidName, + given: s.to_string(), + } + }) + } + } +} + +/// An error from parsing an invalid color specification. +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct ParseColorError { + kind: ParseColorErrorKind, + given: String, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +enum ParseColorErrorKind { + InvalidName, + InvalidAnsi256, + InvalidRgb, +} + +impl ParseColorError { + /// Return the string that couldn't be parsed as a valid color. + pub fn invalid(&self) -> &str { &self.given } +} + +impl error::Error for ParseColorError { + fn description(&self) -> &str { + use self::ParseColorErrorKind::*; + match self.kind { + InvalidName => "unrecognized color name", + InvalidAnsi256 => "invalid ansi256 color number", + InvalidRgb => "invalid RGB color triple", + } + } +} + +impl fmt::Display for ParseColorError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::ParseColorErrorKind::*; + match self.kind { + InvalidName => { + write!(f, "unrecognized color name '{}'. Choose from: \ + black, blue, green, red, cyan, magenta, yellow, \ + white", + self.given) + } + InvalidAnsi256 => { + write!(f, "unrecognized ansi256 color number, \ + should be '[0-255]' (or a hex number), but is '{}'", + self.given) + } + InvalidRgb => { + write!(f, "unrecognized RGB color triple, \ + should be '[0-255],[0-255],[0-255]' (or a hex \ + triple), but is '{}'", self.given) + } + } + } +} + +impl FromStr for Color { + type Err = ParseColorError; + + fn from_str(s: &str) -> Result { + match &*s.to_lowercase() { + "black" => Ok(Color::Black), + "blue" => Ok(Color::Blue), + "green" => Ok(Color::Green), + "red" => Ok(Color::Red), + "cyan" => Ok(Color::Cyan), + "magenta" => Ok(Color::Magenta), + "yellow" => Ok(Color::Yellow), + "white" => Ok(Color::White), + _ => Color::from_str_numeric(s), + } + } +} + +struct LossyStandardStream { + wtr: W, + #[cfg(windows)] + is_console: bool, +} + +impl LossyStandardStream { + #[cfg(not(windows))] + fn new(wtr: W) -> LossyStandardStream { + LossyStandardStream { wtr: wtr } + } + + #[cfg(windows)] + fn new(wtr: W) -> LossyStandardStream { + let is_console = + wincolor::Console::stdout().is_ok() + || wincolor::Console::stderr().is_ok(); + LossyStandardStream { wtr: wtr, is_console: is_console } + } + + #[cfg(not(windows))] + fn wrap(&self, wtr: Q) -> LossyStandardStream { + LossyStandardStream::new(wtr) + } + + #[cfg(windows)] + fn wrap(&self, wtr: Q) -> LossyStandardStream { + LossyStandardStream { wtr: wtr, is_console: self.is_console } + } + + fn get_ref(&self) -> &W { + &self.wtr + } +} + +impl WriteColor for LossyStandardStream { + 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 LossyStandardStream { + #[cfg(not(windows))] + fn write(&mut self, buf: &[u8]) -> io::Result { + self.wtr.write(buf) + } + + #[cfg(windows)] + fn write(&mut self, buf: &[u8]) -> io::Result { + if self.is_console { + write_lossy_utf8(&mut self.wtr, buf) + } else { + self.wtr.write(buf) + } + } + + fn flush(&mut self) -> io::Result<()> { + self.wtr.flush() + } +} + +#[cfg(windows)] +fn write_lossy_utf8(mut w: W, buf: &[u8]) -> io::Result { + match ::std::str::from_utf8(buf) { + Ok(s) => w.write(s.as_bytes()), + Err(ref e) if e.valid_up_to() == 0 => { + w.write(b"\xEF\xBF\xBD")?; + Ok(1) + } + Err(e) => w.write(&buf[..e.valid_up_to()]), + } +} + +#[cfg(test)] +mod tests { + use super::{ + Ansi, Color, ParseColorError, ParseColorErrorKind, StandardStream, + }; + + fn assert_is_send() {} + + #[test] + fn standard_stream_is_send() { + assert_is_send::(); + } + + #[test] + fn test_simple_parse_ok() { + let color = "green".parse::(); + assert_eq!(color, Ok(Color::Green)); + } + + #[test] + fn test_256_parse_ok() { + let color = "7".parse::(); + assert_eq!(color, Ok(Color::Ansi256(7))); + + let color = "32".parse::(); + assert_eq!(color, Ok(Color::Ansi256(32))); + + let color = "0xFF".parse::(); + assert_eq!(color, Ok(Color::Ansi256(0xFF))); + } + + #[test] + fn test_256_parse_err_out_of_range() { + let color = "256".parse::(); + assert_eq!(color, Err(ParseColorError { + kind: ParseColorErrorKind::InvalidAnsi256, + given: "256".to_string(), + })); + } + + #[test] + fn test_rgb_parse_ok() { + let color = "0,0,0".parse::(); + assert_eq!(color, Ok(Color::Rgb(0, 0, 0))); + + let color = "0,128,255".parse::(); + assert_eq!(color, Ok(Color::Rgb(0, 128, 255))); + + let color = "0x0,0x0,0x0".parse::(); + assert_eq!(color, Ok(Color::Rgb(0, 0, 0))); + + let color = "0x33,0x66,0xFF".parse::(); + assert_eq!(color, Ok(Color::Rgb(0x33, 0x66, 0xFF))); + } + + #[test] + fn test_rgb_parse_err_out_of_range() { + let color = "0,0,256".parse::(); + assert_eq!(color, Err(ParseColorError { + kind: ParseColorErrorKind::InvalidRgb, + given: "0,0,256".to_string(), + })); + } + + #[test] + fn test_rgb_parse_err_bad_format() { + let color = "0,0".parse::(); + assert_eq!(color, Err(ParseColorError { + kind: ParseColorErrorKind::InvalidRgb, + given: "0,0".to_string(), + })); + + let color = "not_a_color".parse::(); + assert_eq!(color, Err(ParseColorError { + kind: ParseColorErrorKind::InvalidName, + given: "not_a_color".to_string(), + })); + } + + #[test] + fn test_var_ansi_write_rgb() { + let mut buf = Ansi::new(vec![]); + let _ = buf.write_color(true, &Color::Rgb(254, 253, 255), false); + assert_eq!(buf.0, b"\x1B[38;2;254;253;255m"); + } + + #[test] + fn test_var_ansi_write_256() { + let mut buf = Ansi::new(vec![]); + let _ = buf.write_color(false, &Color::Ansi256(7), false); + assert_eq!(buf.0, b"\x1B[48;5;7m"); + + let mut buf = Ansi::new(vec![]); + let _ = buf.write_color(false, &Color::Ansi256(208), false); + assert_eq!(buf.0, b"\x1B[48;5;208m"); + } +} diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.cargo-ok b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.cargo-ok new file mode 100644 index 0000000000..b5754e2037 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.cargo-ok @@ -0,0 +1 @@ +ok \ No newline at end of file diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.cargo_vcs_info.json b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.cargo_vcs_info.json new file mode 100644 index 0000000000..0bae457a79 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.cargo_vcs_info.json @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "8c407c0455a0bb77b4a4bee9e5705bad9947eb87" + } +} diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.gitignore b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.gitignore new file mode 100644 index 0000000000..3d69c04179 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.gitignore @@ -0,0 +1,4 @@ +/target +**/*.rs.bk +Cargo.lock +tags diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.travis.yml b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.travis.yml new file mode 100644 index 0000000000..b374a47de0 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/.travis.yml @@ -0,0 +1,8 @@ +dist: trusty +language: rust +rust: + - 1.28.0 +script: ci/script.sh +branches: + only: + - master diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/COPYING b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/COPYING new file mode 100644 index 0000000000..bb9c20a094 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/COPYING @@ -0,0 +1,3 @@ +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/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/Cargo.toml b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/Cargo.toml new file mode 100644 index 0000000000..d6a7b7494b --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/Cargo.toml @@ -0,0 +1,27 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "winapi-util" +version = "0.1.2" +authors = ["Andrew Gallant "] +description = "A dumping ground for high level safe wrappers over winapi." +homepage = "https://github.com/BurntSushi/winapi-util" +documentation = "https://docs.rs/winapi-util" +readme = "README.md" +keywords = ["windows", "winapi", "util", "win"] +categories = ["os::windows-apis", "external-ffi-bindings"] +license = "Unlicense/MIT" +repository = "https://github.com/BurntSushi/winapi-util" +[target."cfg(windows)".dependencies.winapi] +version = "0.3" +features = ["std", "consoleapi", "errhandlingapi", "fileapi", "minwindef", "processenv", "winbase", "wincon", "winerror", "winnt"] diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/Cargo.toml.orig b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/Cargo.toml.orig new file mode 100644 index 0000000000..090a4b612c --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/Cargo.toml.orig @@ -0,0 +1,27 @@ +[package] +name = "winapi-util" +version = "0.1.2" #:version +authors = ["Andrew Gallant "] +description = "A dumping ground for high level safe wrappers over winapi." +documentation = "https://docs.rs/winapi-util" +homepage = "https://github.com/BurntSushi/winapi-util" +repository = "https://github.com/BurntSushi/winapi-util" +readme = "README.md" +keywords = ["windows", "winapi", "util", "win"] +license = "Unlicense/MIT" +categories = ["os::windows-apis", "external-ffi-bindings"] + +[target.'cfg(windows)'.dependencies.winapi] +version = "0.3" +features = [ + "std", + "consoleapi", + "errhandlingapi", + "fileapi", + "minwindef", + "processenv", + "winbase", + "wincon", + "winerror", + "winnt", +] diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/LICENSE-MIT b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/LICENSE-MIT new file mode 100644 index 0000000000..3303149e52 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/LICENSE-MIT @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 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/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/README.md b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/README.md new file mode 100644 index 0000000000..145eede1a0 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/README.md @@ -0,0 +1,51 @@ +winapi-util +=========== +This crate provides a smattering of safe wrappers around various parts of the +[winapi](https://crates.io/crates/winapi) crate. + +[![Linux build status](https://api.travis-ci.org/BurntSushi/winapi-util.png)](https://travis-ci.org/BurntSushi/winapi-util) +[![Windows build status](https://ci.appveyor.com/api/projects/status/github/BurntSushi/winapi-util?svg=true)](https://ci.appveyor.com/project/BurntSushi/winapi-util) +[![](http://meritbadge.herokuapp.com/winapi-util)](https://crates.io/crates/winapi-util) + +Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). + + +### Documentation + +https://docs.rs/winapi-util + + +### Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +winapi-util = "0.1" +``` + +and this to your crate root: + +```rust +extern crate winapi_util; +``` + + +### Notes + +This crate was born out of frustration with having to write lots of little +ffi utility bindings in a variety of crates in order to get Windows support. +Eventually, I started needing to copy & paste a lot of those utility routines. +Since they are utility routines, they often don't make sense to expose directly +in the crate in which they are defined. Instead of continuing this process, +I decided to make a crate instead. + +Normally, I'm not a huge fan of "utility" crates like this that don't have a +well defined scope, but this is primarily a practical endeavor to make it +easier to isolate Windows specific ffi code. + +While I don't have a long term vision for this crate, I will welcome additional +PRs that add more high level routines/types on an as-needed basis. + +**WARNING:** I am not a Windows developer, so extra review to make sure I've +got things right is most appreciated. diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/UNLICENSE b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/UNLICENSE new file mode 100644 index 0000000000..68a49daad8 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/UNLICENSE @@ -0,0 +1,24 @@ +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 diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/appveyor.yml b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/appveyor.yml new file mode 100644 index 0000000000..9fdcaa8f16 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/appveyor.yml @@ -0,0 +1,26 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-gnu + BITS: 64 + MSYS2: 1 + - TARGET: x86_64-pc-windows-msvc + BITS: 64 + - TARGET: i686-pc-windows-gnu + BITS: 32 + MSYS2: 1 + - TARGET: i686-pc-windows-msvc + BITS: 32 +install: + - curl -sSf -o rustup-init.exe https://win.rustup.rs/ + - rustup-init.exe -y --default-host %TARGET% + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - if defined MSYS2 set PATH=C:\msys64\mingw%BITS%\bin;%PATH% + - rustc -V + - cargo -V +build: false +test_script: + - cargo build --verbose --all + - cargo test --verbose --all +branches: + only: + - master diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/ci/script.sh b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/ci/script.sh new file mode 100644 index 0000000000..90243df3db --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/ci/script.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -ex + +cargo build --verbose --all +cargo doc --verbose --all +cargo test --verbose --all diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/console.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/console.rs new file mode 100644 index 0000000000..1f7dad8bd5 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/console.rs @@ -0,0 +1,121 @@ +use std::io; +use std::mem; + +use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode}; +use winapi::um::wincon::{ + CONSOLE_SCREEN_BUFFER_INFO, + GetConsoleScreenBufferInfo, SetConsoleTextAttribute, +}; + +use AsHandleRef; + +/// Query the given handle for information about the console's screen buffer. +/// +/// The given handle should represent a console. Otherwise, an error is +/// returned. +/// +/// This corresponds to calling [`GetConsoleScreenBufferInfo`]. +/// +/// [`GetConsoleScreenBufferInfo`]: https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo +pub fn screen_buffer_info( + h: H, +) -> io::Result { + unsafe { + let mut info: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed(); + let rc = GetConsoleScreenBufferInfo(h.as_raw(), &mut info); + if rc == 0 { + return Err(io::Error::last_os_error()); + } + Ok(ScreenBufferInfo(info)) + } +} + +/// Set the text attributes of the console represented by the given handle. +/// +/// This corresponds to calling [`SetConsoleTextAttribute`]. +/// +/// [`SetConsoleTextAttribute`]: https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute +pub fn set_text_attributes( + h: H, + attributes: u16, +) -> io::Result<()> { + if unsafe { SetConsoleTextAttribute(h.as_raw(), attributes) } == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} + +/// Query the mode of the console represented by the given handle. +/// +/// This corresponds to calling [`GetConsoleMode`], which describes the return +/// value. +/// +/// [`GetConsoleMode`]: https://docs.microsoft.com/en-us/windows/console/getconsolemode +pub fn mode(h: H) -> io::Result { + let mut mode = 0; + if unsafe { GetConsoleMode(h.as_raw(), &mut mode) } == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(mode) + } +} + +/// Set the mode of the console represented by the given handle. +/// +/// This corresponds to calling [`SetConsoleMode`], which describes the format +/// of the mode parameter. +/// +/// [`SetConsoleMode`]: https://docs.microsoft.com/en-us/windows/console/setconsolemode +pub fn set_mode(h: H, mode: u32) -> io::Result<()> { + if unsafe { SetConsoleMode(h.as_raw(), mode) } == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} + +/// Represents console screen buffer information such as size, cursor position +/// and styling attributes. +/// +/// This wraps a [`CONSOLE_SCREEN_BUFFER_INFO`]. +/// +/// [`CONSOLE_SCREEN_BUFFER_INFO`]: https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str +#[derive(Clone)] +pub struct ScreenBufferInfo(CONSOLE_SCREEN_BUFFER_INFO); + +impl ScreenBufferInfo { + /// Returns the size of the console screen buffer, in character columns and + /// rows. + /// + /// This corresponds to `dwSize`. + pub fn size(&self) -> (i16, i16) { + (self.0.dwSize.X, self.0.dwSize.Y) + } + + /// Returns the position of the cursor in terms of column and row + /// coordinates of the console screen buffer. + /// + /// This corresponds to `dwCursorPosition`. + pub fn cursor_position(&self) -> (i16, i16) { + (self.0.dwCursorPosition.X, self.0.dwCursorPosition.Y) + } + + /// Returns the character attributes associated with this console. + /// + /// This corresponds to `wAttributes`. + /// + /// See [`char info`] for more details. + /// + /// [`char info`]: https://docs.microsoft.com/en-us/windows/console/char-info-str + pub fn attributes(&self) -> u16 { + self.0.wAttributes + } + + /// Returns the maximum size of the console window, in character columns + /// and rows, given the current screen buffer size and font and the screen + /// size. + pub fn max_window_size(&self) -> (i16, i16) { + (self.0.dwMaximumWindowSize.X, self.0.dwMaximumWindowSize.Y) + } +} diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/file.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/file.rs new file mode 100644 index 0000000000..99f7981b54 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/file.rs @@ -0,0 +1,171 @@ +use std::io; +use std::mem; + +use winapi::shared::minwindef::FILETIME; +use winapi::shared::winerror::NO_ERROR; +use winapi::um::errhandlingapi::GetLastError; +use winapi::um::fileapi::{ + BY_HANDLE_FILE_INFORMATION, + GetFileInformationByHandle, GetFileType, +}; +use winapi::um::winnt; + +use AsHandleRef; + +/// Return various pieces of information about a file. +/// +/// This includes information such as a file's size, unique identifier and +/// time related fields. +/// +/// This corresponds to calling [`GetFileInformationByHandle`]. +/// +/// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle +pub fn information( + h: H, +) -> io::Result { + unsafe { + let mut info: BY_HANDLE_FILE_INFORMATION = mem::zeroed(); + let rc = GetFileInformationByHandle(h.as_raw(), &mut info); + if rc == 0 { + return Err(io::Error::last_os_error()); + }; + Ok(Information(info)) + } +} + +/// Returns the file type of the given handle. +/// +/// If there was a problem querying the file type, then an error is returned. +/// +/// This corresponds to calling [`GetFileType`]. +/// +/// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype +pub fn typ(h: H) -> io::Result { + unsafe { + let rc = GetFileType(h.as_raw()); + if rc == 0 && GetLastError() != NO_ERROR { + return Err(io::Error::last_os_error()); + } + Ok(Type(rc)) + } +} + +/// Returns true if and only if the given file attributes contain the +/// `FILE_ATTRIBUTE_HIDDEN` attribute. +pub fn is_hidden(file_attributes: u64) -> bool { + file_attributes & (winnt::FILE_ATTRIBUTE_HIDDEN as u64) > 0 +} + +/// Represents file information such as creation time, file size, etc. +/// +/// This wraps a [`BY_HANDLE_FILE_INFORMATION`]. +/// +/// [`BY_HANDLE_FILE_INFORMATION`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information +#[derive(Clone)] +pub struct Information(BY_HANDLE_FILE_INFORMATION); + +impl Information { + /// Returns file attributes. + /// + /// This corresponds to `dwFileAttributes`. + pub fn file_attributes(&self) -> u64 { + self.0.dwFileAttributes as u64 + } + + /// Returns true if and only if this file information has the + /// `FILE_ATTRIBUTE_HIDDEN` attribute. + pub fn is_hidden(&self) -> bool { + is_hidden(self.file_attributes()) + } + + /// Return the creation time, if one exists. + /// + /// This corresponds to `ftCreationTime`. + pub fn creation_time(&self) -> Option { + filetime_to_u64(self.0.ftCreationTime) + } + + /// Return the last access time, if one exists. + /// + /// This corresponds to `ftLastAccessTime`. + pub fn last_access_time(&self) -> Option { + filetime_to_u64(self.0.ftLastAccessTime) + } + + /// Return the last write time, if one exists. + /// + /// This corresponds to `ftLastWriteTime`. + pub fn last_write_time(&self) -> Option { + filetime_to_u64(self.0.ftLastWriteTime) + } + + /// Return the serial number of the volume that the file is on. + /// + /// This corresponds to `dwVolumeSerialNumber`. + pub fn volume_serial_number(&self) -> u64 { + self.0.dwVolumeSerialNumber as u64 + } + + /// Return the file size, in bytes. + /// + /// This corresponds to `nFileSizeHigh` and `nFileSizeLow`. + pub fn file_size(&self) -> u64 { + ((self.0.nFileSizeHigh as u64) << 32) | (self.0.nFileSizeLow as u64) + } + + /// Return the number of links to this file. + /// + /// This corresponds to `nNumberOfLinks`. + pub fn number_of_links(&self) -> u64 { + self.0.nNumberOfLinks as u64 + } + + /// Return the index of this file. The index of a file is a purpotedly + /// unique identifier for a file within a particular volume. + pub fn file_index(&self) -> u64 { + ((self.0.nFileIndexHigh as u64) << 32) | (self.0.nFileIndexLow as u64) + } +} + +/// Represents a Windows file type. +/// +/// This wraps the result of [`GetFileType`]. +/// +/// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype +#[derive(Clone)] +pub struct Type(u32); + +impl Type { + /// Returns true if this type represents a character file, which is + /// typically an LPT device or a console. + pub fn is_char(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_CHAR + } + + /// Returns true if this type represents a disk file. + pub fn is_disk(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_DISK + } + + /// Returns true if this type represents a sock, named pipe or an + /// anonymous pipe. + pub fn is_pipe(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_PIPE + } + + /// Returns true if this type is not known. + /// + /// Note that this never corresponds to a failure. + pub fn is_unknown(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_UNKNOWN + } +} + +fn filetime_to_u64(t: FILETIME) -> Option { + let v = ((t.dwHighDateTime as u64) << 32) | (t.dwLowDateTime as u64); + if v == 0 { + None + } else { + Some(v) + } +} diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/lib.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/lib.rs new file mode 100644 index 0000000000..a2864e1d04 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/lib.rs @@ -0,0 +1,35 @@ +/*! +This crate provides a smattering of safe routines for parts of winapi. The +primary purpose of this crate is to serve as a dumping ground for various +utility functions that make interactions with winapi safe. This permits the +centralization of `unsafe` when dealing with Windows APIs, and thus makes it +easier to audit. + +A key abstraction in this crate is the combination of the +[`Handle`](struct.Handle.html) +and +[`HandleRef`](struct.HandleRef.html) +types. Both represent a valid Windows handle to an I/O-like object, where +`Handle` is owned (the resource is closed when the handle is dropped) and +`HandleRef` is borrowed (the resource is not closed when the handle is +dropped). Many of the routines in this crate work on handles and accept +anything that can be safely converted into a `HandleRef`. This includes +standard library types such as `File`, `Stdin`, `Stdout` and `Stderr`. + +Note that this crate is completely empty on non-Windows platforms. +*/ + +#[cfg(windows)] +extern crate winapi; + +#[cfg(windows)] +pub use win::*; + +/// Safe routines for dealing with the Windows console. +#[cfg(windows)] +pub mod console; +/// Safe routines for dealing with files and handles on Windows. +#[cfg(windows)] +pub mod file; +#[cfg(windows)] +mod win; diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/win.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/win.rs new file mode 100644 index 0000000000..490534b994 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/winapi-util-0.1.2/src/win.rs @@ -0,0 +1,247 @@ +use std::fs::File; +use std::io; +use std::os::windows::io::{ + RawHandle, + AsRawHandle, FromRawHandle, IntoRawHandle, +}; +use std::path::Path; +use std::process; + +/// A handle represents an owned and valid Windows handle to a file-like +/// object. +/// +/// When an owned handle is dropped, then the underlying raw handle is closed. +/// To get a borrowed handle, use `HandleRef`. +#[derive(Debug)] +pub struct Handle(File); + +impl AsRawHandle for Handle { + fn as_raw_handle(&self) -> RawHandle { + self.0.as_raw_handle() + } +} + +impl FromRawHandle for Handle { + unsafe fn from_raw_handle(handle: RawHandle) -> Handle { + Handle(File::from_raw_handle(handle)) + } +} + +impl IntoRawHandle for Handle { + fn into_raw_handle(self) -> RawHandle { + self.0.into_raw_handle() + } +} + +impl Handle { + /// Create an owned handle to the given file. + /// + /// When the returned handle is dropped, the file is closed. + /// + /// Note that if the given file represents a handle to a directory, then + /// it is generally required that it have been opened with the + /// [`FILE_FLAG_BACKUP_SEMANTICS`] flag in order to use it in various + /// calls such as `information` or `typ`. To have this done automatically + /// for you, use the `from_path_any` constructor. + /// + /// [`FILE_FLAG_BACKUP_SEMANTICS`]: https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-createfilea + pub fn from_file(file: File) -> Handle { + Handle(file) + } + + /// Open a file to the given file path, and return an owned handle to that + /// file. + /// + /// When the returned handle is dropped, the file is closed. + /// + /// If there was a problem opening the file, then the corresponding error + /// is returned. + pub fn from_path>(path: P) -> io::Result { + Ok(Handle::from_file(File::open(path)?)) + } + + /// Like `from_path`, but supports opening directory handles as well. + /// + /// If you use `from_path` on a directory, then subsequent queries using + /// that handle will fail. + pub fn from_path_any>(path: P) -> io::Result { + use std::fs::OpenOptions; + use std::os::windows::fs::OpenOptionsExt; + use winapi::um::winbase::FILE_FLAG_BACKUP_SEMANTICS; + + let file = OpenOptions::new() + .read(true) + .custom_flags(FILE_FLAG_BACKUP_SEMANTICS) + .open(path)?; + Ok(Handle::from_file(file)) + } + + /// Return this handle as a standard `File` reference. + pub fn as_file(&self) -> &File { + &self.0 + } + + /// Return this handle as a standard `File` mutable reference. + pub fn as_file_mut(&mut self) -> &mut File { + &mut self.0 + } +} + +/// Represents a borrowed and valid Windows handle to a file-like object, such +/// as stdin/stdout/stderr or an actual file. +/// +/// When a borrowed handle is dropped, then the underlying raw handle is +/// **not** closed. To get an owned handle, use `Handle`. +#[derive(Debug)] +pub struct HandleRef(HandleRefInner); + +/// The representation of a HandleRef, on which we define a custom Drop impl +/// that avoids closing the underlying raw handle. +#[derive(Debug)] +struct HandleRefInner(Option); + +impl Drop for HandleRefInner { + fn drop(&mut self) { + self.0.take().unwrap().into_raw_handle(); + } +} + +impl AsRawHandle for HandleRef { + fn as_raw_handle(&self) -> RawHandle { + self.as_file().as_raw_handle() + } +} + +impl Clone for HandleRef { + fn clone(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl HandleRef { + /// Create a borrowed handle to stdin. + /// + /// When the returned handle is dropped, stdin is not closed. + pub fn stdin() -> HandleRef { + unsafe { HandleRef::from_raw_handle(io::stdin().as_raw_handle()) } + } + + /// Create a handle to stdout. + /// + /// When the returned handle is dropped, stdout is not closed. + pub fn stdout() -> HandleRef { + unsafe { HandleRef::from_raw_handle(io::stdout().as_raw_handle()) } + } + + /// Create a handle to stderr. + /// + /// When the returned handle is dropped, stderr is not closed. + pub fn stderr() -> HandleRef { + unsafe { HandleRef::from_raw_handle(io::stderr().as_raw_handle()) } + } + + /// Create a borrowed handle to the given file. + /// + /// When the returned handle is dropped, the file is not closed. + pub fn from_file(file: &File) -> HandleRef { + unsafe { HandleRef::from_raw_handle(file.as_raw_handle()) } + } + + /// Create a borrowed handle from the given raw handle. + /// + /// Note that unlike the `FromRawHandle` trait, this constructor does + /// **not** consume ownership of the given handle. That is, when the + /// borrowed handle created by this constructor is dropped, the underlying + /// handle will not be closed. + /// + /// # Safety + /// + /// This is unsafe because there is no guarantee that the given raw handle + /// is a valid handle. The caller must ensure this is true before invoking + /// this constructor. + pub unsafe fn from_raw_handle(handle: RawHandle) -> HandleRef { + HandleRef(HandleRefInner(Some(File::from_raw_handle(handle)))) + } + + /// Return this handle as a standard `File` reference. + pub fn as_file(&self) -> &File { + (self.0).0.as_ref().unwrap() + } + + /// Return this handle as a standard `File` mutable reference. + pub fn as_file_mut(&mut self) -> &mut File { + (self.0).0.as_mut().unwrap() + } +} + +/// Construct borrowed and valid Windows handles from file-like objects. +pub trait AsHandleRef { + /// A borrowed handle that wraps the raw handle of the `Self` object. + fn as_handle_ref(&self) -> HandleRef; + + /// A convenience routine for extracting a `HandleRef` from `Self`, and + /// then extracting a raw handle from the `HandleRef`. + fn as_raw(&self) -> RawHandle { + self.as_handle_ref().as_raw_handle() + } +} + +impl<'a, T: AsHandleRef> AsHandleRef for &'a T { + fn as_handle_ref(&self) -> HandleRef { + (**self).as_handle_ref() + } +} + +impl AsHandleRef for Handle { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl AsHandleRef for HandleRef { + fn as_handle_ref(&self) -> HandleRef { + self.clone() + } +} + +impl AsHandleRef for File { + fn as_handle_ref(&self) -> HandleRef { + HandleRef::from_file(self) + } +} + +impl AsHandleRef for io::Stdin { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl AsHandleRef for io::Stdout { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl AsHandleRef for io::Stderr { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl AsHandleRef for process::ChildStdin { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl AsHandleRef for process::ChildStdout { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} + +impl AsHandleRef for process::ChildStderr { + fn as_handle_ref(&self) -> HandleRef { + unsafe { HandleRef::from_raw_handle(self.as_raw_handle()) } + } +} diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/.cargo-ok b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/.cargo-ok new file mode 100644 index 0000000000..b5754e2037 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/.cargo-ok @@ -0,0 +1 @@ +ok \ No newline at end of file diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/COPYING b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/COPYING new file mode 100644 index 0000000000..bb9c20a094 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/COPYING @@ -0,0 +1,3 @@ +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/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/Cargo.toml b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/Cargo.toml new file mode 100644 index 0000000000..b1ab58fea9 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/Cargo.toml @@ -0,0 +1,33 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g. crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "wincolor" +version = "1.0.1" +authors = ["Andrew Gallant "] +description = "A simple Windows specific API for controlling text color in a Windows console.\n" +homepage = "https://github.com/BurntSushi/termcolor/tree/master/wincolor" +documentation = "https://docs.rs/wincolor" +readme = "README.md" +keywords = ["windows", "win", "color", "ansi", "console"] +license = "Unlicense/MIT" +repository = "https://github.com/BurntSushi/termcolor/tree/master/wincolor" + +[lib] +name = "wincolor" +bench = false +[dependencies.winapi] +version = "0.3" +features = ["minwindef", "wincon"] + +[dependencies.winapi-util] +version = "0.1.1" diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/Cargo.toml.orig b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/Cargo.toml.orig new file mode 100644 index 0000000000..c9449afa3c --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/Cargo.toml.orig @@ -0,0 +1,24 @@ +[package] +name = "wincolor" +version = "1.0.1" #:version +authors = ["Andrew Gallant "] +description = """ +A simple Windows specific API for controlling text color in a Windows console. +""" +documentation = "https://docs.rs/wincolor" +homepage = "https://github.com/BurntSushi/termcolor/tree/master/wincolor" +repository = "https://github.com/BurntSushi/termcolor/tree/master/wincolor" +readme = "README.md" +keywords = ["windows", "win", "color", "ansi", "console"] +license = "Unlicense/MIT" + +[lib] +name = "wincolor" +bench = false + +[dependencies] +winapi-util = "0.1.1" + +[dependencies.winapi] +version = "0.3" +features = ["minwindef", "wincon"] diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/LICENSE-MIT b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/LICENSE-MIT new file mode 100644 index 0000000000..3b0a5dc09c --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/LICENSE-MIT @@ -0,0 +1,21 @@ +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/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/README.md b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/README.md new file mode 100644 index 0000000000..cc780340e1 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/README.md @@ -0,0 +1,44 @@ +wincolor +======== +A simple Windows specific API for controlling text color in a Windows console. +The purpose of this crate is to expose the full inflexibility of the Windows +console without any platform independent abstraction. + +[![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/wincolor.svg)](https://crates.io/crates/wincolor) + +Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). + +### Documentation + +[https://docs.rs/wincolor](https://docs.rs/wincolor) + +### Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +wincolor = "0.1" +``` + +and this to your crate root: + +```rust +extern crate wincolor; +``` + +### Example + +This is a simple example that shows how to write text with a foreground color +of cyan and the intense attribute set: + +```rust +use wincolor::{Console, Color, Intense}; + +let mut con = Console::stdout().unwrap(); +con.fg(Intense::Yes, Color::Cyan).unwrap(); +println!("This text will be intense cyan."); +con.reset().unwrap(); +println!("This text will be normal."); +``` diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/UNLICENSE b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/UNLICENSE new file mode 100644 index 0000000000..68a49daad8 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/UNLICENSE @@ -0,0 +1,24 @@ +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 diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/src/lib.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/src/lib.rs new file mode 100644 index 0000000000..58dbbb6ef1 --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/src/lib.rs @@ -0,0 +1,35 @@ +/*! +This crate provides a safe and simple Windows specific API to control +text attributes in the Windows console. Text attributes are limited to +foreground/background colors, as well as whether to make colors intense or not. + +Note that on non-Windows platforms, this crate is empty but will compile. + +# Example + +```no_run +# #[cfg(windows)] +# { +use wincolor::{Console, Color, Intense}; + +let mut con = Console::stdout().unwrap(); +con.fg(Intense::Yes, Color::Cyan).unwrap(); +println!("This text will be intense cyan."); +con.reset().unwrap(); +println!("This text will be normal."); +# } +``` +*/ + +#![deny(missing_docs)] + +#[cfg(windows)] +extern crate winapi; +#[cfg(windows)] +extern crate winapi_util; + +#[cfg(windows)] +pub use win::*; + +#[cfg(windows)] +mod win; diff --git a/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/src/win.rs b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/src/win.rs new file mode 100644 index 0000000000..2115d1275b --- /dev/null +++ b/rust_crates/registry/src/github.com-1ecc6299db9ec823/wincolor-1.0.1/src/win.rs @@ -0,0 +1,261 @@ +use std::io; + +use winapi::shared::minwindef::{WORD}; +use winapi::um::wincon::{ + self, + FOREGROUND_BLUE as FG_BLUE, + FOREGROUND_GREEN as FG_GREEN, + FOREGROUND_RED as FG_RED, + FOREGROUND_INTENSITY as FG_INTENSITY, +}; +use winapi_util as winutil; + +const FG_CYAN: WORD = FG_BLUE | FG_GREEN; +const FG_MAGENTA: WORD = FG_BLUE | FG_RED; +const FG_YELLOW: WORD = FG_GREEN | FG_RED; +const FG_WHITE: WORD = FG_BLUE | FG_GREEN | FG_RED; + +/// A Windows console. +/// +/// This represents a very limited set of functionality available to a Windows +/// console. In particular, it can only change text attributes such as color +/// and intensity. +/// +/// There is no way to "write" to this console. Simply write to +/// stdout or stderr instead, while interleaving instructions to the console +/// to change text attributes. +/// +/// A common pitfall when using a console is to forget to flush writes to +/// stdout before setting new text attributes. +#[derive(Debug)] +pub struct Console { + kind: HandleKind, + start_attr: TextAttributes, + cur_attr: TextAttributes, +} + +#[derive(Clone, Copy, Debug)] +enum HandleKind { + Stdout, + Stderr, +} + +impl HandleKind { + fn handle(&self) -> winutil::HandleRef { + match *self { + HandleKind::Stdout => winutil::HandleRef::stdout(), + HandleKind::Stderr => winutil::HandleRef::stderr(), + } + } +} + +impl Console { + /// Get a console for a standard I/O stream. + fn create_for_stream(kind: HandleKind) -> io::Result { + let h = kind.handle(); + let info = winutil::console::screen_buffer_info(&h)?; + let attr = TextAttributes::from_word(info.attributes()); + Ok(Console { + kind: kind, + start_attr: attr, + cur_attr: attr, + }) + } + + /// Create a new Console to stdout. + /// + /// If there was a problem creating the console, then an error is returned. + pub fn stdout() -> io::Result { + Self::create_for_stream(HandleKind::Stdout) + } + + /// Create a new Console to stderr. + /// + /// If there was a problem creating the console, then an error is returned. + pub fn stderr() -> io::Result { + Self::create_for_stream(HandleKind::Stderr) + } + + /// Applies the current text attributes. + fn set(&mut self) -> io::Result<()> { + winutil::console::set_text_attributes( + self.kind.handle(), + self.cur_attr.to_word(), + ) + } + + /// Apply the given intensity and color attributes to the console + /// foreground. + /// + /// If there was a problem setting attributes on the console, then an error + /// is returned. + pub fn fg(&mut self, intense: Intense, color: Color) -> io::Result<()> { + self.cur_attr.fg_color = color; + self.cur_attr.fg_intense = intense; + self.set() + } + + /// Apply the given intensity and color attributes to the console + /// background. + /// + /// If there was a problem setting attributes on the console, then an error + /// is returned. + pub fn bg(&mut self, intense: Intense, color: Color) -> io::Result<()> { + self.cur_attr.bg_color = color; + self.cur_attr.bg_intense = intense; + self.set() + } + + /// Reset the console text attributes to their original settings. + /// + /// The original settings correspond to the text attributes on the console + /// when this `Console` value was created. + /// + /// If there was a problem setting attributes on the console, then an error + /// is returned. + pub fn reset(&mut self) -> io::Result<()> { + self.cur_attr = self.start_attr; + self.set() + } + + /// Toggle virtual terminal processing. + /// + /// This method attempts to toggle virtual terminal processing for this + /// console. If there was a problem toggling it, then an error returned. + /// On success, the caller may assume that toggling it was successful. + /// + /// When virtual terminal processing is enabled, characters emitted to the + /// console are parsed for VT100 and similar control character sequences + /// that control color and other similar operations. + pub fn set_virtual_terminal_processing( + &mut self, + yes: bool, + ) -> io::Result<()> { + let vt = wincon::ENABLE_VIRTUAL_TERMINAL_PROCESSING; + + let handle = self.kind.handle(); + let old_mode = winutil::console::mode(&handle)?; + let new_mode = + if yes { + old_mode | vt + } else { + old_mode & !vt + }; + if old_mode == new_mode { + return Ok(()); + } + winutil::console::set_mode(&handle, new_mode) + } +} + +/// A representation of text attributes for the Windows console. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct TextAttributes { + fg_color: Color, + fg_intense: Intense, + bg_color: Color, + bg_intense: Intense, +} + +impl TextAttributes { + fn to_word(&self) -> WORD { + let mut w = 0; + w |= self.fg_color.to_fg(); + w |= self.fg_intense.to_fg(); + w |= self.bg_color.to_bg(); + w |= self.bg_intense.to_bg(); + w + } + + fn from_word(word: WORD) -> TextAttributes { + TextAttributes { + fg_color: Color::from_fg(word), + fg_intense: Intense::from_fg(word), + bg_color: Color::from_bg(word), + bg_intense: Intense::from_bg(word), + } + } +} + +/// Whether to use intense colors or not. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Intense { + Yes, + No, +} + +impl Intense { + fn to_bg(&self) -> WORD { + self.to_fg() << 4 + } + + fn from_bg(word: WORD) -> Intense { + Intense::from_fg(word >> 4) + } + + fn to_fg(&self) -> WORD { + match *self { + Intense::No => 0, + Intense::Yes => FG_INTENSITY, + } + } + + fn from_fg(word: WORD) -> Intense { + if word & FG_INTENSITY > 0 { + Intense::Yes + } else { + Intense::No + } + } +} + +/// The set of available colors for use with a Windows console. +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Color { + Black, + Blue, + Green, + Red, + Cyan, + Magenta, + Yellow, + White, +} + +impl Color { + fn to_bg(&self) -> WORD { + self.to_fg() << 4 + } + + fn from_bg(word: WORD) -> Color { + Color::from_fg(word >> 4) + } + + fn to_fg(&self) -> WORD { + match *self { + Color::Black => 0, + Color::Blue => FG_BLUE, + Color::Green => FG_GREEN, + Color::Red => FG_RED, + Color::Cyan => FG_CYAN, + Color::Magenta => FG_MAGENTA, + Color::Yellow => FG_YELLOW, + Color::White => FG_WHITE, + } + } + + fn from_fg(word: WORD) -> Color { + match word & 0b111 { + FG_BLUE => Color::Blue, + FG_GREEN => Color::Green, + FG_RED => Color::Red, + FG_CYAN => Color::Cyan, + FG_MAGENTA => Color::Magenta, + FG_YELLOW => Color::Yellow, + FG_WHITE => Color::White, + _ => Color::Black, + } + } +}