From c37a480f78c8c1ca020271ae6902d453122955e9 Mon Sep 17 00:00:00 2001 From: Timon Date: Fri, 22 Feb 2019 15:20:24 +0100 Subject: [PATCH] Improved Styling (#92) --- Cargo.toml | 12 +- README.md | 7 +- crossterm_cursor/Cargo.toml | 4 +- crossterm_input/Cargo.toml | 4 +- crossterm_screen/Cargo.toml | 4 +- crossterm_style/CHANGELOG.md | 7 + crossterm_style/Cargo.toml | 6 +- crossterm_style/README.md | 60 ++-- crossterm_style/examples/style.rs | 397 +++++++++++++++++-------- crossterm_style/src/ansi_color.rs | 29 +- crossterm_style/src/color.rs | 2 +- crossterm_style/src/enums/attribute.rs | 143 +++++++++ crossterm_style/src/enums/color.rs | 81 +++++ crossterm_style/src/enums/colored.rs | 45 +++ crossterm_style/src/enums/mod.rs | 5 + crossterm_style/src/lib.rs | 170 ++++------- crossterm_style/src/macros.rs | 50 ++++ crossterm_style/src/styledobject.rs | 111 ++++--- crossterm_style/src/traits.rs | 72 +++++ crossterm_style/src/winapi_color.rs | 14 +- crossterm_terminal/Cargo.toml | 6 +- crossterm_utils/Cargo.toml | 2 +- docs/{ReleaseNotes.md => CHANGELOG.md} | 0 docs/{UpgradeManual.md => UPGRADE.md} | 0 docs/mdbook/src/styling.md | 50 ++-- docs/mdbook/src/styling_example.md | 92 +++--- examples/style.rs | 6 - 27 files changed, 952 insertions(+), 427 deletions(-) create mode 100644 crossterm_style/CHANGELOG.md create mode 100644 crossterm_style/src/enums/attribute.rs create mode 100644 crossterm_style/src/enums/color.rs create mode 100644 crossterm_style/src/enums/colored.rs create mode 100644 crossterm_style/src/enums/mod.rs create mode 100644 crossterm_style/src/macros.rs create mode 100644 crossterm_style/src/traits.rs rename docs/{ReleaseNotes.md => CHANGELOG.md} (100%) rename docs/{UpgradeManual.md => UPGRADE.md} (100%) diff --git a/Cargo.toml b/Cargo.toml index 4a6957a..0cf67d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,12 +32,12 @@ members = [ ] [dependencies] -crossterm_screen = { path = "./crossterm_screen", optional = true, version = "0.1.0" } -crossterm_cursor = { path = "./crossterm_cursor", optional = true, version = "0.1.0" } -crossterm_terminal = { path = "./crossterm_terminal", optional = true, version = "0.1.0" } -crossterm_style = { path = "./crossterm_style", optional = true, version = "0.1.0" } -crossterm_input = { path = "./crossterm_input", optional = true, version = "0.1.0" } -crossterm_utils = { path = "./crossterm_utils", version = "0.1.0" } +crossterm_screen = { optional = true, version = "0.1.0" } +crossterm_cursor = { optional = true, version = "0.1.0" } +crossterm_terminal = { optional = true, version = "0.1.0" } +crossterm_style = { optional = true, version = "0.1.0" } +crossterm_input = { optional = true, version = "0.1.0" } +crossterm_utils = { version = "0.1.0" } [lib] name = "crossterm" diff --git a/README.md b/README.md index ac4c191..5a325b5 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,9 @@ println!("{}", crossterm.style("Black font on Green background color").with(Colo ``` ### Styled Font | [see more](http://atcentra.com/crossterm/styling.html) This module provides the functionalities to style the terminal. + +**[crossterm_style](https://github.com/TimonPost/crossterm/tree/master/crossterm_style) 0.2 has a new way to style the terminal more easily and will be usable in crossterm soon. +If you only use the styling you might want to use that crate.** ```rust use crossterm::{Color, style}; @@ -258,7 +261,7 @@ If you have used this library for a terminal other than the above list without i ## Notice This library is average stable now but I don't expect it to not to change that much. -If there are any changes that will affect previous versions I will [describe](https://github.com/TimonPost/crossterm/blob/master/docs/UpgradeManual.md) what to change to upgrade. +If there are any changes that will affect previous versions I will [describe](https://github.com/TimonPost/crossterm/blob/master/docs/UPGRADE.md) what to change to upgrade. ## Todo I still have some things in mind to implement. @@ -284,4 +287,4 @@ Check [Contributing](https://github.com/TimonPost/crossterm/blob/master/docs/Con ## License -This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/TimonPost/crossterm/blob/master/LICENSE) file for details +This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/TimonPost/crossterm/blob/master/LICENSE) file for details \ No newline at end of file diff --git a/crossterm_cursor/Cargo.toml b/crossterm_cursor/Cargo.toml index 542e775..e6303d4 100644 --- a/crossterm_cursor/Cargo.toml +++ b/crossterm_cursor/Cargo.toml @@ -13,10 +13,10 @@ edition = "2018" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.5", features = ["wincon","winnt","minwindef"] } -crossterm_winapi = { path = "../crossterm_winapi" } +crossterm_winapi = "0.1.1" [dependencies] -crossterm_utils = { path = "../crossterm_utils" } +crossterm_utils = "0.1.0" [[example]] name = "cursor" diff --git a/crossterm_input/Cargo.toml b/crossterm_input/Cargo.toml index 6f495d6..157d5d7 100644 --- a/crossterm_input/Cargo.toml +++ b/crossterm_input/Cargo.toml @@ -13,13 +13,13 @@ edition = "2018" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.5", features = ["winnt"] } -crossterm_winapi = { path = "../crossterm_winapi" } +crossterm_winapi = "0.1.1" [target.'cfg(unix)'.dependencies] libc = "0.2.43" [dependencies] -crossterm_utils = { path = "../crossterm_utils" } +crossterm_utils = "0.1.0" [[example]] name = "input" diff --git a/crossterm_screen/Cargo.toml b/crossterm_screen/Cargo.toml index 0f275a1..69391d3 100644 --- a/crossterm_screen/Cargo.toml +++ b/crossterm_screen/Cargo.toml @@ -12,8 +12,8 @@ readme = "README.md" edition = "2018" [dependencies] -crossterm_utils = { path = "../crossterm_utils" } +crossterm_utils = "0.1.0" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.5", features = ["minwindef", "wincon"] } -crossterm_winapi = { path = "../crossterm_winapi" } \ No newline at end of file +crossterm_winapi = "0.1.1" \ No newline at end of file diff --git a/crossterm_style/CHANGELOG.md b/crossterm_style/CHANGELOG.md new file mode 100644 index 0000000..0a8ff51 --- /dev/null +++ b/crossterm_style/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changes crossterm_style 0.2 +- Introduced more `Attributes` +- Introduced easier ways to style text [issue 87](https://github.com/TimonPost/crossterm/issues/87). +- Removed `ColorType` since it was unnecessary. + +# Changes crossterm_style 0.1 +- Moved out of `crossterm` 5.4 crate. \ No newline at end of file diff --git a/crossterm_style/Cargo.toml b/crossterm_style/Cargo.toml index 854b156..e30eddc 100644 --- a/crossterm_style/Cargo.toml +++ b/crossterm_style/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "crossterm_style" -version = "0.1.0" +version = "0.2.0" authors = ["T. Post"] description = "A cross-platform library styling the terminal output." repository = "https://github.com/TimonPost/crossterm" @@ -13,10 +13,10 @@ edition = "2018" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.5", features = ["wincon"] } -crossterm_winapi = { path = "../crossterm_winapi" } +crossterm_winapi = "0.1.1" [dependencies] -crossterm_utils = { path = "../crossterm_utils" } +crossterm_utils = "0.1.0" [[example]] name = "style" diff --git a/crossterm_style/README.md b/crossterm_style/README.md index 713be75..3a5b558 100644 --- a/crossterm_style/README.md +++ b/crossterm_style/README.md @@ -80,46 +80,50 @@ These are the features of this crate: - RGB support (Windows 10 and UNIX only) - Text Attributes like: bold, italic, underscore and crossed word ect (Windows 10 and UNIX only) -Planned features: -- Easier usage; e.g. `println!("{}Bold{}Blue", Attribute::Bold, Color::Blue)` - ## Examples Check out the [examples](/examples/) for more information about how to use this crate. -```rust -use crossterm::style::{Color, style}; -// store objcets so it could be painted later to the screen. -let style1 = style("Some Blue font on Black background").with(Color::Blue).on(Color::Black); -let style2 = style("Some Red font on Yellow background").with(Color::Red).on(Color::Yellow); +_style font with attributes_ +```rust +use crossterm_style::{Colored, Color, Colorize, Styler, Attribute}; -// syling font with (Windows 10 and UNIX systems) -let normal = style("Normal text"); -let bold = style("Bold text").bold(); -let italic = style("Italic text").italic(); -let slow_blink = style("Slow blinking text").slow_blink(); -let rapid_blink = style("Rapid blinking text").rapid_blink(); -let hidden = style("Hidden text").hidden(); -let underlined = style("Underlined text").underlined(); -let reversed = style("Reversed text").reverse(); -let dimmed = style("Dim text").dim(); -let crossed_out = style("Crossed out font").crossed_out(); +// pass any `Attribute` value to the formatting braces. +println!("{} Underlined {} No Underline", Attribute::Underlined, Attribute::NoUnderline); -// paint styled text to screen (this could also be called inline) -println!("{}", style1); -println!("{}", style2); -println!("{}", bold); -println!("{}", hidden); -... +// you could also call different attribute methods on a `&str` and keep on chaining if needed. +let styled_text = "Bold Underlined".bold().underlined(); +println!("{}", styled_text); -// cursom rgb value (Windows 10 and UNIX systems) -style("RGB color (10,10,10) ").with(Color::Rgb { +// old-way but still usable +let styled_text = style("Bold Underlined").bold().underlined(); +``` + +_style font with colors_ +```rust +use crossterm_style::{Colored, Color, Colorize}; + + +println!("{} Red foreground color", Colored::Fg(Color::Red)); +println!("{} Blue background color", Colored::Bg(Color::Blue)); + +// you can also call different coloring methods on a `&str`. +let styled_text = "Bold Underlined".red().on_blue(); +println!("{}", styled_text); + +// old-way but still usable +let styled_text = style("Bold Underlined").with(Color::Red).on(Color::Blue); +``` +_style font with RGB and ANSI Value_ +```rust +// custom rgb value (Windows 10 and UNIX systems) +println!("{} some colored text", Colored::Fg(Color::Rgb { r: 10, g: 10, b: 10 })); // custom ansi color value (Windows 10 and UNIX systems) -style("ANSI color value (50) ").with(Color::AnsiValue(50)); +println!("{} some colored text", Colored::Fg(Color::AnsiValue(10))); ``` ## Tested terminals diff --git a/crossterm_style/examples/style.rs b/crossterm_style/examples/style.rs index a6c308e..9d614b2 100644 --- a/crossterm_style/examples/style.rs +++ b/crossterm_style/examples/style.rs @@ -1,220 +1,382 @@ //! //! Examples of coloring the terminal. //! +#[macro_use] extern crate crossterm_style; -use self::crossterm_style::{color, style, Color}; +use self::crossterm_style::{ + color, style, Attribute, Color, Colored, Colorize, Styler, TerminalColor, +}; /// print some red font | demonstration. pub fn paint_foreground() { - // Create a styled object. - // Call the method `with()` on the object given by `style()` and pass in any Color from the Color enum. - let styledobject = style("Red foreground").with(Color::Red); - - // Print the object to the given screen and. - println!("Colored text: {}", styledobject); - - // Or print inline - println!( - "Colored text: {}", - style("Blue foreground").with(Color::Blue) - ); + println!("{}", "Red foreground text: {}".red()); + println!("{} Red foreground text", Colored::Fg(Color::Red)); } /// print some font on red background | demonstration. pub fn paint_background() { - // Create a styled object. - // Call the method `with()` on the object given by `style()` and pass in any Color from the Color enum. - let styledobject = style("Red foreground").on(Color::Red); - - // Print the object to the given screen and. - println!("Colored text: {}", styledobject); - - // Or print inline - println!("Colored text: {}", style("Red foreground").on(Color::Blue)); + println!("{}", "Red background text: {}".on_red()); + println!("{} Red background text", Colored::Bg(Color::Red)); } /// Print all available foreground colors | demonstration. -pub fn print_all_foreground_colors() { +pub fn print_all_foreground_colors_with_enum() { + // we use `Reset` to restore the foreground back to normal at the end of the line. println!( - "{}", - style(format!("Black : \t\t {} \n", "■")).with(Color::Black) + "Black : \t\t {} ■ {}\n", + Colored::Fg(Color::Black), + Attribute::Reset ); println!( - "{}", - style(format!("Red : \t\t {} \n", "■")).with(Color::Red) + "Red : \t\t {} ■ {}\n", + Colored::Fg(Color::Red), + Attribute::Reset ); println!( - "{}", - style(format!("Cyan : \t\t {} \n", "■")).with(Color::Cyan) + "DarkRed : \t\t {} ■ {}\n", + Colored::Fg(Color::DarkRed), + Attribute::Reset ); println!( - "{}", - style(format!("DarkCyan : \t {} \n", "■")).with(Color::DarkCyan) + "Cyan : \t\t {} ■ {}\n", + Colored::Fg(Color::Cyan), + Attribute::Reset ); println!( - "{}", - style(format!("DarkRed : \t {} \n", "■")).with(Color::DarkRed) + "DarkCyan : \t\t {} ■ {}\n", + Colored::Fg(Color::DarkCyan), + Attribute::Reset ); println!( - "{}", - style(format!("Green : \t {} \n", "■")).with(Color::Green) + "Green : \t\t {} ■ {}\n", + Colored::Fg(Color::Green), + Attribute::Reset ); println!( - "{}", - style(format!("DarkGreen : \t {} \n", "■")).with(Color::DarkGreen) + "DarkGreen : \t\t {} ■ {}\n", + Colored::Fg(Color::DarkGreen), + Attribute::Reset ); println!( - "{}", - style(format!("Blue : \t\t {} \n", "■")).with(Color::Blue) + "Blue : \t\t {} ■ {}\n", + Colored::Fg(Color::Blue), + Attribute::Reset ); println!( - "{}", - style(format!("DarkBlue : \t {} \n", "■")).with(Color::DarkBlue) + "DarkBlue : \t\t {} ■ {}\n", + Colored::Fg(Color::DarkBlue), + Attribute::Reset ); println!( - "{}", - style(format!("Magenta : \t {} \n", "■")).with(Color::Magenta) + "Magenta : \t\t {} ■ {}\n", + Colored::Fg(Color::Magenta), + Attribute::Reset ); println!( - "{}", - style(format!("DarkMagenta : \t {} \n", "■")).with(Color::DarkMagenta) + "DarkMagenta : \t\t{} ■ {}\n", + Colored::Fg(Color::DarkMagenta), + Attribute::Reset ); println!( - "{}", - style(format!("Yellow : \t {} \n", "■")).with(Color::Yellow) + "Yellow : \t\t {} ■ {}\n", + Colored::Fg(Color::Yellow), + Attribute::Reset ); println!( - "{}", - style(format!("DarkYellow : \t {} \n", "■")).with(Color::DarkYellow) + "DarkYellow : \t\t {} ■ {}\n", + Colored::Fg(Color::DarkYellow), + Attribute::Reset ); println!( - "{}", - style(format!("Grey : \t\t {} \n", "■")).with(Color::Grey) + "Grey : \t\t {} ■ {}\n", + Colored::Fg(Color::Grey), + Attribute::Reset ); println!( - "{}", - style(format!("White : \t {} \n", "■")).with(Color::White) + "White : \t\t {} ■ {}\n", + Colored::Fg(Color::White), + Attribute::Reset ); - // supported by Unix and < Windows 10 terminals + // custom rgb value (Windows 10 and UNIX systems) println!( - "{}", - style("RGB color (10,10,10) ").with(Color::Rgb { + "{} some colored text", + Colored::Fg(Color::Rgb { r: 10, g: 10, b: 10 }) ); - // supported by Unix and < Windows 10 terminals + // custom ansi color value (Windows 10 and UNIX systems) + println!("{} some colored text", Colored::Fg(Color::AnsiValue(10))); +} + +/// Print all available foreground colors | demonstration. +pub fn print_all_foreground_colors_with_method() { println!( - "{}", - style("RGB color (10,10,10) ").with(Color::AnsiValue(50)) + "Black : \t\t {} {}\n", + "■".black(), + Attribute::Reset + ); + println!("Red : \t\t {} {}\n", "■".red(), Attribute::Reset); + println!( + "DarkRed : \t\t {} {}\n", + "■".dark_red(), + Attribute::Reset + ); + println!("Cyan : \t\t {} {}\n", "■".cyan(), Attribute::Reset); + println!( + "DarkCyan : \t\t {} {}\n", + "■".dark_cyan(), + Attribute::Reset + ); + println!( + "Green : \t\t {} {}\n", + "■".green(), + Attribute::Reset + ); + println!( + "DarkGreen : \t\t {} {}\n", + "■".dark_green(), + Attribute::Reset + ); + println!("Blue : \t\t {} {}\n", "■".blue(), Attribute::Reset); + println!( + "DarkBlue : \t\t {} {}\n", + "■".dark_blue(), + Attribute::Reset + ); + println!( + "Magenta : \t\t {} {}\n", + "■".magenta(), + Attribute::Reset + ); + println!( + "DarkMagenta : \t\t {} {}\n", + "■".dark_magenta(), + Attribute::Reset + ); + println!( + "Yellow : \t\t {} {}\n", + "■".yellow(), + Attribute::Reset + ); + println!( + "DarkYellow : \t\t {} {}\n", + "■".dark_yellow(), + Attribute::Reset + ); + println!("Grey : \t\t {} {}\n", "■".grey(), Attribute::Reset); + println!( + "White : \t\t {} {}\n", + "■".white(), + Attribute::Reset ); } /// Print all available foreground colors | demonstration. -pub fn print_all_background_colors() { +pub fn print_all_background_colors_with_enum() { println!( - "{}", - style(format!("Black : \t {} \n", "■")).on(Color::Black) + "Black : \t\t {} ■ {}\n", + Colored::Bg(Color::Black), + Attribute::Reset ); println!( - "{}", - style(format!("Red : \t\t {} \n", "■")).on(Color::Red) + "Red : \t\t {} ■ {}\n", + Colored::Bg(Color::Red), + Attribute::Reset ); println!( - "{}", - style(format!("Cyan : \t\t {} \n", "■")).on(Color::Cyan) + "DarkRed : \t\t {} ■ {}\n", + Colored::Bg(Color::DarkRed), + Attribute::Reset ); println!( - "{}", - style(format!("DarkCyan : \t {} \n", "■")).on(Color::DarkCyan) + "Cyan : \t\t {} ■ {}\n", + Colored::Bg(Color::Cyan), + Attribute::Reset ); println!( - "{}", - style(format!("DarkRed : \t {} \n", "■")).on(Color::DarkRed) + "DarkCyan : \t\t {} ■ {}\n", + Colored::Bg(Color::DarkCyan), + Attribute::Reset ); println!( - "{}", - style(format!("Green : \t {} \n", "■")).on(Color::Green) + "Green : \t\t {} ■ {}\n", + Colored::Bg(Color::Green), + Attribute::Reset ); println!( - "{}", - style(format!("DarkGreen : \t {} \n", "■")).on(Color::DarkGreen) + "DarkGreen : \t\t {} ■ {}\n", + Colored::Bg(Color::DarkGreen), + Attribute::Reset ); println!( - "{}", - style(format!("Blue : \t\t {} \n", "■")).on(Color::Blue) + "Blue : \t\t {} ■ {}\n", + Colored::Bg(Color::Blue), + Attribute::Reset ); println!( - "{}", - style(format!("DarkBlue : \t {} \n", "■")).on(Color::DarkBlue) + "DarkBlue : \t\t {} ■ {}\n", + Colored::Bg(Color::DarkBlue), + Attribute::Reset ); println!( - "{}", - style(format!("Magenta : \t {} \n", "■")).on(Color::Magenta) + "Magenta : \t\t {} ■ {}\n", + Colored::Bg(Color::Magenta), + Attribute::Reset ); println!( - "{}", - style(format!("DarkMagenta : \t {} \n", "■")).on(Color::DarkMagenta) + "DarkMagenta : \t\t{} ■ {}\n", + Colored::Bg(Color::DarkMagenta), + Attribute::Reset ); println!( - "{}", - style(format!("Yellow : \t {} \n", "■")).on(Color::Yellow) + "Yellow : \t\t {} ■ {}\n", + Colored::Bg(Color::Yellow), + Attribute::Reset ); println!( - "{}", - style(format!("DarkYellow : \t {} \n", "■")).on(Color::DarkYellow) + "DarkYellow : \t\t {} ■ {}\n", + Colored::Bg(Color::DarkYellow), + Attribute::Reset ); println!( - "{}", - style(format!("Grey : \t\t {} \n", "■")).on(Color::Grey) + "Grey : \t\t {} ■ {}\n", + Colored::Bg(Color::Grey), + Attribute::Reset ); println!( - "{}", - style(format!("White : \t {} \n", "■")).on(Color::White) + "White : \t\t {} ■ {}\n", + Colored::Bg(Color::White), + Attribute::Reset ); - // supported by Unix and < Windows 10 terminals + // custom rgb value (Windows 10 and UNIX systems) println!( - "{}", - style("RGB color (10,10,10) ").on(Color::Rgb { - r: 10, + "{} some colored text", + Colored::Bg(Color::Rgb { + r: 80, g: 10, b: 10 }) ); - // supported by Unix and < Windows 10 terminals + + // custom ansi color value (Windows 10 and UNIX systems) + println!("{} some colored text", Colored::Bg(Color::AnsiValue(10))); +} + +/// Print all available foreground colors | demonstration. +pub fn print_all_background_colors_with_method() { println!( - "{}", - style("RGB color (10,10,10) ").on(Color::AnsiValue(50)) + "Black : \t\t {} {}\n", + "■".on_black(), + Attribute::Reset + ); + println!( + "Red : \t\t {} {}\n", + "■".on_red(), + Attribute::Reset + ); + println!( + "DarkRed : \t\t {} {}\n", + "■".on_dark_red(), + Attribute::Reset + ); + println!( + "Cyan : \t\t {} {}\n", + "■".on_cyan(), + Attribute::Reset + ); + println!( + "DarkCyan : \t\t {} {}\n", + "■".on_dark_cyan(), + Attribute::Reset + ); + println!( + "Green : \t\t {} {}\n", + "■".on_green(), + Attribute::Reset + ); + println!( + "DarkGreen : \t\t {} {}\n", + "■".on_dark_green(), + Attribute::Reset + ); + println!( + "Blue : \t\t {} {}\n", + "■".on_blue(), + Attribute::Reset + ); + println!( + "DarkBlue : \t\t {} {}\n", + "■".on_dark_blue(), + Attribute::Reset + ); + println!( + "Magenta : \t\t {} {}\n", + "■".on_magenta(), + Attribute::Reset + ); + println!( + "DarkMagenta : \t\t {} {}\n", + "■".on_dark_magenta(), + Attribute::Reset + ); + println!( + "Yellow : \t\t {} {}\n", + "■".on_yellow(), + Attribute::Reset + ); + println!( + "DarkYellow : \t\t {} {}\n", + "■".on_dark_yellow(), + Attribute::Reset + ); + println!( + "Grey : \t\t {} {}\n", + "■".on_grey(), + Attribute::Reset + ); + println!( + "White : \t\t {} {}\n", + "■".on_white(), + Attribute::Reset ); } /// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration.. #[cfg(unix)] pub fn print_font_with_attributes() { - println!("{}", style("Normal text")); - println!("{}", style("Bold text").bold()); - println!("{}", style("Italic text").italic()); - println!("{}", style("Slow blinking text").slow_blink()); - println!("{}", style("Rapid blinking text").rapid_blink()); - println!("{}", style("Hidden text").hidden()); - println!("{}", style("Underlined text").underlined()); - println!("{}", style("Reversed text").reverse()); - println!("{}", style("Dim text").dim()); - println!("{}", style("Crossed out font").crossed_out()); + println!("{}", "Normal text"); + println!("{}", "Bold text".bold()); + println!("{}", "Italic text".italic()); + println!("{}", "Slow blinking text".slow_blink()); + println!("{}", "Rapid blinking text".rapid_blink()); + println!("{}", "Hidden text".hidden()); + println!("{}", "Underlined text".underlined()); + println!("{}", "Reversed text".reverse()); + println!("{}", "Dim text".dim()); + println!("{}", "Crossed out font".crossed_out()); + // ... + + println!( + "{} Underlined {} No Underline", + Attribute::Underlined, + Attribute::NoUnderline + ); + // ... } -/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration.. +// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely | demonstration.. #[cfg(windows)] pub fn print_font_with_attributes() { - println!("{}", style("Normal text")); - println!("{}", style("Bold text").bold()); - println!("{}", style("Underlined text").underlined()); - println!("{}", style("Negative text").negative()); + println!("{}", "Normal text"); + println!("{}", "Bold text".bold()); + println!("{}", "Underlined text".underlined()); + println!("{}", "Negative text".negative()); } /// Print all supported RGB colors, not supported for Windows systems < 10 | demonstration. @@ -222,15 +384,6 @@ pub fn print_supported_colors() { let count = color().get_available_color_count().unwrap(); for i in 0..count { - println!( - "{}", - style(format!("White : \t {}", i)).on(Color::AnsiValue(i as u8)) - ); + println!("Test {}", Colored::Bg(Color::AnsiValue(i as u8))); } } - -fn main() { - print_all_background_colors(); - print_all_foreground_colors(); - print_font_with_attributes(); -} diff --git a/crossterm_style/src/ansi_color.rs b/crossterm_style/src/ansi_color.rs index b1a867c..f7981fb 100644 --- a/crossterm_style/src/ansi_color.rs +++ b/crossterm_style/src/ansi_color.rs @@ -1,9 +1,10 @@ //! This is a ANSI specific implementation for styling related action. //! This module is used for Windows 10 terminals and Unix terminals by default. -use crate::{Color, ColorType, ITerminalColor}; +use crate::{Color, ITerminalColor}; use crossterm_utils::{write, write_str, Result, TerminalOutput}; +use crate::Colored; use std::sync::Arc; /// This struct is an ANSI escape code implementation for color related actions. @@ -19,10 +20,7 @@ impl ITerminalColor for AnsiColor { fn set_fg(&self, fg_color: Color, stdout: &Option<&Arc>) -> Result<()> { write( stdout, - format!( - csi!("{}m"), - self.color_value(fg_color, ColorType::Foreground) - ), + format!(csi!("{}m"), self.color_value(Colored::Fg(fg_color))), )?; Ok(()) } @@ -30,10 +28,7 @@ impl ITerminalColor for AnsiColor { fn set_bg(&self, bg_color: Color, stdout: &Option<&Arc>) -> Result<()> { write( stdout, - format!( - csi!("{}m"), - self.color_value(bg_color, ColorType::Background) - ), + format!(csi!("{}m"), self.color_value(Colored::Bg(bg_color))), )?; Ok(()) } @@ -43,12 +38,20 @@ impl ITerminalColor for AnsiColor { Ok(()) } - fn color_value(&self, color: Color, color_type: ColorType) -> String { + fn color_value(&self, colored: Colored) -> String { let mut ansi_value = String::new(); - match color_type { - ColorType::Foreground => ansi_value.push_str("38;"), - ColorType::Background => ansi_value.push_str("48;"), + let mut color = Color::White; + + match colored { + Colored::Fg(new_color) => { + ansi_value.push_str("38;"); + color = new_color; + } + Colored::Bg(new_color) => { + ansi_value.push_str("48;"); + color = new_color; + } } let rgb_val: String; diff --git a/crossterm_style/src/color.rs b/crossterm_style/src/color.rs index 7eeb266..07f2fba 100644 --- a/crossterm_style/src/color.rs +++ b/crossterm_style/src/color.rs @@ -102,9 +102,9 @@ impl<'stdout> TerminalColor<'stdout> { } /// Get available color count. + /// (This does not always provide a good result.) pub fn get_available_color_count(&self) -> io::Result { use std::env; - Ok(match env::var_os("TERM") { Some(val) => { if val.to_str().unwrap_or("").contains("256color") { diff --git a/crossterm_style/src/enums/attribute.rs b/crossterm_style/src/enums/attribute.rs new file mode 100644 index 0000000..bd0e0f0 --- /dev/null +++ b/crossterm_style/src/enums/attribute.rs @@ -0,0 +1,143 @@ +use std::fmt::Display; +use std::io::stdout; +use std::io::Write; + +/// These are all the attributes which **could** be apply to font. +/// There are few things to note +/// - Not all attributes are supported, some of them are only supported on Windows some only on Unix, +/// and some are only very rarely supported. +/// - I got those attributes, descriptions, supportability from here: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters +/// - Take note of the fact that when running your program cross-platform that some attributes might not work because of their support. +/// - When an attribute is not supported nothing will happen with the terminal state. +/// +/// # Example +/// You can use an attribute in a write statement to apply the attribute to the terminal output. +/// +/// ```rust +/// println!( +/// "{} Underlined {} No Underline", +/// Attribute::Underlined, +/// Attribute::NoUnderline +/// ); +/// ``` +/// +/// You can also call attribute functions on a `&'static str`: +/// ```rust +/// use crossterm(_style)::Colorizer; +/// +/// println!("{}", style("Bold text").bold()); +/// println!("{}", style("Underlined text").underlined()); +/// println!("{}", style("Negative text").negative()); +/// ``` +#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] +pub enum Attribute { + /// All attributes off + /// [info]: This will reset all current set attributes. + /// [Supportability]: Windows, UNIX. + Reset = 0, + /// Increased Intensity + /// [info]: This will increase the font sensitivity also known as bold. + /// [Supportability]: Windows, UNIX. + Bold = 1, + /// Decreased Intensity + /// [info]: This will decrease the font sensitivity also known as bold. + /// [Supportability]: Windows, UNIX. + Dim = 2, + /// Italic Text + /// [info]: This will make the font italic. + /// [Supportability]: Not widely supported, sometimes treated as inverse. + Italic = 3, + /// This will draw a line under the font. + /// [info]: An line under a word, especially in order to show its importance. + /// [Supportability]: Windows, UNIX + Underlined = 4, + /// Slow Blinking Text + /// [info]: Blink Less than 150 per minute. + /// [Supportability]: UNIX + SlowBlink = 5, + /// Slow Blinking Text + /// [info]: MS-DOS ANSI.SYS; 150+ per minute; + /// [Supportability]: Not widely supported + RapidBlink = 6, + /// Swap foreground and background colors + /// [info]: swap foreground and background colors + /// [Supportability]: Windows, UNIX + Reverse = 7, + /// Hide font + /// [info]: + /// - This will make the font hidden. + /// - Also known as 'Conceal' + /// [Supportability]: Windows, UNIX + Hidden = 8, + /// Cross-out font + /// [info]: Characters legible, but marked for deletion. + /// [Supportability]: UNIX + CrossedOut = 9, + /// The Fraktur is a typeface belonging to the group of Gothic typefaces. + /// [info]: https://nl.wikipedia.org/wiki/Fraktur + /// [Supportability]: Rarely supported + Fraktur = 20, + /// This will turn off the bold attribute. + /// [info]: + /// - Double-underline per ECMA-48. + /// - WikiPedia: https://en.wikipedia.org/wiki/Talk:ANSI_escape_code#SGR_21%E2%80%94%60Bold_off%60_not_widely_supported + /// - Opposite of `Bold`(1) + /// [Supportability]: not widely supported + NoBold = 21, + /// This will turn off the underline attribute. + /// [info]: + /// - Not singly or doubly underlined will be turned off. + /// - Opposite of `Underlined.`(4) + /// [Supportability]: Windows, UNIX + NoUnderline = 24, + /// This will turn off the blinking attribute + /// [info]: Opposite of `Slow and Rapid blink.`(5,6) + /// [Supportability]: Unknown + NoBlink = 25, + /// This will turn off the reverse attribute. + /// [info]: Opposite of `Reverse`(7) + /// [Supportability]: Windows, unknown + NoInverse = 27, + /// This will make the font visible. + /// [info]: Opposite of `Hidden`(8) + /// [Supportability]: Unknown + NoHidden = 28, + /// This will turn off the crossed out attribute. + /// [info]: Opposite of `CrossedOut`(9) + /// [Supportability]: Not widely supported + NotCrossedOut = 29, + /// This will reset the foreground color to default. + /// [info]: Implementation defined (according to standard) + /// [Supportability]: Unknown + DefaultForegroundColor = 48, + /// This will reset the background color to default. + /// [info]: Implementation defined (according to standard) + /// [Supportability]: Unknown + DefaultBackgroundColor = 49, + /// Framed font. + /// [Supportability]: Not widely supported + Framed = 51, + /// This will turn on the encircled attribute. + Encircled = 52, + /// This will draw a line at the top of the font. + /// [info]: Implementation defined (according to standard) + /// [Supportability]: Unknown + OverLined = 53, + /// This will turn off the framed or encircled attribute. + NotFramedOrEncircled = 54, + /// This will turn off the overLined attribute. + /// [info]: Opposite of `OverLined`(7) + /// [Supportability]: Windows, unknown + NotOverLined = 55, + + #[doc(hidden)] + __Nonexhaustive, +} + +impl Display for Attribute { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { + write!(f, "{}", format!(csi!("{}m"), *self as i16))?; + stdout().flush(); + Ok(()) + } +} diff --git a/crossterm_style/src/enums/color.rs b/crossterm_style/src/enums/color.rs new file mode 100644 index 0000000..dad522a --- /dev/null +++ b/crossterm_style/src/enums/color.rs @@ -0,0 +1,81 @@ +use std::convert::AsRef; +use std::str::FromStr; + +/// Colors that are available for coloring the terminal font. +#[derive(Debug, Copy, Clone)] +pub enum Color { + Black, + + Red, + DarkRed, + + Green, + DarkGreen, + + Yellow, + DarkYellow, + + Blue, + DarkBlue, + + Magenta, + DarkMagenta, + + Cyan, + DarkCyan, + + Grey, + White, + /// Color representing RGB-colors; + /// r = red + /// g = green + /// b = blue + Rgb { + r: u8, + g: u8, + b: u8, + }, + AnsiValue(u8), +} + +impl<'a> From<&'a str> for Color { + /// Get an color from an &str like `Color::from("blue")`. + fn from(src: &str) -> Self { + src.parse().unwrap_or(Color::White) + } +} + +impl From for Color { + /// Get an color from an &str like `Color::from(String::from(blue))`. + fn from(src: String) -> Self { + src.parse().unwrap_or(Color::White) + } +} + +impl FromStr for Color { + type Err = (); + + /// Convert a string to an Color value + fn from_str(src: &str) -> ::std::result::Result { + let src = src.to_lowercase(); + + match src.as_ref() { + "black" => Ok(Color::Black), + "red" => Ok(Color::Red), + "dark_red" => Ok(Color::DarkRed), + "green" => Ok(Color::Green), + "dark_green" => Ok(Color::DarkGreen), + "yellow" => Ok(Color::Yellow), + "dark_yellow" => Ok(Color::DarkYellow), + "blue" => Ok(Color::Blue), + "dark_blue" => Ok(Color::DarkBlue), + "magenta" => Ok(Color::Magenta), + "dark_magenta" => Ok(Color::DarkMagenta), + "cyan" => Ok(Color::Cyan), + "dark_cyan" => Ok(Color::DarkCyan), + "grey" => Ok(Color::Grey), + "white" => Ok(Color::White), + _ => Ok(Color::White), + } + } +} diff --git a/crossterm_style/src/enums/colored.rs b/crossterm_style/src/enums/colored.rs new file mode 100644 index 0000000..a3f5c47 --- /dev/null +++ b/crossterm_style/src/enums/colored.rs @@ -0,0 +1,45 @@ +use crate::color::color; +use crate::enums::Color; +use std::fmt::Display; + +/// Could be used to color the foreground or background color. +/// +/// `Colored::Fg` represents the foreground color. +/// `Color::Bg` represents the background color. +/// +/// # Example +/// +/// You can use `Colored` in a write statement to apply the attribute to the terminal output. +/// +/// ```rust +/// println!("{} Red foreground color", Colored::Fg(Color::Red)); +/// println!("{} Blue background color", Colored::Bg(Color::Blue)); +/// ``` +/// +/// You can also call coloring functions on a `&'static str`: +/// ```rust +/// use crossterm(_style)::Colorizer; +/// let styled_text = "Red forground color on blue background.".red().on_blue(); +/// println!("{}", styled_text); +/// ``` +pub enum Colored { + Fg(Color), + Bg(Color), +} + +impl Display for Colored { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> { + let colored_terminal = color(); + + match *self { + Colored::Fg(color) => { + colored_terminal.set_fg(color); + } + Colored::Bg(color) => { + colored_terminal.set_bg(color); + } + } + + Ok(()) + } +} diff --git a/crossterm_style/src/enums/mod.rs b/crossterm_style/src/enums/mod.rs new file mode 100644 index 0000000..683c76c --- /dev/null +++ b/crossterm_style/src/enums/mod.rs @@ -0,0 +1,5 @@ +mod attribute; +mod color; +mod colored; + +pub use self::{attribute::Attribute, color::Color, colored::Colored}; diff --git a/crossterm_style/src/lib.rs b/crossterm_style/src/lib.rs index eeadd9a..bdd18dc 100644 --- a/crossterm_style/src/lib.rs +++ b/crossterm_style/src/lib.rs @@ -6,9 +6,13 @@ extern crate crossterm_utils; #[cfg(target_os = "windows")] extern crate crossterm_winapi; +#[macro_use] +mod macros; mod color; +mod enums; pub mod objectstyle; pub mod styledobject; +mod traits; mod ansi_color; #[cfg(target_os = "windows")] @@ -24,10 +28,14 @@ use std::str::FromStr; use std::sync::Arc; pub use self::color::{color, TerminalColor}; +pub use self::enums::{Attribute, Color, Colored}; pub use self::objectstyle::ObjectStyle; pub use self::styledobject::DisplayableObject; pub use self::styledobject::StyledObject; +pub use self::traits::{Colorize, Styler}; use crossterm_utils::{Result, TerminalOutput}; +use std::io::stdout; +use std::io::Write; /// This trait defines the actions that can be preformed with terminal color. /// This trait can be implemented so that a concrete implementation of the ITerminalColor can fulfill @@ -45,7 +53,7 @@ trait ITerminalColor { /// Reset the terminal color to default. fn reset(&self, stdout: &Option<&Arc>) -> Result<()>; /// Gets an value that represents an color from the given `Color` and `ColorType`. - fn color_value(&self, color: Color, color_type: ColorType) -> String; + fn color_value(&self, cored: Colored) -> String; } /// This could be used to style a type who is implementing `Display` with colors and attributes. @@ -63,6 +71,11 @@ trait ITerminalColor { /// println!("{}", styled_object); /// } /// ``` +/// +/// # Important Remark +/// +/// - Please checkout the documentation for `Colorizer` or `Styler`. +/// Those types will make it a bit easier to style a string. pub fn style<'a, D: 'a>(val: D) -> StyledObject where D: Display, @@ -70,115 +83,52 @@ where ObjectStyle::new().apply_to(val) } -/// Attributes that could be applied on some text. (*nix values) -#[cfg(unix)] -#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] -pub enum Attribute { - Bold = 1, - Dim = 2, - Italic = 3, - Underlined = 4, - SlowBlink = 5, - RapidBlink = 6, - Reverse = 7, - Hidden = 8, - CrossedOut = 9, +impl Colorize<&'static str> for &'static str { + // foreground colors + def_str_color!(fg_color: black => Color::Black); + def_str_color!(fg_color: red => Color::Red); + def_str_color!(fg_color: dark_red => Color::DarkRed); + def_str_color!(fg_color: green => Color::Green); + def_str_color!(fg_color: dark_green => Color::DarkGreen); + def_str_color!(fg_color: yellow => Color::Yellow); + def_str_color!(fg_color: dark_yellow => Color::DarkYellow); + def_str_color!(fg_color: blue => Color::Blue); + def_str_color!(fg_color: dark_blue => Color::DarkBlue); + def_str_color!(fg_color: magenta => Color::Magenta); + def_str_color!(fg_color: dark_magenta => Color::DarkMagenta); + def_str_color!(fg_color: cyan => Color::Cyan); + def_str_color!(fg_color: dark_cyan => Color::DarkCyan); + def_str_color!(fg_color: white => Color::White); + def_str_color!(fg_color: grey => Color::Grey); + + // background colors + def_str_color!(bg_color: on_black => Color::Black); + def_str_color!(bg_color: on_red => Color::Red); + def_str_color!(bg_color: on_dark_red => Color::DarkRed); + def_str_color!(bg_color: on_green => Color::Green); + def_str_color!(bg_color: on_dark_green => Color::DarkGreen); + def_str_color!(bg_color: on_yellow => Color::Yellow); + def_str_color!(bg_color: on_dark_yellow => Color::DarkYellow); + def_str_color!(bg_color: on_blue => Color::Blue); + def_str_color!(bg_color: on_dark_blue => Color::DarkBlue); + def_str_color!(bg_color: on_magenta => Color::Magenta); + def_str_color!(bg_color: on_dark_magenta => Color::DarkMagenta); + def_str_color!(bg_color: on_cyan => Color::Cyan); + def_str_color!(bg_color: on_dark_cyan => Color::DarkCyan); + def_str_color!(bg_color: on_white => Color::White); + def_str_color!(bg_color: on_grey => Color::Grey); } -/// Attributes that could be applied on some text. (Windows specific) -#[cfg(windows)] -#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] -pub enum Attribute { - Reset = 0, - Bold = 1, - Underlined = 4, - NoUnderline = 24, - Negative = 7, - Positive = 27, -} - -/// Colors that are available for coloring the terminal font. -#[derive(Debug, Copy, Clone)] -pub enum Color { - Black, - - Red, - DarkRed, - - Green, - DarkGreen, - - Yellow, - DarkYellow, - - Blue, - DarkBlue, - - Magenta, - DarkMagenta, - - Cyan, - DarkCyan, - - Grey, - White, - /// Color representing RGB-colors; - /// r = red - /// g = green - /// b = blue - Rgb { - r: u8, - g: u8, - b: u8, - }, - AnsiValue(u8), -} - -/// Color types that can be used to determine if the Color enum is a Fore- or Background Color. -#[derive(Debug, Copy, Clone)] -pub enum ColorType { - Background, - Foreground, -} - -impl<'a> From<&'a str> for Color { - /// Get an color from an &str like `Color::from("blue")`. - fn from(src: &str) -> Self { - src.parse().unwrap_or(Color::White) - } -} - -impl From for Color { - /// Get an color from an &str like `Color::from(String::from(blue))`. - fn from(src: String) -> Self { - src.parse().unwrap_or(Color::White) - } -} - -impl FromStr for Color { - type Err = (); - - /// Convert a string to an Color value - fn from_str(src: &str) -> ::std::result::Result { - let src = src.to_lowercase(); - - match src.as_ref() { - "black" => Ok(Color::Black), - "red" => Ok(Color::Red), - "dark_red" => Ok(Color::DarkRed), - "green" => Ok(Color::Green), - "dark_green" => Ok(Color::DarkGreen), - "yellow" => Ok(Color::Yellow), - "dark_yellow" => Ok(Color::DarkYellow), - "blue" => Ok(Color::Blue), - "dark_blue" => Ok(Color::DarkBlue), - "magenta" => Ok(Color::Magenta), - "dark_magenta" => Ok(Color::DarkMagenta), - "cyan" => Ok(Color::Cyan), - "dark_cyan" => Ok(Color::DarkCyan), - "grey" => Ok(Color::Grey), - "white" => Ok(Color::White), - _ => Ok(Color::White), - } - } +impl Styler<&'static str> for &'static str { + def_str_attr!(reset => Attribute::Reset); + def_str_attr!(bold => Attribute::Bold); + def_str_attr!(underlined => Attribute::Underlined); + def_str_attr!(reverse => Attribute::Reverse); + def_str_attr!(dim => Attribute::Dim); + def_str_attr!(italic => Attribute::Italic); + def_str_attr!(negative => Attribute::Reverse); + def_str_attr!(slow_blink => Attribute::SlowBlink); + def_str_attr!(rapid_blink => Attribute::RapidBlink); + def_str_attr!(hidden => Attribute::Hidden); + def_str_attr!(crossed_out => Attribute::CrossedOut); } diff --git a/crossterm_style/src/macros.rs b/crossterm_style/src/macros.rs new file mode 100644 index 0000000..0abbf84 --- /dev/null +++ b/crossterm_style/src/macros.rs @@ -0,0 +1,50 @@ +use crate::{ObjectStyle, StyledObject}; + +macro_rules! def_attr { + ($name: ident => $attr: path) => { + fn $name(self) -> StyledObject { + let mut so = self; + + so.attr($attr) + } + }; +} + +macro_rules! def_color { + ($side:ident: $name: ident => $color: path) => { + fn $name(self) -> StyledObject { + StyledObject { + object_style: ObjectStyle { + $side: Some($color), + .. self.object_style + }, + .. self + } + } + }; +} + +macro_rules! def_str_color { + ($side:ident: $name: ident => $color: path) => { + fn $name(self) -> StyledObject< &'static str> { + StyledObject { + object_style: ObjectStyle { + $side: Some($color), + .. ObjectStyle::default() + }, + content: self + } + } + }; +} + +macro_rules! def_str_attr { + ($name: ident => $color: path) => { + fn $name(self) -> StyledObject<&'static str> { + StyledObject { + object_style: ObjectStyle::default(), + content: self + } + } + } +} diff --git a/crossterm_style/src/styledobject.rs b/crossterm_style/src/styledobject.rs index 92ea03b..06770f8 100644 --- a/crossterm_style/src/styledobject.rs +++ b/crossterm_style/src/styledobject.rs @@ -9,6 +9,8 @@ use std::result; use std::sync::Arc; use super::Attribute; +use crate::Colorize; +use crate::Styler; /// Struct that contains both the style and the content wits can be styled. pub struct StyledObject { @@ -50,65 +52,6 @@ impl<'a, D: Display + 'a> StyledObject { self } - /// Increase the font intensity. - #[inline(always)] - pub fn bold(self) -> StyledObject { - self.attr(Attribute::Bold) - } - /// Faint (decreased intensity) (Not widely supported). - #[cfg(unix)] - #[inline(always)] - pub fn dim(self) -> StyledObject { - self.attr(Attribute::Dim) - } - /// Make the font italic (Not widely supported; Sometimes treated as inverse). - #[cfg(unix)] - #[inline(always)] - pub fn italic(self) -> StyledObject { - self.attr(Attribute::Italic) - } - /// Underline font. - #[inline(always)] - pub fn underlined(self) -> StyledObject { - self.attr(Attribute::Underlined) - } - /// Invert colours. - #[cfg(windows)] - #[inline(always)] - pub fn negative(self) -> StyledObject { - self.attr(Attribute::Negative) - } - /// Slow Blink (less than 150 per minute; not widely supported). - #[cfg(unix)] - #[inline(always)] - pub fn slow_blink(self) -> StyledObject { - self.attr(Attribute::SlowBlink) - } - /// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported). - #[cfg(unix)] - #[inline(always)] - pub fn rapid_blink(self) -> StyledObject { - self.attr(Attribute::RapidBlink) - } - /// Swap foreground and background colors. - #[cfg(unix)] - #[inline(always)] - pub fn reverse(self) -> StyledObject { - self.attr(Attribute::Reverse) - } - /// Hide text (Not widely supported). - #[cfg(unix)] - #[inline(always)] - pub fn hidden(self) -> StyledObject { - self.attr(Attribute::Hidden) - } - /// Characters legible, but marked for deletion. Not widely supported. - #[cfg(unix)] - #[inline(always)] - pub fn crossed_out(self) -> StyledObject { - self.attr(Attribute::CrossedOut) - } - /// This converts an styled object into an `DisplayableObject` witch implements: `Display` and could be used inside the write function of the standard library. /// /// _StyledObject already implements `Display` right?_ @@ -199,6 +142,56 @@ impl Display for StyledObject { } } +impl Colorize for StyledObject { + // foreground colors + def_color!(fg_color: black => Color::Black); + def_color!(fg_color: red => Color::Red); + def_color!(fg_color: dark_red => Color::DarkRed); + def_color!(fg_color: green => Color::Green); + def_color!(fg_color: dark_green => Color::DarkGreen); + def_color!(fg_color: yellow => Color::Yellow); + def_color!(fg_color: dark_yellow => Color::DarkYellow); + def_color!(fg_color: blue => Color::Blue); + def_color!(fg_color: dark_blue => Color::DarkBlue); + def_color!(fg_color: magenta => Color::Magenta); + def_color!(fg_color: dark_magenta => Color::DarkMagenta); + def_color!(fg_color: cyan => Color::Cyan); + def_color!(fg_color: dark_cyan => Color::DarkCyan); + def_color!(fg_color: white => Color::White); + def_color!(fg_color: grey => Color::Grey); + + // background colors + def_color!(bg_color: on_black => Color::Black); + def_color!(bg_color: on_red => Color::Red); + def_color!(bg_color: on_dark_red => Color::DarkRed); + def_color!(bg_color: on_green => Color::Green); + def_color!(bg_color: on_dark_green => Color::DarkGreen); + def_color!(bg_color: on_yellow => Color::Yellow); + def_color!(bg_color: on_dark_yellow => Color::DarkYellow); + def_color!(bg_color: on_blue => Color::Blue); + def_color!(bg_color: on_dark_blue => Color::DarkBlue); + def_color!(bg_color: on_magenta => Color::Magenta); + def_color!(bg_color: on_dark_magenta => Color::DarkMagenta); + def_color!(bg_color: on_cyan => Color::Cyan); + def_color!(bg_color: on_dark_cyan => Color::DarkCyan); + def_color!(bg_color: on_white => Color::White); + def_color!(bg_color: on_grey => Color::Grey); +} + +impl Styler for StyledObject { + def_attr!(reset => Attribute::Reset); + def_attr!(bold => Attribute::Bold); + def_attr!(underlined => Attribute::Underlined); + def_attr!(reverse => Attribute::Reverse); + def_attr!(dim => Attribute::Dim); + def_attr!(italic => Attribute::Italic); + def_attr!(negative => Attribute::Reverse); + def_attr!(slow_blink => Attribute::SlowBlink); + def_attr!(rapid_blink => Attribute::RapidBlink); + def_attr!(hidden => Attribute::Hidden); + def_attr!(crossed_out => Attribute::CrossedOut); +} + /// This is a wrapper for a styled object on 'alternate screen' so that the styled object could be printed on the 'alternate screen' with the standard write functions in rust. /// /// ``` diff --git a/crossterm_style/src/traits.rs b/crossterm_style/src/traits.rs new file mode 100644 index 0000000..51bfc30 --- /dev/null +++ b/crossterm_style/src/traits.rs @@ -0,0 +1,72 @@ +use crate::{ObjectStyle, StyledObject}; +use std::fmt::Display; + +/// Provides a set of methods to color any type implementing `Display` with attributes. +/// +/// This trait is implemented for `&static str` and `StyledObject` and thus the methods of this trait could be called on them. +/// +/// ``` rust +/// use Colorizer; +/// +/// let styled_text = "Red forground color on blue background.".red().on_blue(); +/// println!("{}", styled_text); +/// ``` +pub trait Colorize { + fn black(self) -> StyledObject; + fn red(self) -> StyledObject; + fn dark_red(self) -> StyledObject; + fn green(self) -> StyledObject; + fn dark_green(self) -> StyledObject; + fn yellow(self) -> StyledObject; + fn dark_yellow(self) -> StyledObject; + fn blue(self) -> StyledObject; + fn dark_blue(self) -> StyledObject; + fn magenta(self) -> StyledObject; + fn dark_magenta(self) -> StyledObject; + fn cyan(self) -> StyledObject; + fn dark_cyan(self) -> StyledObject; + fn white(self) -> StyledObject; + fn grey(self) -> StyledObject; + + fn on_black(self) -> StyledObject; + fn on_red(self) -> StyledObject; + fn on_dark_red(self) -> StyledObject; + fn on_green(self) -> StyledObject; + fn on_dark_green(self) -> StyledObject; + fn on_yellow(self) -> StyledObject; + fn on_dark_yellow(self) -> StyledObject; + fn on_blue(self) -> StyledObject; + fn on_dark_blue(self) -> StyledObject; + fn on_magenta(self) -> StyledObject; + fn on_dark_magenta(self) -> StyledObject; + fn on_cyan(self) -> StyledObject; + fn on_dark_cyan(self) -> StyledObject; + fn on_white(self) -> StyledObject; + fn on_grey(self) -> StyledObject; +} + +/// Provides a set of methods to style any type implementing `Display` with attributes. +/// +/// This trait is implemented for `&static str` and `StyledObject` and thus the methods of this trait could be called on them. +/// +/// # Example +/// ``` rust +/// use Colorizer; +/// +/// println!("{}", "Bold text".bold(); +/// println!("{}", "Underlined text".underlined(); +/// println!("{}", "Negative text".negative(); +/// ``` +pub trait Styler { + fn reset(self) -> StyledObject; + fn bold(self) -> StyledObject; + fn underlined(self) -> StyledObject; + fn reverse(self) -> StyledObject; + fn dim(self) -> StyledObject; + fn italic(self) -> StyledObject; + fn negative(self) -> StyledObject; + fn slow_blink(self) -> StyledObject; + fn rapid_blink(self) -> StyledObject; + fn hidden(self) -> StyledObject; + fn crossed_out(self) -> StyledObject; +} diff --git a/crossterm_style/src/winapi_color.rs b/crossterm_style/src/winapi_color.rs index 976daf3..5b08142 100644 --- a/crossterm_style/src/winapi_color.rs +++ b/crossterm_style/src/winapi_color.rs @@ -1,7 +1,7 @@ //! This is an `WinApi` specific implementation for styling related action. //! This module is used for non supporting `ANSI` Windows terminals. -use crate::{Color, ColorType, ITerminalColor}; +use crate::{Color, Colored, ITerminalColor}; use crossterm_utils::{Result, TerminalOutput}; use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer}; use std::io; @@ -23,7 +23,7 @@ impl ITerminalColor for WinApiColor { // init the original color in case it is not set. let _ = init_console_color()?; - let color_value = &self.color_value(fg_color, ColorType::Foreground); + let color_value = &self.color_value(Colored::Fg(fg_color)); let screen_buffer = ScreenBuffer::current()?; let csbi = screen_buffer.info()?; @@ -50,7 +50,7 @@ impl ITerminalColor for WinApiColor { // init the original color in case it is not set. let _ = init_console_color()?; - let color_value = &self.color_value(bg_color, ColorType::Background); + let color_value = &self.color_value(Colored::Bg(bg_color)); let screen_buffer = ScreenBuffer::current()?; let csbi = screen_buffer.info()?; @@ -83,7 +83,7 @@ impl ITerminalColor for WinApiColor { } /// This will get the winapi color value from the Color and ColorType struct - fn color_value(&self, color: Color, color_type: ColorType) -> String { + fn color_value(&self, color: Colored) -> String { let winapi_color: u16; let fg_green = wincon::FOREGROUND_GREEN; @@ -96,8 +96,8 @@ impl ITerminalColor for WinApiColor { let bg_blue = wincon::BACKGROUND_BLUE; let bg_intensity = wincon::BACKGROUND_INTENSITY; - match color_type { - ColorType::Foreground => { + match color { + Colored::Fg(color) => { winapi_color = match color { Color::Black => 0, Color::Red => fg_intensity | fg_red, @@ -120,7 +120,7 @@ impl ITerminalColor for WinApiColor { Color::AnsiValue(_val) => 0, }; } - ColorType::Background => { + Colored::Bg(color) => { winapi_color = match color { Color::Black => 0, Color::Red => bg_intensity | bg_red, diff --git a/crossterm_terminal/Cargo.toml b/crossterm_terminal/Cargo.toml index 1b9d69c..8e6a950 100644 --- a/crossterm_terminal/Cargo.toml +++ b/crossterm_terminal/Cargo.toml @@ -12,14 +12,14 @@ readme = "README.md" edition = "2018" [target.'cfg(windows)'.dependencies] -crossterm_winapi = { path = "../crossterm_winapi" } +crossterm_winapi = "0.1.1" [target.'cfg(unix)'.dependencies] libc = "0.2.43" [dependencies] -crossterm_utils = { path = "../crossterm_utils" } -crossterm_cursor = { path = "../crossterm_cursor" } +crossterm_utils = "0.1.0" +crossterm_cursor = "0.1.0" [[example]] name = "terminal" diff --git a/crossterm_utils/Cargo.toml b/crossterm_utils/Cargo.toml index cbd1a12..b5b745c 100644 --- a/crossterm_utils/Cargo.toml +++ b/crossterm_utils/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Timon Post "] edition = "2018" [target.'cfg(windows)'.dependencies] -crossterm_winapi = { path = "../crossterm_winapi" } +crossterm_winapi = "0.1.1" winapi = { version = "0.3.5", features = ["wincon"] } [target.'cfg(unix)'.dependencies] diff --git a/docs/ReleaseNotes.md b/docs/CHANGELOG.md similarity index 100% rename from docs/ReleaseNotes.md rename to docs/CHANGELOG.md diff --git a/docs/UpgradeManual.md b/docs/UPGRADE.md similarity index 100% rename from docs/UpgradeManual.md rename to docs/UPGRADE.md diff --git a/docs/mdbook/src/styling.md b/docs/mdbook/src/styling.md index b9c4946..f0a3e3e 100644 --- a/docs/mdbook/src/styling.md +++ b/docs/mdbook/src/styling.md @@ -1,13 +1,15 @@ +# Styling Module + Crossterm provides options for you to style your font and terminal. Take for example coloring output and applying attributes. **Color support** -Windows systems with versions less than 10 only have support for 16 colors and don't have any support for attributes. +Windows systems with versions less than 10 will only have support for 16 colors and don't have any support for attributes. Most UNIX-terminal is supporting lots of colors and attributes. ## Colors There are 16 base colors which available for almost all terminals even windows 7 and 8. | Light Variant | Dark Variant | -| :-------------| :------------- | +| :-------------| :------------- | | Grey | Black | | Red | DarkRed | | Green | DarkGreen | @@ -17,36 +19,34 @@ There are 16 base colors which available for almost all terminals even windows 7 | Cyan | DarkCyan | | White | DarkWhite | -In addition to 16 colours, most UNIX terminals and Windows 10 consoles are also supporting more colors. +In addition to 16 colors, most UNIX terminals and Windows 10 consoles are also supporting more colors. Those colors could be: [True color (24-bit)](https://en.wikipedia.org/wiki/Color_depth#True_color_(24-bit)) coloring scheme, which allows you to use [RGB](https://nl.wikipedia.org/wiki/RGB-kleursysteem), and [256 (Xterm, 8-bit)](https://jonasjacek.github.io/colors/) colors. ## Attributes -Only UNIX and Windows 10 terminals are supporting attributes on top of text. Crossterm allows you to add attributes to the text. +Only UNIX and Windows 10 terminals are supporting attributes on top of the text. Crossterm allows you to add attributes to the text. Not all attributes are widely supported for all terminals, keep that in mind when working with this. -**Unix Attributes** +Crossterm implements almost all attributes shown in this [Wikipedia-list](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters). -| Attribute | Note | -| :-------------: | :-------------: | -| Bold | _ | -| Underlined | _| -| Dim | _| -| SlowBlink | less than 150 per minute | -| CrosseOut | characters legible, but marked for deletion. | -| Italic | not widely supported; Sometimes treated as inverse | -| RapidBlink | not widely supported; MS-DOS ANSI.SYS; 150+ per minute | -| Reverse | not widely supported | -| Hidden | not widely supported | + | Attribute | Support | Note | +| :-------------: | :-------------: | :-------------: | +| Reset | Windows, UNIX | This will reset all current set attributes. | +| Bold | Windows, UNIX | This will increase the font sensitivity also known as bold. | +| Dim | Windows, UNIX | This will decrease the font sensitivity also known as bold. | +| Italic | Not widely supported, sometimes treated as inverse. | This will make the font italic. | +| Underlined | Windows, UNIX | An line under a word, especially in order to show its importance. | +| SlowBlink | Not widely supported, sometimes treated as inverse. | less than 150 per minute | +| RapidBlink | Not widely supported | MS-DOS ANSI.SYS; 150+ per minute; | +| Reverse | Windows, UNIX | foreground and background colors | +| Hidden | Windows, UNIX | | Also known as 'Conceal' +| Fraktur | UNIX | characters legible, but marked for deletion. | +| DefaultForegroundColor | Unknown | Implementation defined (according to standard) | +| DefaultBackgroundColor | Unknown | Implementation defined (according to standard) | +| Framed | Not widely supported | Framed font. +| Encircled | Unknown | This will turn on the encircled attribute. | +| OverLined | Unknown | This will draw a line at the top of the font. | -**Windows Attributes** - -| Attribute | Note | -| :-------------: | :-------------: | -| Reset | _ | -| Underlined | _ | -| NoUnderline | _ | -| Negative | _ | -| Positive | _ | +(There are a few attributes who disable one of the above, I did not write those down in the above scheme). Now we have covered the basics of styling lets go some [examples](styling_example.md). diff --git a/docs/mdbook/src/styling_example.md b/docs/mdbook/src/styling_example.md index e9e042e..4ba23ff 100644 --- a/docs/mdbook/src/styling_example.md +++ b/docs/mdbook/src/styling_example.md @@ -4,48 +4,55 @@ _setup the basics_ ```rust extern crate crossterm; -use crossterm::{style, Color, Attribute}; +use crossterm::{Colored, Color, Attribute, Styler, Colorize}; fn main() { /* your code here */ } ``` -Let's dive into styling with crossterm. The easiest way to do this is by making use of the `style()` function. +There are a couple of ways to style the terminal output with crossterm. The most important part of the styling module is `StyledObject`. -```rust -let styled_object = style("This is some text converted into a styled object"); -``` +A `StyledObject` is just a wrapper crossterm uses to store the text and style together. +A `StyledObject` implements `Display` and thus you could use it inside `print!`, `println!` etc. -The function `style()` takes in any type that implement `Display` -and returns a `StyledObject`. -A `StyledObject` is just a wrapper crossterm uses to store the text and style together. - -The above code will not do any coloring magic yet. Lets play around with some colors to see it in working. +Without further ado let's get straight into it. ## Coloring -```rust -let styled_object = style("'Red' text on 'White' background") - .with(Color::Red) - .on(Color::White); -println!("{}", styled_object); +There are a few ways to do the coloring, the first one is by using the `Colored` enum. + +### Using Enum +```rust +println!("{} Red foreground color", Colored::Fg(Color::Red)); +println!("{} Blue background color", Colored::Bg(Color::Blue)); +``` +`Colored::Bg` will set the background color, and `Colored::Fg` will set the foreground color to the provided color. +The provided color is of type `Color` and has a bunch of enum values you could choose out. + +Because `Colored` implements `Display` you are able to use it inside any write statement. + +### Using Methods +You can do the same as the above in a slightly different way. Instead of enabling it for all text you could also color the only piece of text. +(Make sure to include the `crossterm::Coloring` trait). + +```rust +let styled_text = "Red forground color on blue background.".red().on_blue(); +println!("{}", styled_text); ``` -With the function `with()` you can decide the foreground color and with the function `on()` you can decide the background color of the text. -Because `StyledObject` you got from `style()` implements `Display` you are allowed to print it with: `print!, println!, write` etc. -When running the above code you are supposed to see colored text with foreground color 'red' and with the background color 'white'. +As you see in the above example you could call coloring methods on a string. How is this possible you might ask..? +Well, the trait `Coloring`, who you need to include, is implemented for `&'static str`. +When calling a method on this string crossterm transforms it into a `StyledObject` who you could use in your write statements. -_note: you don't have to color both backround an foreground, if not specified they remain as they are_. ### RGB Most UNIX terminals and all Windows 10 consoles are supporting [True color(24-bit)](https://en.wikipedia.org/wiki/Color_depth#True_color_(24-bit)) coloring scheme. You can set the color of the terminal by using `Color::RGB(r,g,b)`. -``` -let styled_object = style("'Light green' text on 'Black' background") - .with(Color::Rgb {r: 0, g: 255, b: 128}) - .on(Color::Rgb {r: 0, g: 0, b: 0}); +``` +// custom rgb value (Windows 10 and UNIX systems) +println!("{}{} 'Light green' text on 'Black' background", Colored::Fg(Color::Rgb { r: 0, g: 255, b: 128 }), Colored::Bg(Color::Rgb {r: 0, g: 0, b: 0})); ``` This will print some light green text on black background. @@ -54,25 +61,40 @@ When working on UNIX or Windows 10 you could also specify a custom ANSI value ra See [256 (Xterm, 8-bit) colors](https://jonasjacek.github.io/colors/) for more information. ``` -let styled_object = style("'Red' text on 'White' background") - .with(Color::AnsiValue(9)) - .on(Color::AnsiValue(15)); - - -println!("{}", styled_object); +// custom ansi color value (Windows 10 and UNIX systems) +println!("{} some colored text", Colored::Fg(Color::AnsiValue(10))); ``` ## Attributes -When working with UNIX or Windows 10 terminals you could also use attributes to style your font. For example you could cross your text with a line and make it bold. +When working with UNIX or Windows 10 terminals you could also use attributes to style your font. For example, you could cross your text with a line and make it bold. See [this](styling.md#Attributes) for more information. -``` -let styled_object = style("'Red' text on 'White' background") - .attr(Attribute::CrossedOut) - .attr(Attribute::Bold); +### Using Enum +You could use the `Attribute` enum for styling text with attributes. +`Attribute` implements `Display`, thus crossterm will enable the attribute style when using it in any writing operation. -println!("{}", styled_object); ``` +println!( + "{} Underlined {} No Underline", + Attribute::Underlined, + Attribute::NoUnderline +); +``` + +### Using Method + +You can do the same as the above in a slightly different way. Instead of enabling it for all text you could also style only one piece of text. +(Make sure to include the `crossterm::Styler` trait). + +``` +println!("{}", "Bold text".bold(); +println!("{}", "Underlined text".underlined(); +println!("{}", "Negative text".negative(); +``` + +As you see in the above example you could call attributes methods on a string. How is this possible you might ask..? +Well, the trait `Styling`, who you need to include, is implemented for `&'static str`. +When calling a method on any string crossterm transforms will transform it into a `StyledObject` who you could use in your write statements. --------------------------------------------------------------------------------------------------------------------------------------------- More examples could be found at this [link](https://github.com/TimonPost/crossterm/blob/master/examples/style.rs). \ No newline at end of file diff --git a/examples/style.rs b/examples/style.rs index ebe8fc8..d83a593 100644 --- a/examples/style.rs +++ b/examples/style.rs @@ -230,9 +230,3 @@ pub fn print_supported_colors() { ); } } - -fn main() { - print_all_background_colors(); - print_all_foreground_colors(); - print_font_with_attributes(); -}