Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and Expose Methods of easily Creating and Mutating ColoredString's and Style's for Users #154

Merged
merged 35 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
aa6d070
Initial change (Deref<Target = String> + DerefMut for ColoredString).
JustAnotherCodemonkey Dec 3, 2023
eeeb841
Add an example of modifying a ColoredString's text content with Deref…
JustAnotherCodemonkey Dec 3, 2023
528ef77
Add methods copy_fgcolor, copy_bgcolor, and copy_style to ColoredString.
JustAnotherCodemonkey Dec 3, 2023
b02b864
Create traits Colorized and CopyColorize, moved style copying functio…
JustAnotherCodemonkey Dec 3, 2023
6f530a3
Create, implement, and expose methods of creating and modifying Style…
JustAnotherCodemonkey Dec 3, 2023
2d04660
Fmt + add new_from method to StyleTemplate.
JustAnotherCodemonkey Dec 3, 2023
d93fe2c
Since Style now implements default, move Default impls for ColoredStr…
JustAnotherCodemonkey Dec 3, 2023
f1b5252
Improve docs for StyleTemplate and espeically Style to be more helpful.
JustAnotherCodemonkey Dec 3, 2023
ffa2c13
Add builder pattern methods to Style to make them easier to construct…
JustAnotherCodemonkey Dec 4, 2023
a3004e1
Add ColorizedMut trait for univeral direct color and style setting.
JustAnotherCodemonkey Dec 4, 2023
79dac37
Impl FromIterator<Styles> for Style and update docs to mention and us…
JustAnotherCodemonkey Dec 4, 2023
f349cd1
Fix docs (remove mention in docs for Style of CLEAR which is private).
JustAnotherCodemonkey Dec 4, 2023
57186f5
Move tests for Style bitwise operations into their own testing submod…
JustAnotherCodemonkey Dec 4, 2023
91dbdd3
Fix typos introduced in this branch.
JustAnotherCodemonkey Dec 4, 2023
ec313f0
Add big docs for ColoredString in light of all the new implementation…
JustAnotherCodemonkey Dec 5, 2023
2ec9393
Make doc examples for Style more readable.
JustAnotherCodemonkey Dec 5, 2023
9b8ade8
Add impls of bitwise logic ops for Styles for quick creation of Style…
JustAnotherCodemonkey Dec 6, 2023
21fc6d4
Remove StyleTemplate as it didn't really serve enough purpose to just…
JustAnotherCodemonkey Dec 7, 2023
0e73f6b
Add clearing methods to ColorizedMut, updated docs to not use 'set to…
JustAnotherCodemonkey Dec 7, 2023
aa8baa5
Change section headers for Style docs to be h2's because they look ni…
JustAnotherCodemonkey Dec 7, 2023
6b77b80
Touch up doc for CopyColorize.
JustAnotherCodemonkey Dec 7, 2023
53d1b17
Merge from master.
JustAnotherCodemonkey Dec 7, 2023
56abf18
Touch up ColorizedMut doc and fix some typos.
JustAnotherCodemonkey Dec 7, 2023
00458b3
Expose fields of ColoredString, remove Colored, ColoredMut, and CopyC…
JustAnotherCodemonkey Dec 7, 2023
54add72
Add note in crate root docs about ColoredString and to see its docs f…
JustAnotherCodemonkey Dec 7, 2023
bc30115
Remove modifying_colored_strings example as it was perfectly well exp…
JustAnotherCodemonkey Dec 7, 2023
ee96c49
Update CHANGELOG.md
JustAnotherCodemonkey Dec 8, 2023
159a6fc
Remove ColoredString.input.[str method] antipattern from docs.
JustAnotherCodemonkey Dec 8, 2023
95d6f4f
Oops. diff.txt was temp and not supposed to be in there
JustAnotherCodemonkey Dec 8, 2023
aa7b652
Add missing assign ops involving Styles and add missing tests for ops.
JustAnotherCodemonkey Dec 8, 2023
8a5f549
Add with_style and with_color_and_style methods to Colorize (I can't …
JustAnotherCodemonkey Dec 8, 2023
94e12e7
Reset <ColoredString as Deref>::Target to str and change docs and cha…
JustAnotherCodemonkey Dec 8, 2023
f30fec9
Remove with_style and with_color_and_style from Colorize (they might …
JustAnotherCodemonkey Dec 12, 2023
3076389
Merge from master.
JustAnotherCodemonkey Dec 12, 2023
bf08f1d
Somehow the merge messed some formatting up.
JustAnotherCodemonkey Dec 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Unreleased

- Updated top-level docs to include a note about `ColoredString`\'s role in the `Colorize` pipeline as well as link to it to suggest learning more about how to manipulate existing `ColoredString`\'s.
- Changes to `ColoredString`:
- Expose fields.
- **[DEPRECATION]:** Deprecated methods `fgcolor`, `bgcolor`, and `style` due to their obsolescence in the face of the exposing of their represented fields.
- Add methods for clearing specific elements of `fgcolor`, `bgcolor`, and `style`.
- Change Default implementation to be via derive as Style now implements Default (see changes to Style below).
- Add implementation of `DerefMut`.
- Updated docs to reflect the above changes as well as generally greatly expand them.
- Changes to `Style`:
- Implemented `Default` for `Style` (returns `CLEAR`). This exposes a method by which users can create plain `Style`\'s from scratch.
- Implemented `From<Styles>` for `Style`. This lets users easily create `Style`\'s from specific styles.
- Exposed previously private method `add`.
- Created method `remove` which essentially does the opposite.
- Added builder-style methods in the vein of `Colorize` to add stylings (e.g. `bold`, `underline`, `italic`, `strikethrough`).
- Implemented bitwise operators `BitAnd`, `BitOr`, `BitXor`, and `Not` as well as their representative assignment operators. You can also use a `Styles` as an operand for these.
- Implemented `FromIterator<Styles>` for Style.
- Changes to `Styles`:
- Implemented bitwise operators `BitAnd`, `BitOr`, `BitXor`, and `Not` which all combine `Styles`\'s and output `Style`\'s. These can also take a `Style` as an operand.
- Added additional testing for all of the above changes.
- Added methods `with_style` and `with_color_and_style` to `Colorize`.

# 2.0.4
- Switch from `winapi` to `windows-sys`.

Expand Down
162 changes: 144 additions & 18 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
//!
//! See [the `Colorize` trait](./trait.Colorize.html) for all the methods.
//!
//! Note: The methods of [`Colorize`], when used on [`str`]'s, return
//! [`ColoredString`]'s. See [`ColoredString`] to learn more about them and
//! what you can do with them beyond continue to use [`Colorize`] to further
//! modify them.
#![warn(missing_docs)]

extern crate is_terminal;
Expand All @@ -43,17 +47,93 @@ pub mod customcolors;

pub use color::*;

use std::{borrow::Cow, fmt, ops::Deref};
use std::{
borrow::Cow,
fmt,
ops::{Deref, DerefMut},
};

pub use style::{Style, Styles};

/// A string that may have color and/or style applied to it.
#[derive(Clone, Debug, PartialEq, Eq)]
///
/// Commonly created via calling the methods of [`Colorize`] on a &str.
/// All methods of [`Colorize`] either create a new `ColoredString` from
/// the type called on or modify a callee `ColoredString`. See
/// [`Colorize`] for more.
///
/// The primary usage of `ColoredString`'s is as a way to take text,
/// apply colors and miscillaneous styling to it (such as bold or
/// underline), and then use it to create formatted strings that print
/// to the console with the special styling applied.
///
/// ## Usage
///
/// As stated, `ColoredString`'s, once created, can be printed to the
/// console with their colors and style or turned into a string
/// containing special console codes that has the same effect.
/// This is made easy via `ColoredString`'s implementations of
/// [`Display`](std::fmt::Display) and [`ToString`] for those purposes
/// respectively.
///
/// Printing a `ColoredString` with its style is as easy as:
///
/// ```
/// # use colored::*;
/// let cstring: ColoredString = "Bold and Red!".bold().red();
/// println!("{}", cstring);
/// ```
///
/// ## Manipulating the coloring/style of a `ColoredString`
///
/// Getting or changing the foreground color, background color, and or
/// style of a `ColoredString` is as easy as manually reading / modifying
/// the fields of `ColoredString`.
///
/// ```
/// # use colored::*;
/// let mut red_text = "Red".red();
/// // Changing color using re-assignment and [`Colorize`]:
/// red_text = red_text.blue();
/// // Manipulating fields of `ColoredString` in-place:
/// red_text.fgcolor = Some(Color::Blue);
///
/// let styled_text1 = "Bold".bold();
/// let styled_text2 = "Italic".italic();
/// let mut styled_text3 = ColoredString::from("Bold and Italic");
/// styled_text3.style = styled_text1.style | styled_text2.style;
/// ```
///
/// ## Modifying the text of a `ColoredString`
///
/// Modifying the text is as easy as modifying the `input` field of
/// `ColoredString`...
///
/// ```
/// # use colored::*;
/// let mut colored_text = "Magenta".magenta();
/// colored_text = colored_text.blue();
/// colored_text.input = "Blue".to_string();
/// // Note: The above is inefficient and `colored_text.input.replace_range(.., "Blue")` would
/// // be more proper. This is just for example.
///
/// assert_eq!(&*colored_text, "Blue");
/// ```
///
/// Notice how this process preserves the coloring and style.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct ColoredString {
input: String,
fgcolor: Option<Color>,
bgcolor: Option<Color>,
style: style::Style,
/// The plain text that will have color and style applied to it.
pub input: String,
/// The color of the text as it will be printed.
pub fgcolor: Option<Color>,
/// The background color (if any). None means that the text will be printed
/// without a special background.
pub bgcolor: Option<Color>,
/// Any special styling to be applied to the text (see Styles for a list of
/// available options).
pub style: style::Style,
}

/// The trait that enables something to be given color.
Expand Down Expand Up @@ -327,6 +407,8 @@ pub trait Colorize {
fn reversed(self) -> ColoredString;
fn hidden(self) -> ColoredString;
fn strikethrough(self) -> ColoredString;
fn with_style<S: Into<Style>>(self, style: S) -> ColoredString;
fn with_color_and_style(self, other: &ColoredString) -> ColoredString;
}

impl ColoredString {
Expand All @@ -339,6 +421,7 @@ impl ColoredString {
/// let cstr = cstr.clear();
/// assert_eq!(cstr.fgcolor(), None);
/// ```
#[deprecated(note = "Deprecated due to the exposing of the fgcolor struct field.")]
pub fn fgcolor(&self) -> Option<Color> {
self.fgcolor.as_ref().copied()
}
Expand All @@ -352,6 +435,7 @@ impl ColoredString {
/// let cstr = cstr.clear();
/// assert_eq!(cstr.bgcolor(), None);
/// ```
#[deprecated(note = "Deprecated due to the exposing of the bgcolor struct field.")]
pub fn bgcolor(&self) -> Option<Color> {
self.bgcolor.as_ref().copied()
}
Expand All @@ -365,10 +449,28 @@ impl ColoredString {
/// assert_eq!(colored.style().contains(Styles::Italic), true);
/// assert_eq!(colored.style().contains(Styles::Dimmed), false);
/// ```
#[deprecated(note = "Deprecated due to the exposing of the style struct field.")]
pub fn style(&self) -> style::Style {
self.style
}

/// Clears foreground coloring on this `ColoredString`, meaning that it
/// will be printed with the default terminal text color.
pub fn clear_fgcolor(&mut self) {
self.fgcolor = None;
}

/// Gets rid of this `ColoredString`'s background.
pub fn clear_bgcolor(&mut self) {
self.bgcolor = None;
}

/// Clears any special styling and sets it back to the default (plain,
/// maybe colored, text).
pub fn clear_style(&mut self) {
self.style = Style::default();
}

/// Checks if the colored string has no color or styling.
///
/// ```rust
Expand Down Expand Up @@ -461,24 +563,19 @@ impl ColoredString {
}
}

impl Default for ColoredString {
fn default() -> Self {
ColoredString {
input: String::default(),
fgcolor: None,
bgcolor: None,
style: style::CLEAR,
}
}
}

impl Deref for ColoredString {
type Target = str;
fn deref(&self) -> &str {
fn deref(&self) -> &Self::Target {
&self.input
}
}

impl DerefMut for ColoredString {
fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
&mut self.input
}
}

impl From<String> for ColoredString {
fn from(s: String) -> Self {
ColoredString {
Expand Down Expand Up @@ -506,6 +603,16 @@ impl Colorize for ColoredString {
self.bgcolor = Some(color.into());
self
}
fn with_style<S: Into<Style>>(mut self, style: S) -> ColoredString {
self.style = style.into();
self
}
fn with_color_and_style(mut self, other: &ColoredString) -> ColoredString {
self.fgcolor = other.fgcolor;
self.bgcolor = other.bgcolor;
self.style = other.style;
self
}

fn clear(self) -> ColoredString {
ColoredString {
Expand Down Expand Up @@ -570,6 +677,23 @@ impl<'a> Colorize for &'a str {
}
}

fn with_style<S: Into<Style>>(self, style: S) -> ColoredString {
ColoredString {
input: self.to_string(),
style: style.into(),
..Default::default()
}
}

fn with_color_and_style(self, other: &ColoredString) -> ColoredString {
ColoredString {
input: self.to_string(),
fgcolor: other.fgcolor,
bgcolor: other.bgcolor,
style: other.style,
}
}

fn clear(self) -> ColoredString {
ColoredString {
input: String::from(self),
Expand Down Expand Up @@ -849,6 +973,8 @@ mod tests {

#[test]
fn exposing_tests() {
#![allow(deprecated)]

let cstring = "".red();
assert_eq!(cstring.fgcolor(), Some(Color::Red));
assert_eq!(cstring.bgcolor(), None);
Expand Down
Loading