diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/yansi-term | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/yansi-term')
-rw-r--r-- | vendor/yansi-term/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/yansi-term/Cargo.lock | 166 | ||||
-rw-r--r-- | vendor/yansi-term/Cargo.toml | 47 | ||||
-rw-r--r-- | vendor/yansi-term/LICENCE | 21 | ||||
-rw-r--r-- | vendor/yansi-term/README.md | 119 | ||||
-rw-r--r-- | vendor/yansi-term/examples/256_colours.rs | 76 | ||||
-rw-r--r-- | vendor/yansi-term/examples/basic_colours.rs | 18 | ||||
-rw-r--r-- | vendor/yansi-term/examples/overwrite.rs | 18 | ||||
-rw-r--r-- | vendor/yansi-term/examples/rgb_colours.rs | 23 | ||||
-rw-r--r-- | vendor/yansi-term/src/ansi.rs | 290 | ||||
-rw-r--r-- | vendor/yansi-term/src/display.rs | 80 | ||||
-rw-r--r-- | vendor/yansi-term/src/lib.rs | 168 | ||||
-rw-r--r-- | vendor/yansi-term/src/style.rs | 541 | ||||
-rw-r--r-- | vendor/yansi-term/src/windows.rs | 61 |
14 files changed, 1629 insertions, 0 deletions
diff --git a/vendor/yansi-term/.cargo-checksum.json b/vendor/yansi-term/.cargo-checksum.json new file mode 100644 index 000000000..c0e7bf67d --- /dev/null +++ b/vendor/yansi-term/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"edf0cae7f83b55007885193ecd42f99d98a29ac962f3572d1a32a62d4e48c6a5","Cargo.toml":"713a90e09d7d319549c0d7d9de44dfd72650fa14451f5954133b8da863a7aac7","LICENCE":"2762990c7fbba9d550802a2593c1d857dcd52596bb0f9f192a97e9a7ac5f4f9e","README.md":"9615020697f2899bac358a9e888c2a8a8b76bbbd5230bb13d4388dcc252960df","examples/256_colours.rs":"635a307aa7e343d1f739f100e47bef6be3014009cde61003a13aaf0af4ba7cf6","examples/basic_colours.rs":"cfa1df2d113f9476e4f27cbdfc531210dc92342b73169917b1fc5be4674d0e31","examples/overwrite.rs":"f00ae49c072f0395a6aaa3f56179d3987210d239ed2248eed257438e478c6708","examples/rgb_colours.rs":"94aa54e3572e08a785e23f0a1b0ab6d51f61ade1a8d378634903cfa86a116d29","src/ansi.rs":"a8ebfd4b610a6aef9ce80934dc5fb21f83a2dc7298366857eb01acfd0bbb191d","src/display.rs":"e1838a10500343a38b5a2c314465f079d5f024a79e3955c10a045a9bc6b71c5d","src/lib.rs":"af3539ba603706ca5f6f1d7348649a0d5abe6ab4d62704f0b2b769b36db55493","src/style.rs":"177864e4304d286ad65bce9e446c61f12947fdce8936bc7d59ae8170f26aad51","src/windows.rs":"f6dad095cde0400fd238bb5ae03e0be84d665abdcfae3c5e4005c0d837d2e692"},"package":"fe5c30ade05e61656247b2e334a031dfd0cc466fadef865bdcdea8d537951bf1"}
\ No newline at end of file diff --git a/vendor/yansi-term/Cargo.lock b/vendor/yansi-term/Cargo.lock new file mode 100644 index 000000000..9964b2354 --- /dev/null +++ b/vendor/yansi-term/Cargo.lock @@ -0,0 +1,166 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +dependencies = [ + "memchr", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "memchr" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" + +[[package]] +name = "proc-macro2" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" + +[[package]] +name = "ryu" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" + +[[package]] +name = "serde" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb37da98a55b1d08529362d9cbb863be17556873df2585904ab9d2bc951291d0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yansi-term" +version = "0.1.2" +dependencies = [ + "doc-comment", + "regex", + "serde", + "serde_json", + "winapi", +] diff --git a/vendor/yansi-term/Cargo.toml b/vendor/yansi-term/Cargo.toml new file mode 100644 index 000000000..031786682 --- /dev/null +++ b/vendor/yansi-term/Cargo.toml @@ -0,0 +1,47 @@ +# 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] +edition = "2018" +name = "yansi-term" +version = "0.1.2" +authors = ["ogham@bsago.me", "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>", "Josh Triplett <josh@joshtriplett.org>", "Juan Aguilar Santillana <mhpoin@gmail.com>"] +description = "Library for ANSI terminal colours and styles (bold, underline)" +homepage = "https://github.com/botika/yansi-term" +documentation = "https://docs.rs/yansi-term" +readme = "README.md" +license = "MIT" +repository = "https://github.com/botika/yansi-term" +[dependencies.serde] +version = "1.0" +features = ["derive"] +optional = true +[dev-dependencies.doc-comment] +version = "0.3" + +[dev-dependencies.regex] +version = "1.1" + +[dev-dependencies.serde_json] +version = "1.0" + +[features] +derive_serde_style = ["serde"] +[target."cfg(target_os=\"windows\")".dependencies.winapi] +version = "0.3.4" +features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"] +[badges.maintenance] +status = "actively-developed" + +[badges.travis-ci] +branch = "master" +repository = "botika/yansi-term" diff --git a/vendor/yansi-term/LICENCE b/vendor/yansi-term/LICENCE new file mode 100644 index 000000000..3228cc99b --- /dev/null +++ b/vendor/yansi-term/LICENCE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Benjamin Sago + +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/vendor/yansi-term/README.md b/vendor/yansi-term/README.md new file mode 100644 index 000000000..182f0ddf3 --- /dev/null +++ b/vendor/yansi-term/README.md @@ -0,0 +1,119 @@ +# yansi-term [![Latest version](https://img.shields.io/crates/v/yansi-term.svg)](https://crates.io/crates/yansi-term) [![Build Status](https://travis-ci.org/botika/yansi-term.svg?branch=master)](https://travis-ci.org/botika/yansi-term) +> Adapted from [`rust-ansi-term`](https://github.com/ogham/rust-ansi-term) + +Refactor for use [`fmt::Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) and `FnOnce(&mut fmt::Formatter) -> fmt::Result` + + +This is a library for controlling colours and formatting, such as red bold text or blue underlined text, on ANSI terminals. + +### [View the Rustdoc](https://docs.rs/yansi-term) + + +# Installation + +This crate works with [Cargo](http://crates.io). Add the following to your `Cargo.toml` dependencies section: + +```toml +[dependencies] +yansi-term = "0.1" +``` + + +## Basic usage + +There are two main types in this crate that you need to be concerned with: `Style`, and `Colour`. + +A `Style` holds stylistic information: foreground and background colours, whether the text should be bold, or blinking, or other properties. +The `Colour` enum represents the available colours. + +`Color` is also available as an alias to `Colour`. + +To format a string, call the `paint` method on a `Style` or a `Colour`, passing in the string you want to format as the argument. +For example, here’s how to get some red text: + +```rust +use yansi_term::Colour::Red; + +println!("This is in red: {}", Red.paint("a red string")); +``` + +**Note for Windows 10 users:** On Windows 10, the application must enable ANSI support first: + +```rust,ignore +let enabled = yansi_term::enable_ansi_support(); +``` + +## Bold, underline, background, and other styles + +For anything more complex than plain foreground colour changes, you need to construct `Style` values themselves, rather than beginning with a `Colour`. +You can do this by chaining methods based on a new `Style`, created with `Style::new()`. +Each method creates a new style that has that specific property set. +For example: + +```rust +use yansi_term::Style; + +println!("How about some {} and {}?", + Style::new().bold().paint("bold"), + Style::new().underline().paint("underline")); +``` + +For brevity, these methods have also been implemented for `Colour` values, so you can give your styles a foreground colour without having to begin with an empty `Style` value: + +```rust +use yansi_term::Colour::{Blue, Yellow}; + +println!("Demonstrating {} and {}!", + Blue.bold().paint("blue bold"), + Yellow.underline().paint("yellow underline")); + +println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!")); +``` + +The complete list of styles you can use are: +`bold`, `dimmed`, `italic`, `underline`, `blink`, `reverse`, `hidden`, and `on` for background colours. + +In some cases, you may find it easier to change the foreground on an existing `Style` rather than starting from the appropriate `Colour`. +You can do this using the `fg` method: + +```rust +use yansi_term::Style; +use yansi_term::Colour::{Blue, Cyan, Yellow}; + +println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!")); +println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!")); +``` + +You can turn a `Colour` into a `Style` with the `normal` method. + +```rust +use yansi_term::Style; +use yansi_term::Colour::Red; + +Red.normal().paint("yet another red string"); +Style::default().paint("a completely regular string"); +``` + + +## Extended colours + +You can access the extended range of 256 colours by using the `Colour::Fixed` variant, which takes an argument of the colour number to use. +This can be included wherever you would use a `Colour`: + +```rust +use yansi_term::Colour::Fixed; + +Fixed(134).paint("A sort of light purple"); +Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup"); +``` + +The first sixteen of these values are the same as the normal and bold standard colour variants. +There’s nothing stopping you from using these as `Fixed` colours instead, but there’s nothing to be gained by doing so either. + +You can also access full 24-bit colour by using the `Colour::RGB` variant, which takes separate `u8` arguments for red, green, and blue: + +```rust +use yansi_term::Colour::RGB; + +RGB(70, 130, 180).paint("Steel blue"); +``` diff --git a/vendor/yansi-term/examples/256_colours.rs b/vendor/yansi-term/examples/256_colours.rs new file mode 100644 index 000000000..1a222a755 --- /dev/null +++ b/vendor/yansi-term/examples/256_colours.rs @@ -0,0 +1,76 @@ +extern crate yansi_term; +use yansi_term::Colour; + +// This example prints out the 256 colours. +// They're arranged like this: +// +// - 0 to 8 are the eight standard colours. +// - 9 to 15 are the eight bold colours. +// - 16 to 231 are six blocks of six-by-six colour squares. +// - 232 to 255 are shades of grey. + +fn main() { + // First two lines + for c in 0..8 { + glow(c, c != 0); + print!(" "); + } + println!(); + for c in 8..16 { + glow(c, c != 8); + print!(" "); + } + println!("\n"); + + // Six lines of the first three squares + for row in 0..6 { + for square in 0..3 { + for column in 0..6 { + glow(16 + square * 36 + row * 6 + column, row >= 3); + print!(" "); + } + + print!(" "); + } + + println!(); + } + println!(); + + // Six more lines of the other three squares + for row in 0..6 { + for square in 0..3 { + for column in 0..6 { + glow(124 + square * 36 + row * 6 + column, row >= 3); + print!(" "); + } + + print!(" "); + } + + println!(); + } + println!(); + + // The last greyscale lines + for c in 232..=243 { + glow(c, false); + print!(" "); + } + println!(); + for c in 244..=255 { + glow(c, true); + print!(" "); + } + println!(); +} + +fn glow(c: u8, light_bg: bool) { + let base = if light_bg { + Colour::Black + } else { + Colour::White + }; + let style = base.on(Colour::Fixed(c)); + print!("{}", style.paint_fn(|f| write!(f, " {:3} ", c))); +} diff --git a/vendor/yansi-term/examples/basic_colours.rs b/vendor/yansi-term/examples/basic_colours.rs new file mode 100644 index 000000000..666c4789a --- /dev/null +++ b/vendor/yansi-term/examples/basic_colours.rs @@ -0,0 +1,18 @@ +extern crate yansi_term; +use yansi_term::{Colour::*, Style}; + +// This example prints out the 16 basic colours. + +fn main() { + let normal = Style::default(); + + println!("{} {}", normal.paint("Normal"), normal.bold().paint("bold")); + println!("{} {}", Black.paint("Black"), Black.bold().paint("bold")); + println!("{} {}", Red.paint("Red"), Red.bold().paint("bold")); + println!("{} {}", Green.paint("Green"), Green.bold().paint("bold")); + println!("{} {}", Yellow.paint("Yellow"), Yellow.bold().paint("bold")); + println!("{} {}", Blue.paint("Blue"), Blue.bold().paint("bold")); + println!("{} {}", Purple.paint("Purple"), Purple.bold().paint("bold")); + println!("{} {}", Cyan.paint("Cyan"), Cyan.bold().paint("bold")); + println!("{} {}", White.paint("White"), White.bold().paint("bold")); +} diff --git a/vendor/yansi-term/examples/overwrite.rs b/vendor/yansi-term/examples/overwrite.rs new file mode 100644 index 000000000..ed0224f48 --- /dev/null +++ b/vendor/yansi-term/examples/overwrite.rs @@ -0,0 +1,18 @@ +extern crate yansi_term; +use yansi_term::{Colour::*, Style}; + +// This example prints out the 16 basic colours. + +fn main() { + println!( + "{}", + Red.paint_fn(|f| { + f.write_str("RED")?; + Style::new().bold().write_prefix(f)?; + f.write_str("RED_BOLD")?; + Style::write_reset(f)?; + Black.write_prefix(f)?; + f.write_str("BLACK") + }) + ); +} diff --git a/vendor/yansi-term/examples/rgb_colours.rs b/vendor/yansi-term/examples/rgb_colours.rs new file mode 100644 index 000000000..c28b52e56 --- /dev/null +++ b/vendor/yansi-term/examples/rgb_colours.rs @@ -0,0 +1,23 @@ +extern crate yansi_term; +use yansi_term::{Colour, Style}; + +// This example prints out a colour gradient in a grid by calculating each +// character’s red, green, and blue components, and using 24-bit colour codes +// to display them. + +const WIDTH: i32 = 80; +const HEIGHT: i32 = 24; + +fn main() { + for row in 0..HEIGHT { + for col in 0..WIDTH { + let r = (row * 255 / HEIGHT) as u8; + let g = (col * 255 / WIDTH) as u8; + let b = 128; + + print!("{}", Style::default().on(Colour::RGB(r, g, b)).paint(" ")); + } + + println!(); + } +} diff --git a/vendor/yansi-term/src/ansi.rs b/vendor/yansi-term/src/ansi.rs new file mode 100644 index 000000000..159038d38 --- /dev/null +++ b/vendor/yansi-term/src/ansi.rs @@ -0,0 +1,290 @@ +use std::fmt::{self, Display, Write}; + +use crate::{Colour, Style}; + +impl Style { + /// Write any bytes that go *before* a piece of text to the given writer. + pub fn write_prefix(&self, f: &mut fmt::Formatter) -> Result<bool, fmt::Error> { + let mut written_anything = false; + macro_rules! write_anything { + () => { + if written_anything { + f.write_char(';')?; + } else { + // Write the codes’ prefix, then write numbers, separated by + // semicolons, for each text style we want to apply. + f.write_str("\x1B[")?; + written_anything = true; + } + }; + } + macro_rules! write_char { + ($cond:ident, $c:expr) => { + if self.$cond { + write_anything!(); + f.write_char($c)?; + } + }; + } + macro_rules! write_chars { + ($cond:ident => $c:expr) => { write_char!($cond, $c); }; + ($cond:ident => $c:expr, $($t:tt)+) => { + write_char!($cond, $c); + write_chars!($($t)+); + }; + } + + write_chars!( + is_bold => '1', + is_dimmed => '2', + is_italic => '3', + is_underline => '4', + is_blink => '5', + is_reverse => '7', + is_hidden => '8', + is_strikethrough => '9' + ); + + // The foreground and background colours, if specified, need to be + // handled specially because the number codes are more complicated. + // (see `write_background_code` and `write_foreground_code`) + if let Some(bg) = self.background { + write_anything!(); + bg.write_background_code(f)?; + } + + if let Some(fg) = self.foreground { + write_anything!(); + fg.write_foreground_code(f)?; + } + + if written_anything { + // All the codes end with an `m`, because reasons. + f.write_char('m')?; + } + + Ok(written_anything) + } + + /// Write any bytes that go *after* a piece of text to the given writer. + #[inline] + pub fn write_reset(f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(RESET) + } +} + +impl Colour { + /// Write any bytes that go *before* a piece of text to the given writer. + #[inline] + pub fn write_prefix(self, f: &mut fmt::Formatter) -> Result<bool, fmt::Error> { + self.normal().write_prefix(f) + } +} + +/// The code to send to reset all styles and return to `Style::default()`. +pub static RESET: &str = "\x1B[0m"; + +macro_rules! write_color { + ($_self:ident, $f:ident => + $black:expr, $red:expr, $green:expr, $yellow:expr, $blue:expr, + $purple:expr, $cyan:expr, $white:expr, $fixed:expr, $rgb:expr) => {{ + use Colour::*; + match $_self { + Black => $f.write_str($black), + Red => $f.write_str($red), + Green => $f.write_str($green), + Yellow => $f.write_str($yellow), + Blue => $f.write_str($blue), + Purple => $f.write_str($purple), + Cyan => $f.write_str($cyan), + White => $f.write_str($white), + Fixed(num) => { + $f.write_str($fixed)?; + num.fmt($f) + } + RGB(r, g, b) => { + $f.write_str($rgb)?; + r.fmt($f)?; + $f.write_char(';')?; + g.fmt($f)?; + $f.write_char(';')?; + b.fmt($f) + } + } + }}; +} + +impl Colour { + #[inline] + fn write_foreground_code(self, f: &mut fmt::Formatter) -> fmt::Result { + write_color!(self, f => "30", "31", "32", "33", "34", "35", "36", "37", "38;5;", "38;2;") + } + + #[inline] + fn write_background_code(self, f: &mut fmt::Formatter) -> fmt::Result { + write_color!(self, f => "40", "41", "42", "43", "44", "45", "46", "47", "48;5;", "48;2;") + } +} + +#[cfg(test)] +mod test { + use crate::{Colour::*, Style}; + + macro_rules! test { + ($name: ident: $style: expr; $input: expr => $result: expr) => { + #[test] + fn $name() { + assert_eq!($style.paint($input).to_string(), $result.to_string()); + } + }; + } + + test!(plain: Style::default(); "text/plain" => "text/plain"); + test!(red: Red; "hi" => "\x1B[31mhi\x1B[0m"); + test!(black: Black.normal(); "hi" => "\x1B[30mhi\x1B[0m"); + test!(yellow_bold: Yellow.bold(); "hi" => "\x1B[1;33mhi\x1B[0m"); + test!(yellow_bold_2: Yellow.normal().bold(); "hi" => "\x1B[1;33mhi\x1B[0m"); + test!(blue_underline: Blue.underline(); "hi" => "\x1B[4;34mhi\x1B[0m"); + test!(green_bold_ul: Green.bold().underline(); "hi" => "\x1B[1;4;32mhi\x1B[0m"); + test!(green_bold_ul_2: Green.underline().bold(); "hi" => "\x1B[1;4;32mhi\x1B[0m"); + test!(purple_on_white: Purple.on(White); "hi" => "\x1B[47;35mhi\x1B[0m"); + test!(purple_on_white_2: Purple.normal().on(White); "hi" => "\x1B[47;35mhi\x1B[0m"); + test!(yellow_on_blue: Style::new().on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m"); + test!(yellow_on_blue_2: Cyan.on(Blue).fg(Yellow); "hi" => "\x1B[44;33mhi\x1B[0m"); + test!(cyan_bold_on_white: Cyan.bold().on(White); "hi" => "\x1B[1;47;36mhi\x1B[0m"); + test!(cyan_ul_on_white: Cyan.underline().on(White); "hi" => "\x1B[4;47;36mhi\x1B[0m"); + test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m"); + test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m"); + test!(fixed: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m"); + test!(fixed_on_purple: Fixed(100).on(Purple); "hi" => "\x1B[45;38;5;100mhi\x1B[0m"); + test!(fixed_on_fixed: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m"); + test!(rgb: RGB(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m"); + test!(rgb_on_blue: RGB(70,130,180).on(Blue); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m"); + test!(blue_on_rgb: Blue.on(RGB(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m"); + test!(rgb_on_rgb: RGB(70,130,180).on(RGB(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m"); + test!(bold: Style::new().bold(); "hi" => "\x1B[1mhi\x1B[0m"); + test!(underline: Style::new().underline(); "hi" => "\x1B[4mhi\x1B[0m"); + test!(bunderline: Style::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m"); + test!(dimmed: Style::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m"); + test!(italic: Style::new().italic(); "hi" => "\x1B[3mhi\x1B[0m"); + test!(blink: Style::new().blink(); "hi" => "\x1B[5mhi\x1B[0m"); + test!(reverse: Style::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m"); + test!(hidden: Style::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m"); + test!(stricken: Style::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m"); + + macro_rules! test_fn { + ($name:ident: $style:expr; $result:expr) => { + #[test] + fn $name() { + let string = String::from("hi"); + let string: &str = &string; + assert_eq!( + $style.paint_fn(|f| f.write_str(string)).to_string(), + $result.to_string() + ); + } + }; + } + + test_fn!(plain_fn: Style::default(); "hi"); + test_fn!(red_fn: Red; "\x1B[31mhi\x1B[0m"); + test_fn!(black_fn: Black.normal(); "\x1B[30mhi\x1B[0m"); + test_fn!(yellow_bold_fn: Yellow.bold(); "\x1B[1;33mhi\x1B[0m"); + test_fn!(yellow_bold_2_fn: Yellow.normal().bold(); "\x1B[1;33mhi\x1B[0m"); + test_fn!(blue_underline_fn: Blue.underline(); "\x1B[4;34mhi\x1B[0m"); + test_fn!(green_bold_ul_fn: Green.bold().underline(); "\x1B[1;4;32mhi\x1B[0m"); + test_fn!(green_bold_ul_2_fn: Green.underline().bold(); "\x1B[1;4;32mhi\x1B[0m"); + test_fn!(purple_on_white_fn: Purple.on(White); "\x1B[47;35mhi\x1B[0m"); + test_fn!(purple_on_white_2_fn: Purple.normal().on(White); "\x1B[47;35mhi\x1B[0m"); + test_fn!(yellow_on_blue_fn: Style::new().on(Blue).fg(Yellow); "\x1B[44;33mhi\x1B[0m"); + test_fn!(yellow_on_blue_2_fn: Cyan.on(Blue).fg(Yellow); "\x1B[44;33mhi\x1B[0m"); + test_fn!(cyan_bold_on_white_fn: Cyan.bold().on(White); "\x1B[1;47;36mhi\x1B[0m"); + test_fn!(cyan_ul_on_white_fn: Cyan.underline().on(White); "\x1B[4;47;36mhi\x1B[0m"); + test_fn!(cyan_bold_ul_on_white_fn: Cyan.bold().underline().on(White); "\x1B[1;4;47;36mhi\x1B[0m"); + test_fn!(cyan_ul_bold_on_white_fn: Cyan.underline().bold().on(White); "\x1B[1;4;47;36mhi\x1B[0m"); + test_fn!(fixed_fn: Fixed(100); "\x1B[38;5;100mhi\x1B[0m"); + test_fn!(fixed_on_purple_fn: Fixed(100).on(Purple); "\x1B[45;38;5;100mhi\x1B[0m"); + test_fn!(fixed_on_fixed_fn: Fixed(100).on(Fixed(200)); "\x1B[48;5;200;38;5;100mhi\x1B[0m"); + test_fn!(rgb_fn: RGB(70,130,180); "\x1B[38;2;70;130;180mhi\x1B[0m"); + test_fn!(rgb_on_blue_fn: RGB(70,130,180).on(Blue); "\x1B[44;38;2;70;130;180mhi\x1B[0m"); + test_fn!(blue_on_rgb_fn: Blue.on(RGB(70,130,180)); "\x1B[48;2;70;130;180;34mhi\x1B[0m"); + test_fn!(rgb_on_rgb_fn: RGB(70,130,180).on(RGB(5,10,15)); "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m"); + test_fn!(bold_fn: Style::new().bold(); "\x1B[1mhi\x1B[0m"); + test_fn!(underline_fn: Style::new().underline(); "\x1B[4mhi\x1B[0m"); + test_fn!(bunderline_fn: Style::new().bold().underline(); "\x1B[1;4mhi\x1B[0m"); + test_fn!(dimmed_fn: Style::new().dimmed(); "\x1B[2mhi\x1B[0m"); + test_fn!(italic_fn: Style::new().italic(); "\x1B[3mhi\x1B[0m"); + test_fn!(blink_fn: Style::new().blink(); "\x1B[5mhi\x1B[0m"); + test_fn!(reverse_fn: Style::new().reverse(); "\x1B[7mhi\x1B[0m"); + test_fn!(hidden_fn: Style::new().hidden(); "\x1B[8mhi\x1B[0m"); + test_fn!(stricken_fn: Style::new().strikethrough(); "\x1B[9mhi\x1B[0m"); + + #[test] + fn test_move() { + let string = String::from("hi"); + assert_eq!( + Style::default() + .paint_fn(|f| f.write_str(&string)) + .to_string(), + "hi" + ); + } + + #[test] + fn test_ref() { + let string = &String::from("hi"); + assert_eq!( + Style::default() + .paint_fn(|f| f.write_str(string)) + .to_string(), + "hi" + ); + } + + #[test] + fn test_debug() { + let a = vec![1, 2, 3]; + assert_eq!( + Style::default() + .paint_fn(|f| std::fmt::Debug::fmt(&a, f)) + .to_string(), + "[1, 2, 3]" + ); + assert_eq!( + Style::default() + .bold() + .paint_fn(|f| std::fmt::Debug::fmt(&a, f)) + .to_string(), + "\x1B[1m[1, 2, 3]\x1B[0m" + ); + } + + #[test] + fn test_write() { + assert_eq!( + Style::default() + .paint_fn(|f| write!(f, "{:.5}", 1.0)) + .to_string(), + "1.00000" + ); + assert_eq!( + Style::default() + .bold() + .paint_fn(|f| write!(f, "{:.5}", 1.0)) + .to_string(), + "\x1B[1m1.00000\x1B[0m" + ); + } + + /// Can not write the same `impl Display` two or more times + /// else return error + #[test] + fn test_error() { + use std::fmt::Write; + let a = Style::default().paint("foo"); + let _ = a.to_string(); + let mut b = String::new(); + + assert!(write!(b, "{}", a).is_err()); + } +} diff --git a/vendor/yansi-term/src/display.rs b/vendor/yansi-term/src/display.rs new file mode 100644 index 000000000..afc4e2846 --- /dev/null +++ b/vendor/yansi-term/src/display.rs @@ -0,0 +1,80 @@ +use std::{cell::Cell, fmt}; + +use crate::{Colour, Style}; + +/// An `DisplayANSI` includes a format function and a `Style` +struct DisplayANSI<F: FnOnce(&mut fmt::Formatter) -> fmt::Result> { + style: Style, + f: Cell<Option<F>>, +} + +impl<F: FnOnce(&mut fmt::Formatter) -> fmt::Result> fmt::Display for DisplayANSI<F> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let written = self.style.write_prefix(f)?; + self.f.take().ok_or(fmt::Error).and_then(|c| c(f))?; + if written { + Style::write_reset(f)?; + } + Ok(()) + } +} + +impl Style { + /// Paints the given text with this style + #[inline] + pub fn paint<'a>(self, input: &'a str) -> impl fmt::Display + 'a { + DisplayANSI { + f: Cell::new(Some(move |f: &mut fmt::Formatter| f.write_str(input))), + style: self, + } + } + + /// Paints the given format function with this style + #[inline] + pub fn paint_fn<F: FnOnce(&mut fmt::Formatter) -> fmt::Result>( + self, + f: F, + ) -> impl fmt::Display { + DisplayANSI { + f: Cell::new(Some(f)), + style: self, + } + } +} + +impl Colour { + /// Paints the given text with this colour + /// This is a short-cut so you don’t have to use `Blue.normal()` just + /// to get blue text. + /// + /// ``` + /// use yansi_term::Colour::Blue; + /// println!("{}", Blue.paint("da ba dee")); + /// ``` + #[inline] + pub fn paint<'a>(self, input: &'a str) -> impl fmt::Display + 'a { + self.normal().paint(input) + } + + /// Paints the given format function with this colour + #[inline] + pub fn paint_fn<F: FnOnce(&mut fmt::Formatter) -> fmt::Result>( + self, + f: F, + ) -> impl fmt::Display { + self.normal().paint_fn(f) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn no_control_codes_for_plain() { + let one = Style::default().paint("one"); + let two = Style::default().paint("two"); + let output = format!("{}{}", one, two); + assert_eq!(output, "onetwo"); + } +} diff --git a/vendor/yansi-term/src/lib.rs b/vendor/yansi-term/src/lib.rs new file mode 100644 index 000000000..588ce6344 --- /dev/null +++ b/vendor/yansi-term/src/lib.rs @@ -0,0 +1,168 @@ +//! > Adapted from [`rust-ansi-term`](https://github.com/ogham/rust-ansi-term) +//! > +//! > Refactor for use [`fmt::Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) +//! and `FnOnce(&mut fmt::Formatter) -> fmt::Result` +//! This is a library for controlling colours and formatting, such as +//! red bold text or blue underlined text, on ANSI terminals. +//! +//! +//! ## Basic usage +//! +//! There are three main types in this crate that you need to be +//! concerned with: [`ANSIString`], [`Style`], and [`Colour`]. +//! +//! A `Style` holds stylistic information: foreground and background colours, +//! whether the text should be bold, or blinking, or other properties. The +//! [`Colour`] enum represents the available colours. And an [`ANSIString`] is a +//! string paired with a [`Style`]. +//! +//! [`Color`] is also available as an alias to `Colour`. +//! +//! To format a string, call the `paint` method on a `Style` or a `Colour`, +//! passing in the string you want to format as the argument. For example, +//! here’s how to get some red text: +//! +//! ``` +//! use yansi_term::Colour::Red; +//! +//! println!("This is in red: {}", Red.paint("a red string")); +//! ``` +//! +//! It’s important to note that the `paint` method does *not* actually return a +//! string with the ANSI control characters surrounding it. Instead, it returns +//! that has a [`Display`] implementation that, when formatted, returns the characters. +//! ``` +//! use yansi_term::Colour::Red; +//! +//! let red_string = Red.paint("a red string").to_string(); +//! ``` +//! +//! +//! ## Bold, underline, background, and other styles +//! +//! For anything more complex than plain foreground colour changes, you need to +//! construct `Style` values themselves, rather than beginning with a `Colour`. +//! You can do this by chaining methods based on a new `Style`, created with +//! [`Style::new()`]. Each method creates a new style that has that specific +//! property set. For example: +//! +//! ``` +//! use yansi_term::Style; +//! +//! println!("How about some {} and {}?", +//! Style::new().bold().paint("bold"), +//! Style::new().underline().paint("underline")); +//! ``` +//! +//! For brevity, these methods have also been implemented for `Colour` values, +//! so you can give your styles a foreground colour without having to begin with +//! an empty `Style` value: +//! +//! ``` +//! use yansi_term::Colour::{Blue, Yellow}; +//! +//! println!("Demonstrating {} and {}!", +//! Blue.bold().paint("blue bold"), +//! Yellow.underline().paint("yellow underline")); +//! +//! println!("Yellow on blue: {}", Yellow.on(Blue).paint("wow!")); +//! ``` +//! +//! The complete list of styles you can use are: [`bold`], [`dimmed`], [`italic`], +//! [`underline`], [`blink`], [`reverse`], [`hidden`], [`strikethrough`], and [`on`] for +//! background colours. +//! +//! In some cases, you may find it easier to change the foreground on an +//! existing `Style` rather than starting from the appropriate `Colour`. +//! You can do this using the [`fg`] method: +//! +//! ``` +//! use yansi_term::Style; +//! use yansi_term::Colour::{Blue, Cyan, Yellow}; +//! +//! println!("Yellow on blue: {}", Style::new().on(Blue).fg(Yellow).paint("yow!")); +//! println!("Also yellow on blue: {}", Cyan.on(Blue).fg(Yellow).paint("zow!")); +//! ``` +//! +//! You can turn a `Colour` into a `Style` with the [`normal`] method. +//! This will produce the exact same `ANSIString` as if you just used the +//! `paint` method on the `Colour` directly, but it’s useful in certain cases: +//! for example, you may have a method that returns `Styles`, and need to +//! represent both the “red bold” and “red, but not bold” styles with values of +//! the same type. The `Style` struct also has a [`Default`] implementation if you +//! want to have a style with *nothing* set. +//! +//! ``` +//! use yansi_term::Style; +//! use yansi_term::Colour::Red; +//! +//! Red.normal().paint("yet another red string"); +//! Style::default().paint("a completely regular string"); +//! ``` +//! +//! +//! ## Extended colours +//! +//! You can access the extended range of 256 colours by using the `Colour::Fixed` +//! variant, which takes an argument of the colour number to use. This can be +//! included wherever you would use a `Colour`: +//! +//! ``` +//! use yansi_term::Colour::Fixed; +//! +//! Fixed(134).paint("A sort of light purple"); +//! Fixed(221).on(Fixed(124)).paint("Mustard in the ketchup"); +//! ``` +//! +//! The first sixteen of these values are the same as the normal and bold +//! standard colour variants. There’s nothing stopping you from using these as +//! `Fixed` colours instead, but there’s nothing to be gained by doing so +//! either. +//! +//! You can also access full 24-bit colour by using the `Colour::RGB` variant, +//! which takes separate `u8` arguments for red, green, and blue: +//! +//! ``` +//! use yansi_term::Colour::RGB; +//! +//! RGB(70, 130, 180).paint("Steel blue"); +//! ``` + +//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html +//! [`Default`]: https://doc.rust-lang.org/std/default/trait.Default.html +//! [`Style`]: struct.Style.html +//! [`Style::new()`]: struct.Style.html#method.new +//! [`Color`]: enum.Color.html +//! [`Colour`]: enum.Colour.html +//! +//! [`bold`]: struct.Style.html#method.bold +//! [`dimmed`]: struct.Style.html#method.dimmed +//! [`italic`]: struct.Style.html#method.italic +//! [`underline`]: struct.Style.html#method.underline +//! [`blink`]: struct.Style.html#method.blink +//! [`reverse`]: struct.Style.html#method.reverse +//! [`hidden`]: struct.Style.html#method.hidden +//! [`strikethrough`]: struct.Style.html#method.strikethrough +//! [`fg`]: struct.Style.html#method.fg +//! [`on`]: struct.Style.html#method.on + +#[cfg(target_os = "windows")] +extern crate winapi; +#[cfg(test)] +#[macro_use] +extern crate doc_comment; + +#[cfg(test)] +doctest!("../README.md"); + +mod ansi; +mod style; +pub use style::{Colour, Style}; + +/// Color is a type alias for `Colour`. +pub use Colour as Color; + +mod display; + +mod windows; +pub use windows::*; diff --git a/vendor/yansi-term/src/style.rs b/vendor/yansi-term/src/style.rs new file mode 100644 index 000000000..aaef739f9 --- /dev/null +++ b/vendor/yansi-term/src/style.rs @@ -0,0 +1,541 @@ +/// A style is a collection of properties that can format a string +/// using ANSI escape codes. +/// +/// # Examples +/// +/// ``` +/// use yansi_term::{Style, Colour}; +/// +/// let style = Style::new().bold().on(Colour::Black); +/// println!("{}", style.paint("Bold on black")); +/// ``` +#[derive(PartialEq, Clone, Copy, Default, Debug)] +#[cfg_attr( + feature = "derive_serde_style", + derive(serde::Deserialize, serde::Serialize) +)] +pub struct Style { + /// The style's foreground colour, if it has one. + pub foreground: Option<Colour>, + + /// The style's background colour, if it has one. + pub background: Option<Colour>, + + /// Whether this style is bold. + pub is_bold: bool, + + /// Whether this style is dimmed. + pub is_dimmed: bool, + + /// Whether this style is italic. + pub is_italic: bool, + + /// Whether this style is underlined. + pub is_underline: bool, + + /// Whether this style is blinking. + pub is_blink: bool, + + /// Whether this style has reverse colours. + pub is_reverse: bool, + + /// Whether this style is hidden. + pub is_hidden: bool, + + /// Whether this style is struckthrough. + pub is_strikethrough: bool, +} + +impl Style { + /// Creates a new Style with no properties set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new(); + /// println!("{}", style.paint("hi")); + /// ``` + pub fn new() -> Style { + Style::default() + } + + /// Returns a `Style` with the bold property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().bold(); + /// println!("{}", style.paint("hey")); + /// ``` + pub fn bold(mut self) -> Self { + self.is_bold = true; + self + } + + /// Returns a `Style` with the dimmed property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().dimmed(); + /// println!("{}", style.paint("sup")); + /// ``` + pub fn dimmed(mut self) -> Self { + self.is_dimmed = true; + self + } + + /// Returns a `Style` with the italic property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().italic(); + /// println!("{}", style.paint("greetings")); + /// ``` + pub fn italic(mut self) -> Self { + self.is_italic = true; + self + } + + /// Returns a `Style` with the underline property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().underline(); + /// println!("{}", style.paint("salutations")); + /// ``` + pub fn underline(mut self) -> Self { + self.is_underline = true; + self + } + + /// Returns a `Style` with the blink property set. + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().blink(); + /// println!("{}", style.paint("wazzup")); + /// ``` + pub fn blink(mut self) -> Self { + self.is_blink = true; + self + } + + /// Returns a `Style` with the reverse property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().reverse(); + /// println!("{}", style.paint("aloha")); + /// ``` + pub fn reverse(mut self) -> Self { + self.is_reverse = true; + self + } + + /// Returns a `Style` with the hidden property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().hidden(); + /// println!("{}", style.paint("ahoy")); + /// ``` + pub fn hidden(mut self) -> Self { + self.is_hidden = true; + self + } + + /// Returns a `Style` with the strikethrough property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// let style = Style::new().strikethrough(); + /// println!("{}", style.paint("yo")); + /// ``` + pub fn strikethrough(mut self) -> Self { + self.is_strikethrough = true; + self + } + + /// Returns a `Style` with the foreground colour property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::{Style, Colour}; + /// + /// let style = Style::new().fg(Colour::Yellow); + /// println!("{}", style.paint("hi")); + /// ``` + pub fn fg(mut self, foreground: Colour) -> Self { + self.foreground = Some(foreground); + self + } + + /// Returns a `Style` with the background colour property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::{Style, Colour}; + /// + /// let style = Style::new().on(Colour::Blue); + /// println!("{}", style.paint("eyyyy")); + /// ``` + pub fn on(mut self, background: Colour) -> Self { + self.background = Some(background); + self + } + + /// Return true if this `Style` has no actual styles, and can be written + /// without any control characters. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Style; + /// + /// assert_eq!(true, Style::default().is_plain()); + /// assert_eq!(false, Style::default().bold().is_plain()); + /// ``` + pub fn is_plain(&self) -> bool { + *self == Style::default() + } +} + +/// A colour is one specific type of ANSI escape code, and can refer +/// to either the foreground or background colour. +/// +/// These use the standard numeric sequences. +/// See <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html> +#[derive(PartialEq, Clone, Copy, Debug)] +#[cfg_attr( + feature = "derive_serde_style", + derive(serde::Deserialize, serde::Serialize) +)] +pub enum Colour { + /// Colour #0 (foreground code `30`, background code `40`). + /// + /// This is not necessarily the background colour, and using it as one may + /// render the text hard to read on terminals with dark backgrounds. + Black, + + /// Colour #1 (foreground code `31`, background code `41`). + Red, + + /// Colour #2 (foreground code `32`, background code `42`). + Green, + + /// Colour #3 (foreground code `33`, background code `43`). + Yellow, + + /// Colour #4 (foreground code `34`, background code `44`). + Blue, + + /// Colour #5 (foreground code `35`, background code `45`). + Purple, + + /// Colour #6 (foreground code `36`, background code `46`). + Cyan, + + /// Colour #7 (foreground code `37`, background code `47`). + /// + /// As above, this is not necessarily the foreground colour, and may be + /// hard to read on terminals with light backgrounds. + White, + + /// A colour number from 0 to 255, for use in 256-colour terminal + /// environments. + /// + /// - Colours 0 to 7 are the `Black` to `White` variants respectively. + /// These colours can usually be changed in the terminal emulator. + /// - Colours 8 to 15 are brighter versions of the eight colours above. + /// These can also usually be changed in the terminal emulator, or it + /// could be configured to use the original colours and show the text in + /// bold instead. It varies depending on the program. + /// - Colours 16 to 231 contain several palettes of bright colours, + /// arranged in six squares measuring six by six each. + /// - Colours 232 to 255 are shades of grey from black to white. + /// + /// It might make more sense to look at a [colour chart][cc]. + /// + /// [cc]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg + Fixed(u8), + + /// A 24-bit RGB color, as specified by ISO-8613-3. + RGB(u8, u8, u8), +} + +impl Colour { + /// Returns a `Style` with the foreground colour set to this colour. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Red.normal(); + /// println!("{}", style.paint("hi")); + /// ``` + pub fn normal(self) -> Style { + Style { + foreground: Some(self), + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// bold property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Green.bold(); + /// println!("{}", style.paint("hey")); + /// ``` + pub fn bold(self) -> Style { + Style { + foreground: Some(self), + is_bold: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// dimmed property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Yellow.dimmed(); + /// println!("{}", style.paint("sup")); + /// ``` + pub fn dimmed(self) -> Style { + Style { + foreground: Some(self), + is_dimmed: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// italic property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Blue.italic(); + /// println!("{}", style.paint("greetings")); + /// ``` + pub fn italic(self) -> Style { + Style { + foreground: Some(self), + is_italic: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// underline property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Purple.underline(); + /// println!("{}", style.paint("salutations")); + /// ``` + pub fn underline(self) -> Style { + Style { + foreground: Some(self), + is_underline: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// blink property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Cyan.blink(); + /// println!("{}", style.paint("wazzup")); + /// ``` + pub fn blink(self) -> Style { + Style { + foreground: Some(self), + is_blink: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// reverse property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Black.reverse(); + /// println!("{}", style.paint("aloha")); + /// ``` + pub fn reverse(self) -> Style { + Style { + foreground: Some(self), + is_reverse: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// hidden property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::White.hidden(); + /// println!("{}", style.paint("ahoy")); + /// ``` + pub fn hidden(self) -> Style { + Style { + foreground: Some(self), + is_hidden: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// strikethrough property set. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::Fixed(244).strikethrough(); + /// println!("{}", style.paint("yo")); + /// ``` + pub fn strikethrough(self) -> Style { + Style { + foreground: Some(self), + is_strikethrough: true, + ..Style::default() + } + } + + /// Returns a `Style` with the foreground colour set to this colour and the + /// background colour property set to the given colour. + /// + /// # Examples + /// + /// ``` + /// use yansi_term::Colour; + /// + /// let style = Colour::RGB(31, 31, 31).on(Colour::White); + /// println!("{}", style.paint("eyyyy")); + /// ``` + pub fn on(self, background: Colour) -> Style { + Style { + foreground: Some(self), + background: Some(background), + ..Style::default() + } + } +} + +impl From<Colour> for Style { + /// You can turn a `Colour` into a `Style` with the foreground colour set + /// with the `From` trait. + /// + /// ``` + /// use yansi_term::{Style, Colour}; + /// let green_foreground = Style::default().fg(Colour::Green); + /// assert_eq!(green_foreground, Colour::Green.normal()); + /// assert_eq!(green_foreground, Colour::Green.into()); + /// assert_eq!(green_foreground, Style::from(Colour::Green)); + /// ``` + fn from(colour: Colour) -> Style { + colour.normal() + } +} + +#[cfg(test)] +#[cfg(feature = "derive_serde_style")] +mod serde_json_tests { + use super::{Colour, Style}; + + #[test] + fn colour_serialization() { + let colours = &[ + Colour::Red, + Colour::Blue, + Colour::RGB(123, 123, 123), + Colour::Fixed(255), + ]; + + assert_eq!( + serde_json::to_string(&colours).unwrap(), + String::from("[\"Red\",\"Blue\",{\"RGB\":[123,123,123]},{\"Fixed\":255}]") + ); + } + + #[test] + fn colour_deserialization() { + let colours = &[ + Colour::Red, + Colour::Blue, + Colour::RGB(123, 123, 123), + Colour::Fixed(255), + ]; + + for colour in colours { + let serialized = serde_json::to_string(&colour).unwrap(); + let deserialized: Colour = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(colour, &deserialized); + } + } + + #[test] + fn style_serialization() { + let style = Style::default(); + + assert_eq!(serde_json::to_string(&style).unwrap(), "{\"foreground\":null,\"background\":null,\"is_bold\":false,\"is_dimmed\":false,\"is_italic\":false,\"is_underline\":false,\"is_blink\":false,\"is_reverse\":false,\"is_hidden\":false,\"is_strikethrough\":false}".to_string()); + } +} diff --git a/vendor/yansi-term/src/windows.rs b/vendor/yansi-term/src/windows.rs new file mode 100644 index 000000000..3df9ff4ac --- /dev/null +++ b/vendor/yansi-term/src/windows.rs @@ -0,0 +1,61 @@ +/// Enables ANSI code support on Windows 10. +/// +/// This uses Windows API calls to alter the properties of the console that +/// the program is running in. +/// +/// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx +/// +/// Returns a `Result` with the Windows error code if unsuccessful. +#[cfg(windows)] +pub fn enable_ansi_support() -> Result<(), u32> { + // ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76% + + use std::{ffi::OsStr, iter::once, os::windows::ffi::OsStrExt, ptr::null_mut}; + use winapi::um::{ + consoleapi::{GetConsoleMode, SetConsoleMode}, + errhandlingapi::GetLastError, + fileapi::{CreateFileW, OPEN_EXISTING}, + handleapi::INVALID_HANDLE_VALUE, + winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}, + }; + + const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004; + + unsafe { + // ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew + // Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected + let console_out_name: Vec<u16> = + OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect(); + let console_handle = CreateFileW( + console_out_name.as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, + null_mut(), + OPEN_EXISTING, + 0, + null_mut(), + ); + if console_handle == INVALID_HANDLE_VALUE { + return Err(GetLastError()); + } + + // ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode + let mut console_mode: u32 = 0; + if 0 == GetConsoleMode(console_handle, &mut console_mode) { + return Err(GetLastError()); + } + + // VT processing not already enabled? + if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 { + // https://docs.microsoft.com/en-us/windows/console/setconsolemode + if 0 == SetConsoleMode( + console_handle, + console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING, + ) { + return Err(GetLastError()); + } + } + } + + return Ok(()); +} |