Removed old api Style Module (#299)
This commit is contained in:
parent
5c36790187
commit
3e82d6ae1c
12
CHANGELOG.md
12
CHANGELOG.md
@ -26,6 +26,18 @@
|
|||||||
- Rename `PrintStyledFont` to `PrintStyledContent`
|
- Rename `PrintStyledFont` to `PrintStyledContent`
|
||||||
- Rename `attr` method to `attribute`.
|
- Rename `attr` method to `attribute`.
|
||||||
- Rename `Attribute::NoInverse` to `NoReverse`
|
- Rename `Attribute::NoInverse` to `NoReverse`
|
||||||
|
- `Crossterm::style()` and `Crossterm::color()`
|
||||||
|
- Remove re-exports from style module at at root and only expose those in the `crossterm::style` module.
|
||||||
|
- Remove `TerminalColor` (/style.rs),
|
||||||
|
- Remove `color` (style.rs)
|
||||||
|
- Update documentation
|
||||||
|
- Made `Colored` private, user should use commands instead.
|
||||||
|
- Rename `SetFg` -> `SetForegroundColor`
|
||||||
|
- Rename `SetBg` -> `SetBackgroundColor`
|
||||||
|
- Rename `SetAttr` -> `SetAttribute`
|
||||||
|
- Rename `ContentStyle::fg_color` -> `ContentStyle::foreground_color`
|
||||||
|
- Rename `ContentStyle::bg_color` -> `ContentStyle::background_color`
|
||||||
|
- Rename `ContentStyle::attrs` -> `ContentStyle::attributes`
|
||||||
|
|
||||||
# Version 0.12.1
|
# Version 0.12.1
|
||||||
|
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
#[cfg(feature = "style")]
|
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
// TODO Should be removed? This adds just another way to achieve the same thing.
|
|
||||||
/// A crossterm functionality wrapper.
|
/// A crossterm functionality wrapper.
|
||||||
pub struct Crossterm;
|
pub struct Crossterm;
|
||||||
|
|
||||||
@ -16,19 +12,4 @@ impl Crossterm {
|
|||||||
pub fn input(&self) -> crate::input::TerminalInput {
|
pub fn input(&self) -> crate::input::TerminalInput {
|
||||||
crate::input::TerminalInput::new()
|
crate::input::TerminalInput::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `TerminalColor`.
|
|
||||||
#[cfg(feature = "style")]
|
|
||||||
pub fn color(&self) -> crate::style::TerminalColor {
|
|
||||||
crate::style::TerminalColor::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new `StyledContent`.
|
|
||||||
#[cfg(feature = "style")]
|
|
||||||
pub fn style<D>(&self, val: D) -> crate::style::StyledContent<D>
|
|
||||||
where
|
|
||||||
D: Display + Clone,
|
|
||||||
{
|
|
||||||
crate::style::ContentStyle::new().apply(val)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
13
src/lib.rs
13
src/lib.rs
@ -118,8 +118,8 @@
|
|||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use std::io::{stdout, Write};
|
//! use std::io::{stdout, Write};
|
||||||
//! use crossterm::{
|
//! use crossterm::{
|
||||||
//! ExecutableCommand, QueueableCommand, Color,
|
//! ExecutableCommand, QueueableCommand,
|
||||||
//! Colorize, terminal, cursor, style, Result
|
//! terminal, cursor, style::{self, Colorize}, Result
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! fn main() -> Result<()> {
|
//! fn main() -> Result<()> {
|
||||||
@ -146,8 +146,8 @@
|
|||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use std::io::{stdout, Write};
|
//! use std::io::{stdout, Write};
|
||||||
//! use crossterm::{
|
//! use crossterm::{
|
||||||
//! execute, queue, Color, PrintStyledContent,
|
//! execute, queue,
|
||||||
//! Colorize, cursor, terminal, style, Result
|
//! style::{self, Colorize}, cursor, terminal, Result
|
||||||
//! };
|
//! };
|
||||||
//!
|
//!
|
||||||
//! fn main() -> Result<()> {
|
//! fn main() -> Result<()> {
|
||||||
@ -176,11 +176,6 @@ pub use input::{
|
|||||||
pub use screen::{
|
pub use screen::{
|
||||||
AlternateScreen, EnterAlternateScreen, IntoRawMode, LeaveAlternateScreen, RawScreen,
|
AlternateScreen, EnterAlternateScreen, IntoRawMode, LeaveAlternateScreen, RawScreen,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "style")]
|
|
||||||
pub use style::{
|
|
||||||
color, style, Attribute, Color, Colored, Colorize, ContentStyle, PrintStyledContent,
|
|
||||||
ResetColor, SetAttr, SetBg, SetFg, StyledContent, Styler, TerminalColor,
|
|
||||||
};
|
|
||||||
pub use utils::{Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result};
|
pub use utils::{Command, ErrorKind, ExecutableCommand, Output, QueueableCommand, Result};
|
||||||
|
|
||||||
pub use self::crossterm::Crossterm;
|
pub use self::crossterm::Crossterm;
|
||||||
|
251
src/style.rs
251
src/style.rs
@ -25,15 +25,16 @@
|
|||||||
//! use std::io::{stdout, Write};
|
//! use std::io::{stdout, Write};
|
||||||
//!
|
//!
|
||||||
//! use crossterm::{execute, Result, Output};
|
//! use crossterm::{execute, Result, Output};
|
||||||
//! use crossterm::{SetBg, SetFg, ResetColor, Color, Attribute};
|
//! use crossterm::style::{SetForegroundColor, SetBackgroundColor, ResetColor, Color, Attribute};
|
||||||
//!
|
//!
|
||||||
//! fn main() -> Result<()> {
|
//! fn main() -> Result<()> {
|
||||||
//! execute!(
|
//! execute!(
|
||||||
//! stdout(),
|
//! stdout(),
|
||||||
//! // Blue foreground
|
//! // Blue foreground
|
||||||
//! SetFg(Color::Blue),
|
//! SetForegroundColor(Color::Blue),
|
||||||
//! // Red background
|
//! // Red background
|
||||||
//! SetBg(Color::Red),
|
//! SetBackgroundColor(Color::Red),
|
||||||
|
//! // output text
|
||||||
//! Output("Styled text here.".to_string()),
|
//! Output("Styled text here.".to_string()),
|
||||||
//! // Reset to default colors
|
//! // Reset to default colors
|
||||||
//! ResetColor
|
//! ResetColor
|
||||||
@ -41,19 +42,10 @@
|
|||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! The [`Colored`](enum.Colored.html) & [`Color`](enum.Color.html) enums:
|
|
||||||
//!
|
|
||||||
//! ```no_run
|
|
||||||
//! use crossterm::{Colored, Color};
|
|
||||||
//!
|
|
||||||
//! println!("{} Red foreground", Colored::Fg(Color::Red));
|
|
||||||
//! println!("{} Blue background", Colored::Bg(Color::Blue));
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! The [`Colorize`](trait.Colorize.html) trait:
|
//! The [`Colorize`](trait.Colorize.html) trait:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use crossterm::Colorize;
|
//! use crossterm::style::Colorize;
|
||||||
//!
|
//!
|
||||||
//! println!("{}", "Red foreground color & blue background.".red().on_blue());
|
//! println!("{}", "Red foreground color & blue background.".red().on_blue());
|
||||||
//! ```
|
//! ```
|
||||||
@ -66,16 +58,16 @@
|
|||||||
//! use std::io::{stdout, Write};
|
//! use std::io::{stdout, Write};
|
||||||
//!
|
//!
|
||||||
//! use crossterm::{execute, Result, Output};
|
//! use crossterm::{execute, Result, Output};
|
||||||
//! use crossterm::{SetAttr, Attribute};
|
//! use crossterm::style::{SetAttribute, Attribute};
|
||||||
//!
|
//!
|
||||||
//! fn main() -> Result<()> {
|
//! fn main() -> Result<()> {
|
||||||
//! execute!(
|
//! execute!(
|
||||||
//! stdout(),
|
//! stdout(),
|
||||||
//! // Set to bold
|
//! // Set to bold
|
||||||
//! SetAttr(Attribute::Bold),
|
//! SetAttribute(Attribute::Bold),
|
||||||
//! Output("Styled text here.".to_string()),
|
//! Output("Styled text here.".to_string()),
|
||||||
//! // Reset all attributes
|
//! // Reset all attributes
|
||||||
//! SetAttr(Attribute::Reset)
|
//! SetAttribute(Attribute::Reset)
|
||||||
//! )
|
//! )
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
@ -83,7 +75,7 @@
|
|||||||
//! The [`Styler`](trait.Styler.html) trait:
|
//! The [`Styler`](trait.Styler.html) trait:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use crossterm::Styler;
|
//! use crossterm::style::Styler;
|
||||||
//!
|
//!
|
||||||
//! println!("{}", "Bold".bold());
|
//! println!("{}", "Bold".bold());
|
||||||
//! println!("{}", "Underlined".underlined());
|
//! println!("{}", "Underlined".underlined());
|
||||||
@ -93,7 +85,7 @@
|
|||||||
//! The [`Attribute`](enum.Attribute.html) enum:
|
//! The [`Attribute`](enum.Attribute.html) enum:
|
||||||
//!
|
//!
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use crossterm::Attribute;
|
//! use crossterm::style::Attribute;
|
||||||
//!
|
//!
|
||||||
//! println!(
|
//! println!(
|
||||||
//! "{} Underlined {} No Underline",
|
//! "{} Underlined {} No Underline",
|
||||||
@ -105,27 +97,25 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use style::ansi::{self, AnsiColor};
|
|
||||||
#[cfg(windows)]
|
|
||||||
use style::winapi::WinApiColor;
|
|
||||||
use style::Style;
|
|
||||||
|
|
||||||
use crate::impl_display;
|
use crate::impl_display;
|
||||||
#[cfg(windows)]
|
use crate::utils::Command;
|
||||||
use crate::utils::supports_ansi;
|
|
||||||
use crate::utils::{Command, Result};
|
|
||||||
|
|
||||||
pub use self::contentstyle::ContentStyle;
|
#[cfg(windows)]
|
||||||
pub use self::enums::{Attribute, Color, Colored};
|
use crate::Result;
|
||||||
pub use self::styledcontent::StyledContent;
|
|
||||||
|
pub use self::content_style::ContentStyle;
|
||||||
|
pub(crate) use self::enums::Colored;
|
||||||
|
pub use self::enums::{Attribute, Color};
|
||||||
|
pub use self::styled_content::StyledContent;
|
||||||
pub use self::traits::{Colorize, Styler};
|
pub use self::traits::{Colorize, Styler};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
mod contentstyle;
|
mod ansi;
|
||||||
|
mod content_style;
|
||||||
mod enums;
|
mod enums;
|
||||||
mod style;
|
mod styled_content;
|
||||||
mod styledcontent;
|
mod sys;
|
||||||
mod traits;
|
mod traits;
|
||||||
|
|
||||||
/// Creates a `StyledContent`.
|
/// Creates a `StyledContent`.
|
||||||
@ -137,7 +127,7 @@ mod traits;
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use crossterm::{style, Color};
|
/// use crossterm::style::{style, Color};
|
||||||
///
|
///
|
||||||
/// let styled_content = style("Blue colored text on yellow background")
|
/// let styled_content = style("Blue colored text on yellow background")
|
||||||
/// .with(Color::Blue)
|
/// .with(Color::Blue)
|
||||||
@ -154,40 +144,40 @@ where
|
|||||||
|
|
||||||
impl Colorize<&'static str> for &'static str {
|
impl Colorize<&'static str> for &'static str {
|
||||||
// foreground colors
|
// foreground colors
|
||||||
def_str_color!(fg_color: black => Color::Black);
|
def_str_color!(foreground_color: black => Color::Black);
|
||||||
def_str_color!(fg_color: dark_grey => Color::DarkGrey);
|
def_str_color!(foreground_color: dark_grey => Color::DarkGrey);
|
||||||
def_str_color!(fg_color: red => Color::Red);
|
def_str_color!(foreground_color: red => Color::Red);
|
||||||
def_str_color!(fg_color: dark_red => Color::DarkRed);
|
def_str_color!(foreground_color: dark_red => Color::DarkRed);
|
||||||
def_str_color!(fg_color: green => Color::Green);
|
def_str_color!(foreground_color: green => Color::Green);
|
||||||
def_str_color!(fg_color: dark_green => Color::DarkGreen);
|
def_str_color!(foreground_color: dark_green => Color::DarkGreen);
|
||||||
def_str_color!(fg_color: yellow => Color::Yellow);
|
def_str_color!(foreground_color: yellow => Color::Yellow);
|
||||||
def_str_color!(fg_color: dark_yellow => Color::DarkYellow);
|
def_str_color!(foreground_color: dark_yellow => Color::DarkYellow);
|
||||||
def_str_color!(fg_color: blue => Color::Blue);
|
def_str_color!(foreground_color: blue => Color::Blue);
|
||||||
def_str_color!(fg_color: dark_blue => Color::DarkBlue);
|
def_str_color!(foreground_color: dark_blue => Color::DarkBlue);
|
||||||
def_str_color!(fg_color: magenta => Color::Magenta);
|
def_str_color!(foreground_color: magenta => Color::Magenta);
|
||||||
def_str_color!(fg_color: dark_magenta => Color::DarkMagenta);
|
def_str_color!(foreground_color: dark_magenta => Color::DarkMagenta);
|
||||||
def_str_color!(fg_color: cyan => Color::Cyan);
|
def_str_color!(foreground_color: cyan => Color::Cyan);
|
||||||
def_str_color!(fg_color: dark_cyan => Color::DarkCyan);
|
def_str_color!(foreground_color: dark_cyan => Color::DarkCyan);
|
||||||
def_str_color!(fg_color: white => Color::White);
|
def_str_color!(foreground_color: white => Color::White);
|
||||||
def_str_color!(fg_color: grey => Color::Grey);
|
def_str_color!(foreground_color: grey => Color::Grey);
|
||||||
|
|
||||||
// background colors
|
// background colors
|
||||||
def_str_color!(bg_color: on_black => Color::Black);
|
def_str_color!(background_color: on_black => Color::Black);
|
||||||
def_str_color!(bg_color: on_dark_grey => Color::DarkGrey);
|
def_str_color!(background_color: on_dark_grey => Color::DarkGrey);
|
||||||
def_str_color!(bg_color: on_red => Color::Red);
|
def_str_color!(background_color: on_red => Color::Red);
|
||||||
def_str_color!(bg_color: on_dark_red => Color::DarkRed);
|
def_str_color!(background_color: on_dark_red => Color::DarkRed);
|
||||||
def_str_color!(bg_color: on_green => Color::Green);
|
def_str_color!(background_color: on_green => Color::Green);
|
||||||
def_str_color!(bg_color: on_dark_green => Color::DarkGreen);
|
def_str_color!(background_color: on_dark_green => Color::DarkGreen);
|
||||||
def_str_color!(bg_color: on_yellow => Color::Yellow);
|
def_str_color!(background_color: on_yellow => Color::Yellow);
|
||||||
def_str_color!(bg_color: on_dark_yellow => Color::DarkYellow);
|
def_str_color!(background_color: on_dark_yellow => Color::DarkYellow);
|
||||||
def_str_color!(bg_color: on_blue => Color::Blue);
|
def_str_color!(background_color: on_blue => Color::Blue);
|
||||||
def_str_color!(bg_color: on_dark_blue => Color::DarkBlue);
|
def_str_color!(background_color: on_dark_blue => Color::DarkBlue);
|
||||||
def_str_color!(bg_color: on_magenta => Color::Magenta);
|
def_str_color!(background_color: on_magenta => Color::Magenta);
|
||||||
def_str_color!(bg_color: on_dark_magenta => Color::DarkMagenta);
|
def_str_color!(background_color: on_dark_magenta => Color::DarkMagenta);
|
||||||
def_str_color!(bg_color: on_cyan => Color::Cyan);
|
def_str_color!(background_color: on_cyan => Color::Cyan);
|
||||||
def_str_color!(bg_color: on_dark_cyan => Color::DarkCyan);
|
def_str_color!(background_color: on_dark_cyan => Color::DarkCyan);
|
||||||
def_str_color!(bg_color: on_white => Color::White);
|
def_str_color!(background_color: on_white => Color::White);
|
||||||
def_str_color!(bg_color: on_grey => Color::Grey);
|
def_str_color!(background_color: on_grey => Color::Grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Styler<&'static str> for &'static str {
|
impl Styler<&'static str> for &'static str {
|
||||||
@ -204,110 +194,27 @@ impl Styler<&'static str> for &'static str {
|
|||||||
def_str_attr!(crossed_out => Attribute::CrossedOut);
|
def_str_attr!(crossed_out => Attribute::CrossedOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A terminal color.
|
/// Returns available color count.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Notes
|
||||||
///
|
///
|
||||||
/// Basic usage:
|
/// This does not always provide a good result.
|
||||||
///
|
pub fn available_color_count() -> u16 {
|
||||||
/// ```no_run
|
env::var("TERM")
|
||||||
/// // You can replace the following line with `use crossterm::TerminalColor;`
|
.map(|x| if x.contains("256color") { 256 } else { 8 })
|
||||||
/// // if you're using the `crossterm` crate with the `style` feature enabled.
|
.unwrap_or(8)
|
||||||
/// use crossterm::{Result, TerminalColor, Color};
|
|
||||||
///
|
|
||||||
/// fn main() -> Result<()> {
|
|
||||||
/// let color = TerminalColor::new();
|
|
||||||
/// // Set foreground color
|
|
||||||
/// color.set_fg(Color::Blue)?;
|
|
||||||
/// // Set background color
|
|
||||||
/// color.set_bg(Color::Red)?;
|
|
||||||
/// // Reset to the default colors
|
|
||||||
/// color.reset()
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub struct TerminalColor {
|
|
||||||
#[cfg(windows)]
|
|
||||||
color: Box<(dyn Style + Sync + Send)>,
|
|
||||||
#[cfg(unix)]
|
|
||||||
color: AnsiColor,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalColor {
|
/// A command that sets the the foreground color.
|
||||||
/// Creates a new `TerminalColor`.
|
|
||||||
pub fn new() -> TerminalColor {
|
|
||||||
#[cfg(windows)]
|
|
||||||
let color = if supports_ansi() {
|
|
||||||
Box::from(AnsiColor::new()) as Box<(dyn Style + Sync + Send)>
|
|
||||||
} else {
|
|
||||||
WinApiColor::new() as Box<(dyn Style + Sync + Send)>
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
let color = AnsiColor::new();
|
|
||||||
|
|
||||||
TerminalColor { color }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the foreground color.
|
|
||||||
pub fn set_fg(&self, color: Color) -> Result<()> {
|
|
||||||
self.color.set_fg(color)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets the background color.
|
|
||||||
pub fn set_bg(&self, color: Color) -> Result<()> {
|
|
||||||
self.color.set_bg(color)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets the terminal colors and attributes to the default ones.
|
|
||||||
pub fn reset(&self) -> Result<()> {
|
|
||||||
self.color.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns available color count.
|
|
||||||
///
|
|
||||||
/// # Notes
|
|
||||||
///
|
|
||||||
/// This does not always provide a good result.
|
|
||||||
pub fn available_color_count(&self) -> u16 {
|
|
||||||
env::var("TERM")
|
|
||||||
.map(|x| if x.contains("256color") { 256 } else { 8 })
|
|
||||||
.unwrap_or(8)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new `TerminalColor`.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// Basic usage:
|
|
||||||
///
|
|
||||||
/// ```no_run
|
|
||||||
/// use crossterm::{color, Color, Result};
|
|
||||||
///
|
|
||||||
/// fn main() -> Result<()> {
|
|
||||||
/// let color = color();
|
|
||||||
/// // Set foreground color
|
|
||||||
/// color.set_fg(Color::Blue)?;
|
|
||||||
/// // Set background color
|
|
||||||
/// color.set_bg(Color::Red)?;
|
|
||||||
/// // Reset to the default colors
|
|
||||||
/// color.reset()
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub fn color() -> TerminalColor {
|
|
||||||
TerminalColor::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A command to set the foreground color.
|
|
||||||
///
|
///
|
||||||
/// See [`Color`](enum.Color.html) for more info.
|
/// See [`Color`](enum.Color.html) for more info.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
/// Commands must be executed/queued for execution otherwise they do nothing.
|
/// Commands must be executed/queued for execution otherwise they do nothing.
|
||||||
pub struct SetFg(pub Color);
|
pub struct SetForegroundColor(pub Color);
|
||||||
|
|
||||||
impl Command for SetFg {
|
impl Command for SetForegroundColor {
|
||||||
type AnsiType = String;
|
type AnsiType = String;
|
||||||
|
|
||||||
fn ansi_code(&self) -> Self::AnsiType {
|
fn ansi_code(&self) -> Self::AnsiType {
|
||||||
@ -316,20 +223,20 @@ impl Command for SetFg {
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self) -> Result<()> {
|
||||||
WinApiColor::new().set_fg(self.0)
|
sys::windows::set_foreground_color(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A command to set the background color.
|
/// A command that sets the the background color.
|
||||||
///
|
///
|
||||||
/// See [`Color`](enum.Color.html) for more info.
|
/// See [`Color`](enum.Color.html) for more info.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
/// Commands must be executed/queued for execution otherwise they do nothing.
|
/// Commands must be executed/queued for execution otherwise they do nothing.
|
||||||
pub struct SetBg(pub Color);
|
pub struct SetBackgroundColor(pub Color);
|
||||||
|
|
||||||
impl Command for SetBg {
|
impl Command for SetBackgroundColor {
|
||||||
type AnsiType = String;
|
type AnsiType = String;
|
||||||
|
|
||||||
fn ansi_code(&self) -> Self::AnsiType {
|
fn ansi_code(&self) -> Self::AnsiType {
|
||||||
@ -338,20 +245,20 @@ impl Command for SetBg {
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self) -> Result<()> {
|
||||||
WinApiColor::new().set_bg(self.0)
|
sys::windows::set_background_color(self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A command to set the text attribute.
|
/// A command that sets an attribute.
|
||||||
///
|
///
|
||||||
/// See [`Attribute`](enum.Attribute.html) for more info.
|
/// See [`Attribute`](enum.Attribute.html) for more info.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
/// Commands must be executed/queued for execution otherwise they do nothing.
|
/// Commands must be executed/queued for execution otherwise they do nothing.
|
||||||
pub struct SetAttr(pub Attribute);
|
pub struct SetAttribute(pub Attribute);
|
||||||
|
|
||||||
impl Command for SetAttr {
|
impl Command for SetAttribute {
|
||||||
type AnsiType = String;
|
type AnsiType = String;
|
||||||
|
|
||||||
fn ansi_code(&self) -> Self::AnsiType {
|
fn ansi_code(&self) -> Self::AnsiType {
|
||||||
@ -365,7 +272,7 @@ impl Command for SetAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A command to print the styled content.
|
/// A command that prints styled content.
|
||||||
///
|
///
|
||||||
/// See [`StyledContent`](struct.StyledContent.html) for more info.
|
/// See [`StyledContent`](struct.StyledContent.html) for more info.
|
||||||
///
|
///
|
||||||
@ -390,7 +297,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A command to reset the colors back to default ones.
|
/// A command that resets the colors back to default.
|
||||||
///
|
///
|
||||||
/// # Notes
|
/// # Notes
|
||||||
///
|
///
|
||||||
@ -406,13 +313,13 @@ impl Command for ResetColor {
|
|||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn execute_winapi(&self) -> Result<()> {
|
fn execute_winapi(&self) -> Result<()> {
|
||||||
WinApiColor::new().reset()
|
sys::windows::reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display!(for SetFg);
|
impl_display!(for SetForegroundColor);
|
||||||
impl_display!(for SetBg);
|
impl_display!(for SetBackgroundColor);
|
||||||
impl_display!(for SetAttr);
|
impl_display!(for SetAttribute);
|
||||||
impl_display!(for PrintStyledContent<String>);
|
impl_display!(for PrintStyledContent<String>);
|
||||||
impl_display!(for PrintStyledContent<&'static str>);
|
impl_display!(for PrintStyledContent<&'static str>);
|
||||||
impl_display!(for ResetColor);
|
impl_display!(for ResetColor);
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
//! This is a ANSI specific implementation for styling related action.
|
//! This is a ANSI specific implementation for styling related action.
|
||||||
//! This module is used for Windows 10 terminals and Unix terminals by default.
|
//! This module is used for Windows 10 terminals and Unix terminals by default.
|
||||||
|
|
||||||
use crate::utils::Result;
|
use crate::csi;
|
||||||
use crate::{csi, write_cout};
|
use crate::style::{Attribute, Color, Colored};
|
||||||
|
|
||||||
use super::super::{Attribute, Color, Colored, Style};
|
|
||||||
|
|
||||||
pub(crate) fn set_fg_csi_sequence(fg_color: Color) -> String {
|
pub(crate) fn set_fg_csi_sequence(fg_color: Color) -> String {
|
||||||
format!(csi!("{}m"), Into::<String>::into(Colored::Fg(fg_color)))
|
format!(
|
||||||
|
csi!("{}m"),
|
||||||
|
Into::<String>::into(Colored::ForegroundColor(fg_color))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_bg_csi_sequence(bg_color: Color) -> String {
|
pub(crate) fn set_bg_csi_sequence(bg_color: Color) -> String {
|
||||||
format!(csi!("{}m"), Into::<String>::into(Colored::Bg(bg_color)))
|
format!(
|
||||||
|
csi!("{}m"),
|
||||||
|
Into::<String>::into(Colored::BackgroundColor(bg_color))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_attr_csi_sequence(attribute: Attribute) -> String {
|
pub(crate) fn set_attr_csi_sequence(attribute: Attribute) -> String {
|
||||||
@ -20,32 +24,6 @@ pub(crate) fn set_attr_csi_sequence(attribute: Attribute) -> String {
|
|||||||
|
|
||||||
pub(crate) static RESET_CSI_SEQUENCE: &'static str = csi!("0m");
|
pub(crate) static RESET_CSI_SEQUENCE: &'static str = csi!("0m");
|
||||||
|
|
||||||
/// This struct is an ANSI escape code implementation for color related actions.
|
|
||||||
pub(crate) struct AnsiColor;
|
|
||||||
|
|
||||||
impl AnsiColor {
|
|
||||||
pub fn new() -> AnsiColor {
|
|
||||||
AnsiColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Style for AnsiColor {
|
|
||||||
fn set_fg(&self, fg_color: Color) -> Result<()> {
|
|
||||||
write_cout!(set_fg_csi_sequence(fg_color))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_bg(&self, bg_color: Color) -> Result<()> {
|
|
||||||
write_cout!(set_bg_csi_sequence(bg_color))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset(&self) -> Result<()> {
|
|
||||||
write_cout!(RESET_CSI_SEQUENCE)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Colored> for String {
|
impl From<Colored> for String {
|
||||||
fn from(colored: Colored) -> Self {
|
fn from(colored: Colored) -> Self {
|
||||||
let mut ansi_value = String::new();
|
let mut ansi_value = String::new();
|
||||||
@ -53,7 +31,7 @@ impl From<Colored> for String {
|
|||||||
let color;
|
let color;
|
||||||
|
|
||||||
match colored {
|
match colored {
|
||||||
Colored::Fg(new_color) => {
|
Colored::ForegroundColor(new_color) => {
|
||||||
if new_color == Color::Reset {
|
if new_color == Color::Reset {
|
||||||
ansi_value.push_str("39");
|
ansi_value.push_str("39");
|
||||||
return ansi_value;
|
return ansi_value;
|
||||||
@ -62,7 +40,7 @@ impl From<Colored> for String {
|
|||||||
color = new_color;
|
color = new_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Colored::Bg(new_color) => {
|
Colored::BackgroundColor(new_color) => {
|
||||||
if new_color == Color::Reset {
|
if new_color == Color::Reset {
|
||||||
ansi_value.push_str("49");
|
ansi_value.push_str("49");
|
||||||
return ansi_value;
|
return ansi_value;
|
||||||
@ -108,41 +86,41 @@ impl From<Colored> for String {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{Color, Colored};
|
use crate::style::{Color, Colored};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_fg_color() {
|
fn test_parse_fg_color() {
|
||||||
let colored = Colored::Fg(Color::Red);
|
let colored = Colored::ForegroundColor(Color::Red);
|
||||||
assert_eq!(Into::<String>::into(colored), "38;5;9");
|
assert_eq!(Into::<String>::into(colored), "38;5;9");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_bg_color() {
|
fn test_parse_bg_color() {
|
||||||
let colored = Colored::Bg(Color::Red);
|
let colored = Colored::BackgroundColor(Color::Red);
|
||||||
assert_eq!(Into::<String>::into(colored), "48;5;9");
|
assert_eq!(Into::<String>::into(colored), "48;5;9");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_reset_fg_color() {
|
fn test_parse_reset_fg_color() {
|
||||||
let colored = Colored::Fg(Color::Reset);
|
let colored = Colored::ForegroundColor(Color::Reset);
|
||||||
assert_eq!(Into::<String>::into(colored), "39");
|
assert_eq!(Into::<String>::into(colored), "39");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_reset_bg_color() {
|
fn test_parse_reset_bg_color() {
|
||||||
let colored = Colored::Bg(Color::Reset);
|
let colored = Colored::BackgroundColor(Color::Reset);
|
||||||
assert_eq!(Into::<String>::into(colored), "49");
|
assert_eq!(Into::<String>::into(colored), "49");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_fg_rgb_color() {
|
fn test_parse_fg_rgb_color() {
|
||||||
let colored = Colored::Bg(Color::Rgb { r: 1, g: 2, b: 3 });
|
let colored = Colored::BackgroundColor(Color::Rgb { r: 1, g: 2, b: 3 });
|
||||||
assert_eq!(Into::<String>::into(colored), "48;2;1;2;3");
|
assert_eq!(Into::<String>::into(colored), "48;2;1;2;3");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_fg_ansi_color() {
|
fn test_parse_fg_ansi_color() {
|
||||||
let colored = Colored::Fg(Color::AnsiValue(255));
|
let colored = Colored::ForegroundColor(Color::AnsiValue(255));
|
||||||
assert_eq!(Into::<String>::into(colored), "38;5;255");
|
assert_eq!(Into::<String>::into(colored), "38;5;255");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,17 +2,17 @@
|
|||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::{Attribute, Color, StyledContent};
|
use crate::style::{Attribute, Color, StyledContent};
|
||||||
|
|
||||||
/// A content style.
|
/// A content style.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ContentStyle {
|
pub struct ContentStyle {
|
||||||
/// The foreground color.
|
/// The foreground color.
|
||||||
pub fg_color: Option<Color>,
|
pub foreground_color: Option<Color>,
|
||||||
/// The background color.
|
/// The background color.
|
||||||
pub bg_color: Option<Color>,
|
pub background_color: Option<Color>,
|
||||||
/// List of attributes.
|
/// List of attributes.
|
||||||
pub attrs: Vec<Attribute>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentStyle {
|
impl ContentStyle {
|
||||||
@ -28,13 +28,13 @@ impl ContentStyle {
|
|||||||
|
|
||||||
/// Sets the background color.
|
/// Sets the background color.
|
||||||
pub fn background(mut self, color: Color) -> ContentStyle {
|
pub fn background(mut self, color: Color) -> ContentStyle {
|
||||||
self.bg_color = Some(color);
|
self.background_color = Some(color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the foreground color.
|
/// Sets the foreground color.
|
||||||
pub fn foreground(mut self, color: Color) -> ContentStyle {
|
pub fn foreground(mut self, color: Color) -> ContentStyle {
|
||||||
self.fg_color = Some(color);
|
self.foreground_color = Some(color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,14 +42,14 @@ impl ContentStyle {
|
|||||||
///
|
///
|
||||||
/// You can add more attributes by calling this method multiple times.
|
/// You can add more attributes by calling this method multiple times.
|
||||||
pub fn attribute(mut self, attr: Attribute) -> ContentStyle {
|
pub fn attribute(mut self, attr: Attribute) -> ContentStyle {
|
||||||
self.attrs.push(attr);
|
self.attributes.push(attr);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{Attribute, Color, ContentStyle};
|
use crate::style::{Attribute, Color, ContentStyle};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_set_fg_bg_add_attr() {
|
fn test_set_fg_bg_add_attr() {
|
||||||
@ -58,9 +58,9 @@ mod tests {
|
|||||||
.background(Color::Red)
|
.background(Color::Red)
|
||||||
.attribute(Attribute::Reset);
|
.attribute(Attribute::Reset);
|
||||||
|
|
||||||
assert_eq!(content_style.fg_color, Some(Color::Blue));
|
assert_eq!(content_style.foreground_color, Some(Color::Blue));
|
||||||
assert_eq!(content_style.bg_color, Some(Color::Red));
|
assert_eq!(content_style.background_color, Some(Color::Red));
|
||||||
assert_eq!(content_style.attrs[0], Attribute::Reset);
|
assert_eq!(content_style.attributes[0], Attribute::Reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -72,8 +72,8 @@ mod tests {
|
|||||||
|
|
||||||
let styled_content = content_style.apply("test");
|
let styled_content = content_style.apply("test");
|
||||||
|
|
||||||
assert_eq!(styled_content.style().fg_color, Some(Color::Blue));
|
assert_eq!(styled_content.style().foreground_color, Some(Color::Blue));
|
||||||
assert_eq!(styled_content.style().bg_color, Some(Color::Red));
|
assert_eq!(styled_content.style().background_color, Some(Color::Red));
|
||||||
assert_eq!(styled_content.style().attrs[0], Attribute::Reset);
|
assert_eq!(styled_content.style().attributes[0], Attribute::Reset);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
pub use self::{attribute::Attribute, color::Color, colored::Colored};
|
pub(crate) use self::colored::Colored;
|
||||||
|
pub use self::{attribute::Attribute, color::Color};
|
||||||
|
|
||||||
mod attribute;
|
mod attribute;
|
||||||
mod color;
|
mod color;
|
||||||
|
@ -3,7 +3,7 @@ use std::fmt::Display;
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::super::SetAttr;
|
use super::super::SetAttribute;
|
||||||
|
|
||||||
/// Represents an attribute.
|
/// Represents an attribute.
|
||||||
///
|
///
|
||||||
@ -37,7 +37,7 @@ use super::super::SetAttr;
|
|||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use crossterm::Attribute;
|
/// use crossterm::style::Attribute;
|
||||||
///
|
///
|
||||||
/// println!(
|
/// println!(
|
||||||
/// "{} Underlined {} No Underline",
|
/// "{} Underlined {} No Underline",
|
||||||
@ -49,7 +49,7 @@ use super::super::SetAttr;
|
|||||||
/// Style existing text:
|
/// Style existing text:
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use crossterm::Styler;
|
/// use crossterm::style::Styler;
|
||||||
///
|
///
|
||||||
/// println!("{}", "Bold text".bold());
|
/// println!("{}", "Bold text".bold());
|
||||||
/// println!("{}", "Underlined text".underlined());
|
/// println!("{}", "Underlined text".underlined());
|
||||||
@ -115,7 +115,7 @@ pub enum Attribute {
|
|||||||
|
|
||||||
impl Display for Attribute {
|
impl Display for Attribute {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
write!(f, "{}", SetAttr(*self))?;
|
write!(f, "{}", SetAttribute(*self))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,46 +1,10 @@
|
|||||||
use std::fmt::Display;
|
use crate::style::Color;
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::{super::color, color::Color};
|
|
||||||
|
|
||||||
/// Represents a foreground or a background color.
|
/// Represents a foreground or a background color.
|
||||||
///
|
|
||||||
/// Can be used to easily change the text colors.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// `Colored` implements `Display` therefore you can use it in any `write` operation.
|
|
||||||
///
|
|
||||||
/// ```no_run
|
|
||||||
/// use crossterm::{Colored, Color};
|
|
||||||
///
|
|
||||||
/// println!("{} Red foreground color", Colored::Fg(Color::Red));
|
|
||||||
/// println!("{} Blue background color", Colored::Bg(Color::Blue));
|
|
||||||
/// ```
|
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
||||||
pub enum Colored {
|
pub(crate) enum Colored {
|
||||||
/// A foreground color.
|
/// A foreground color.
|
||||||
Fg(Color),
|
ForegroundColor(Color),
|
||||||
/// A background color.
|
/// A background color.
|
||||||
Bg(Color),
|
BackgroundColor(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)
|
|
||||||
.map_err(|_| std::fmt::Error)?,
|
|
||||||
Colored::Bg(color) => colored_terminal
|
|
||||||
.set_bg(color)
|
|
||||||
.map_err(|_| std::fmt::Error)?,
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
//! A module that contains all the actions related to the styling of the terminal.
|
|
||||||
//! Like applying attributes to text and changing the foreground and background.
|
|
||||||
|
|
||||||
use crate::utils::Result;
|
|
||||||
|
|
||||||
use super::Color;
|
|
||||||
|
|
||||||
pub(crate) mod ansi;
|
|
||||||
#[cfg(windows)]
|
|
||||||
pub(crate) mod winapi;
|
|
||||||
|
|
||||||
/// This trait defines the actions that can be performed with terminal colors.
|
|
||||||
/// This trait can be implemented so that a concrete implementation of the ITerminalColor can fulfill
|
|
||||||
/// the wishes to work on a specific platform.
|
|
||||||
///
|
|
||||||
/// ## For example:
|
|
||||||
///
|
|
||||||
/// This trait is implemented for `WinApi` (Windows specific) and `ANSI` (Unix specific),
|
|
||||||
/// so that color-related actions can be performed on both UNIX and Windows systems.
|
|
||||||
pub(crate) trait Style: Sync + Send {
|
|
||||||
/// Set the foreground color to the given color.
|
|
||||||
fn set_fg(&self, fg_color: Color) -> Result<()>;
|
|
||||||
/// Set the background color to the given color.
|
|
||||||
fn set_bg(&self, fg_color: Color) -> Result<()>;
|
|
||||||
/// Reset the terminal color to default.
|
|
||||||
fn reset(&self) -> Result<()>;
|
|
||||||
}
|
|
@ -5,14 +5,17 @@ use std::result;
|
|||||||
|
|
||||||
use crate::queue;
|
use crate::queue;
|
||||||
|
|
||||||
use super::{Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttr, SetBg, SetFg, Styler};
|
use crate::style::{
|
||||||
|
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttribute, SetBackgroundColor,
|
||||||
|
SetForegroundColor, Styler,
|
||||||
|
};
|
||||||
|
|
||||||
/// A styled content.
|
/// A styled content.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use crossterm::{style, Color, Attribute};
|
/// use crossterm::style::{style, Color, Attribute};
|
||||||
///
|
///
|
||||||
/// let styled = style("Hello there")
|
/// let styled = style("Hello there")
|
||||||
/// .with(Color::Yellow)
|
/// .with(Color::Yellow)
|
||||||
@ -70,17 +73,17 @@ impl<D: Display + Clone> Display for StyledContent<D> {
|
|||||||
fn fmt(&self, f: &mut Formatter<'_>) -> result::Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter<'_>) -> result::Result<(), fmt::Error> {
|
||||||
let mut reset = false;
|
let mut reset = false;
|
||||||
|
|
||||||
if let Some(bg) = self.style.bg_color {
|
if let Some(bg) = self.style.background_color {
|
||||||
queue!(f, SetBg(bg)).map_err(|_| fmt::Error)?;
|
queue!(f, SetBackgroundColor(bg)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
if let Some(fg) = self.style.fg_color {
|
if let Some(fg) = self.style.foreground_color {
|
||||||
queue!(f, SetFg(fg)).map_err(|_| fmt::Error)?;
|
queue!(f, SetForegroundColor(fg)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for attr in self.style.attrs.iter() {
|
for attr in self.style.attributes.iter() {
|
||||||
queue!(f, SetAttr(*attr)).map_err(|_| fmt::Error)?;
|
queue!(f, SetAttribute(*attr)).map_err(|_| fmt::Error)?;
|
||||||
reset = true;
|
reset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,40 +99,40 @@ impl<D: Display + Clone> Display for StyledContent<D> {
|
|||||||
|
|
||||||
impl<D: Display + Clone> Colorize<D> for StyledContent<D> {
|
impl<D: Display + Clone> Colorize<D> for StyledContent<D> {
|
||||||
// foreground colors
|
// foreground colors
|
||||||
def_color!(fg_color: black => Color::Black);
|
def_color!(foreground_color: black => Color::Black);
|
||||||
def_color!(fg_color: dark_grey => Color::DarkGrey);
|
def_color!(foreground_color: dark_grey => Color::DarkGrey);
|
||||||
def_color!(fg_color: red => Color::Red);
|
def_color!(foreground_color: red => Color::Red);
|
||||||
def_color!(fg_color: dark_red => Color::DarkRed);
|
def_color!(foreground_color: dark_red => Color::DarkRed);
|
||||||
def_color!(fg_color: green => Color::Green);
|
def_color!(foreground_color: green => Color::Green);
|
||||||
def_color!(fg_color: dark_green => Color::DarkGreen);
|
def_color!(foreground_color: dark_green => Color::DarkGreen);
|
||||||
def_color!(fg_color: yellow => Color::Yellow);
|
def_color!(foreground_color: yellow => Color::Yellow);
|
||||||
def_color!(fg_color: dark_yellow => Color::DarkYellow);
|
def_color!(foreground_color: dark_yellow => Color::DarkYellow);
|
||||||
def_color!(fg_color: blue => Color::Blue);
|
def_color!(foreground_color: blue => Color::Blue);
|
||||||
def_color!(fg_color: dark_blue => Color::DarkBlue);
|
def_color!(foreground_color: dark_blue => Color::DarkBlue);
|
||||||
def_color!(fg_color: magenta => Color::Magenta);
|
def_color!(foreground_color: magenta => Color::Magenta);
|
||||||
def_color!(fg_color: dark_magenta => Color::DarkMagenta);
|
def_color!(foreground_color: dark_magenta => Color::DarkMagenta);
|
||||||
def_color!(fg_color: cyan => Color::Cyan);
|
def_color!(foreground_color: cyan => Color::Cyan);
|
||||||
def_color!(fg_color: dark_cyan => Color::DarkCyan);
|
def_color!(foreground_color: dark_cyan => Color::DarkCyan);
|
||||||
def_color!(fg_color: white => Color::White);
|
def_color!(foreground_color: white => Color::White);
|
||||||
def_color!(fg_color: grey => Color::Grey);
|
def_color!(foreground_color: grey => Color::Grey);
|
||||||
|
|
||||||
// background colors
|
// background colors
|
||||||
def_color!(bg_color: on_black => Color::Black);
|
def_color!(background_color: on_black => Color::Black);
|
||||||
def_color!(bg_color: on_dark_grey => Color::DarkGrey);
|
def_color!(background_color: on_dark_grey => Color::DarkGrey);
|
||||||
def_color!(bg_color: on_red => Color::Red);
|
def_color!(background_color: on_red => Color::Red);
|
||||||
def_color!(bg_color: on_dark_red => Color::DarkRed);
|
def_color!(background_color: on_dark_red => Color::DarkRed);
|
||||||
def_color!(bg_color: on_green => Color::Green);
|
def_color!(background_color: on_green => Color::Green);
|
||||||
def_color!(bg_color: on_dark_green => Color::DarkGreen);
|
def_color!(background_color: on_dark_green => Color::DarkGreen);
|
||||||
def_color!(bg_color: on_yellow => Color::Yellow);
|
def_color!(background_color: on_yellow => Color::Yellow);
|
||||||
def_color!(bg_color: on_dark_yellow => Color::DarkYellow);
|
def_color!(background_color: on_dark_yellow => Color::DarkYellow);
|
||||||
def_color!(bg_color: on_blue => Color::Blue);
|
def_color!(background_color: on_blue => Color::Blue);
|
||||||
def_color!(bg_color: on_dark_blue => Color::DarkBlue);
|
def_color!(background_color: on_dark_blue => Color::DarkBlue);
|
||||||
def_color!(bg_color: on_magenta => Color::Magenta);
|
def_color!(background_color: on_magenta => Color::Magenta);
|
||||||
def_color!(bg_color: on_dark_magenta => Color::DarkMagenta);
|
def_color!(background_color: on_dark_magenta => Color::DarkMagenta);
|
||||||
def_color!(bg_color: on_cyan => Color::Cyan);
|
def_color!(background_color: on_cyan => Color::Cyan);
|
||||||
def_color!(bg_color: on_dark_cyan => Color::DarkCyan);
|
def_color!(background_color: on_dark_cyan => Color::DarkCyan);
|
||||||
def_color!(bg_color: on_white => Color::White);
|
def_color!(background_color: on_white => Color::White);
|
||||||
def_color!(bg_color: on_grey => Color::Grey);
|
def_color!(background_color: on_grey => Color::Grey);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Display + Clone> Styler<D> for StyledContent<D> {
|
impl<D: Display + Clone> Styler<D> for StyledContent<D> {
|
||||||
@ -164,10 +167,10 @@ mod tests {
|
|||||||
.on(Color::Magenta)
|
.on(Color::Magenta)
|
||||||
.attribute(Attribute::NoItalic);
|
.attribute(Attribute::NoItalic);
|
||||||
|
|
||||||
assert_eq!(styled_content.style.fg_color, Some(Color::Green));
|
assert_eq!(styled_content.style.foreground_color, Some(Color::Green));
|
||||||
assert_eq!(styled_content.style.bg_color, Some(Color::Magenta));
|
assert_eq!(styled_content.style.background_color, Some(Color::Magenta));
|
||||||
assert_eq!(styled_content.style.attrs.len(), 2);
|
assert_eq!(styled_content.style.attributes.len(), 2);
|
||||||
assert_eq!(styled_content.style.attrs[0], Attribute::Reset);
|
assert_eq!(styled_content.style.attributes[0], Attribute::Reset);
|
||||||
assert_eq!(styled_content.style.attrs[1], Attribute::NoItalic);
|
assert_eq!(styled_content.style.attributes[1], Attribute::NoItalic);
|
||||||
}
|
}
|
||||||
}
|
}
|
2
src/style/sys.rs
Normal file
2
src/style/sys.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#[cfg(windows)]
|
||||||
|
pub(crate) mod windows;
|
@ -1,6 +1,3 @@
|
|||||||
//! This is a `WinApi` specific implementation for styling related action.
|
|
||||||
//! This module is used for non supporting `ANSI` Windows terminals.
|
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer};
|
use crossterm_winapi::{Console, Handle, HandleType, ScreenBuffer};
|
||||||
@ -10,7 +7,7 @@ use lazy_static::lazy_static;
|
|||||||
|
|
||||||
use crate::utils::Result;
|
use crate::utils::Result;
|
||||||
|
|
||||||
use super::super::{Color, Colored, Style};
|
use super::super::{Color, Colored};
|
||||||
|
|
||||||
const FG_GREEN: u16 = wincon::FOREGROUND_GREEN;
|
const FG_GREEN: u16 = wincon::FOREGROUND_GREEN;
|
||||||
const FG_RED: u16 = wincon::FOREGROUND_RED;
|
const FG_RED: u16 = wincon::FOREGROUND_RED;
|
||||||
@ -22,80 +19,98 @@ const BG_RED: u16 = wincon::BACKGROUND_RED;
|
|||||||
const BG_BLUE: u16 = wincon::BACKGROUND_BLUE;
|
const BG_BLUE: u16 = wincon::BACKGROUND_BLUE;
|
||||||
const BG_INTENSITY: u16 = wincon::BACKGROUND_INTENSITY;
|
const BG_INTENSITY: u16 = wincon::BACKGROUND_INTENSITY;
|
||||||
|
|
||||||
/// This struct is a WinApi implementation for color related actions.
|
pub(crate) fn set_foreground_color(fg_color: Color) -> Result<()> {
|
||||||
pub(crate) struct WinApiColor;
|
init_console_color()?;
|
||||||
|
|
||||||
impl WinApiColor {
|
let color_value: u16 = Colored::ForegroundColor(fg_color).into();
|
||||||
pub fn new() -> Box<WinApiColor> {
|
|
||||||
init_console_color().unwrap();
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
Box::from(WinApiColor)
|
let csbi = screen_buffer.info()?;
|
||||||
|
|
||||||
|
// Notice that the color values are stored in wAttribute.
|
||||||
|
// So we need to use bitwise operators to check if the values exists or to get current console colors.
|
||||||
|
let mut color: u16;
|
||||||
|
let attrs = csbi.attributes();
|
||||||
|
let bg_color = attrs & 0x0070;
|
||||||
|
color = color_value | bg_color;
|
||||||
|
|
||||||
|
// background intensity is a separate value in attrs,
|
||||||
|
// wee need to check if this was applied to the current bg color.
|
||||||
|
if (attrs & wincon::BACKGROUND_INTENSITY as u16) != 0 {
|
||||||
|
color = color | wincon::BACKGROUND_INTENSITY as u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console::from(**screen_buffer.handle()).set_text_attribute(color)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style for WinApiColor {
|
pub(crate) fn set_background_color(bg_color: Color) -> Result<()> {
|
||||||
fn set_fg(&self, fg_color: Color) -> Result<()> {
|
init_console_color()?;
|
||||||
let color_value: u16 = Colored::Fg(fg_color).into();
|
|
||||||
|
|
||||||
|
let color_value: u16 = Colored::BackgroundColor(bg_color).into();
|
||||||
|
|
||||||
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
|
let csbi = screen_buffer.info()?;
|
||||||
|
|
||||||
|
// Notice that the color values are stored in wAttribute.
|
||||||
|
// So wee need to use bitwise operators to check if the values exists or to get current console colors.
|
||||||
|
let mut color: u16;
|
||||||
|
let attrs = csbi.attributes();
|
||||||
|
let fg_color = attrs & 0x0007;
|
||||||
|
color = fg_color | color_value;
|
||||||
|
|
||||||
|
// Foreground intensity is a separate value in attrs,
|
||||||
|
// So we need to check if this was applied to the current fg color.
|
||||||
|
if (attrs & wincon::FOREGROUND_INTENSITY as u16) != 0 {
|
||||||
|
color = color | wincon::FOREGROUND_INTENSITY as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::from(**screen_buffer.handle()).set_text_attribute(color)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn reset() -> Result<()> {
|
||||||
|
let original_color = original_console_color();
|
||||||
|
|
||||||
|
Console::from(Handle::new(HandleType::CurrentOutputHandle)?)
|
||||||
|
.set_text_attribute(original_color)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes the default console color. It will will be skipped if it has already been initialized.
|
||||||
|
pub(crate) fn init_console_color() -> Result<()> {
|
||||||
|
let mut locked_pos = ORIGINAL_CONSOLE_COLOR.lock().unwrap();
|
||||||
|
|
||||||
|
if locked_pos.is_none() {
|
||||||
let screen_buffer = ScreenBuffer::current()?;
|
let screen_buffer = ScreenBuffer::current()?;
|
||||||
let csbi = screen_buffer.info()?;
|
let attr = screen_buffer.info()?.attributes();
|
||||||
|
*locked_pos = Some(attr);
|
||||||
// Notice that the color values are stored in wAttribute.
|
|
||||||
// So we need to use bitwise operators to check if the values exists or to get current console colors.
|
|
||||||
let mut color: u16;
|
|
||||||
let attrs = csbi.attributes();
|
|
||||||
let bg_color = attrs & 0x0070;
|
|
||||||
color = color_value | bg_color;
|
|
||||||
|
|
||||||
// background intensity is a separate value in attrs,
|
|
||||||
// wee need to check if this was applied to the current bg color.
|
|
||||||
if (attrs & wincon::BACKGROUND_INTENSITY as u16) != 0 {
|
|
||||||
color = color | wincon::BACKGROUND_INTENSITY as u16;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::from(**screen_buffer.handle()).set_text_attribute(color)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_bg(&self, bg_color: Color) -> Result<()> {
|
Ok(())
|
||||||
let color_value: u16 = Colored::Bg(bg_color).into();
|
}
|
||||||
|
|
||||||
let screen_buffer = ScreenBuffer::current()?;
|
/// Returns the original console color, make sure to call `init_console_color` before calling this function. Otherwise this function will panic.
|
||||||
let csbi = screen_buffer.info()?;
|
pub(crate) fn original_console_color() -> u16 {
|
||||||
|
// safe unwrap, initial console color was set with `init_console_color` in `WinApiColor::new()`
|
||||||
|
ORIGINAL_CONSOLE_COLOR
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.expect("Initial console color not set")
|
||||||
|
}
|
||||||
|
|
||||||
// Notice that the color values are stored in wAttribute.
|
lazy_static! {
|
||||||
// So wee need to use bitwise operators to check if the values exists or to get current console colors.
|
static ref ORIGINAL_CONSOLE_COLOR: Mutex<Option<u16>> = Mutex::new(None);
|
||||||
let mut color: u16;
|
|
||||||
let attrs = csbi.attributes();
|
|
||||||
let fg_color = attrs & 0x0007;
|
|
||||||
color = fg_color | color_value;
|
|
||||||
|
|
||||||
// Foreground intensity is a separate value in attrs,
|
|
||||||
// So we need to check if this was applied to the current fg color.
|
|
||||||
if (attrs & wincon::FOREGROUND_INTENSITY as u16) != 0 {
|
|
||||||
color = color | wincon::FOREGROUND_INTENSITY as u16;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console::from(**screen_buffer.handle()).set_text_attribute(color)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reset(&self) -> Result<()> {
|
|
||||||
let original_color = original_console_color();
|
|
||||||
|
|
||||||
Console::from(Handle::new(HandleType::CurrentOutputHandle)?)
|
|
||||||
.set_text_attribute(original_color)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Colored> for u16 {
|
impl From<Colored> for u16 {
|
||||||
/// Returns the WinApi color value (u16) from the `Colored` struct.
|
/// Returns the WinApi color value (u16) from the `Colored` struct.
|
||||||
fn from(colored: Colored) -> Self {
|
fn from(colored: Colored) -> Self {
|
||||||
match colored {
|
match colored {
|
||||||
Colored::Fg(color) => {
|
Colored::ForegroundColor(color) => {
|
||||||
match color {
|
match color {
|
||||||
Color::Black => 0,
|
Color::Black => 0,
|
||||||
Color::DarkGrey => FG_INTENSITY,
|
Color::DarkGrey => FG_INTENSITY,
|
||||||
@ -128,7 +143,7 @@ impl From<Colored> for u16 {
|
|||||||
Color::AnsiValue(_val) => 0,
|
Color::AnsiValue(_val) => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Colored::Bg(color) => {
|
Colored::BackgroundColor(color) => {
|
||||||
match color {
|
match color {
|
||||||
Color::Black => 0,
|
Color::Black => 0,
|
||||||
Color::DarkGrey => BG_INTENSITY,
|
Color::DarkGrey => BG_INTENSITY,
|
||||||
@ -163,48 +178,22 @@ impl From<Colored> for u16 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the default console color. It will will be skipped if it has already been initialized.
|
|
||||||
fn init_console_color() -> Result<()> {
|
|
||||||
let mut locked_pos = ORIGINAL_CONSOLE_COLOR.lock().unwrap();
|
|
||||||
|
|
||||||
if locked_pos.is_none() {
|
|
||||||
let screen_buffer = ScreenBuffer::current()?;
|
|
||||||
let attr = screen_buffer.info()?.attributes();
|
|
||||||
*locked_pos = Some(attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the original console color, make sure to call `init_console_color` before calling this function. Otherwise this function will panic.
|
|
||||||
fn original_console_color() -> u16 {
|
|
||||||
// safe unwrap, initial console color was set with `init_console_color` in `WinApiColor::new()`
|
|
||||||
ORIGINAL_CONSOLE_COLOR
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.expect("Initial console color not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref ORIGINAL_CONSOLE_COLOR: Mutex<Option<u16>> = Mutex::new(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
Color, Colored, WinApiColor, BG_INTENSITY, BG_RED, FG_INTENSITY, FG_RED,
|
Color, Colored, BG_INTENSITY, BG_RED, FG_INTENSITY, FG_RED, ORIGINAL_CONSOLE_COLOR,
|
||||||
ORIGINAL_CONSOLE_COLOR,
|
|
||||||
};
|
};
|
||||||
|
use crate::style::sys::windows::set_foreground_color;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_fg_color() {
|
fn test_parse_fg_color() {
|
||||||
let colored = Colored::Fg(Color::Red);
|
let colored = Colored::ForegroundColor(Color::Red);
|
||||||
assert_eq!(Into::<u16>::into(colored), FG_INTENSITY | FG_RED);
|
assert_eq!(Into::<u16>::into(colored), FG_INTENSITY | FG_RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_bg_color() {
|
fn test_parse_bg_color() {
|
||||||
let colored = Colored::Bg(Color::Red);
|
let colored = Colored::BackgroundColor(Color::Red);
|
||||||
assert_eq!(Into::<u16>::into(colored), BG_INTENSITY | BG_RED);
|
assert_eq!(Into::<u16>::into(colored), BG_INTENSITY | BG_RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +202,7 @@ mod tests {
|
|||||||
assert!(ORIGINAL_CONSOLE_COLOR.lock().unwrap().is_none());
|
assert!(ORIGINAL_CONSOLE_COLOR.lock().unwrap().is_none());
|
||||||
|
|
||||||
// will call `init_console_color`
|
// will call `init_console_color`
|
||||||
let _ = WinApiColor::new();
|
set_foreground_color(Color::Blue).unwrap();
|
||||||
|
|
||||||
assert!(ORIGINAL_CONSOLE_COLOR.lock().unwrap().is_some());
|
assert!(ORIGINAL_CONSOLE_COLOR.lock().unwrap().is_some());
|
||||||
}
|
}
|
@ -12,7 +12,7 @@ use super::StyledContent;
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use crossterm::Colorize;
|
/// use crossterm::style::Colorize;
|
||||||
///
|
///
|
||||||
/// let styled_text = "Red foreground color on blue background.".red().on_blue();
|
/// let styled_text = "Red foreground color on blue background.".red().on_blue();
|
||||||
/// println!("{}", styled_text);
|
/// println!("{}", styled_text);
|
||||||
@ -60,7 +60,7 @@ pub trait Colorize<D: Display + Clone> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```no_run
|
/// ```no_run
|
||||||
/// use crossterm::Styler;
|
/// use crossterm::style::Styler;
|
||||||
///
|
///
|
||||||
/// println!("{}", "Bold text".bold());
|
/// println!("{}", "Bold text".bold());
|
||||||
/// println!("{}", "Underlined text".underlined());
|
/// println!("{}", "Underlined text".underlined());
|
||||||
|
Loading…
Reference in New Issue
Block a user