use std::{
ops::Add,
fmt::{
Display,
Formatter,
Result as FmtResult
}
};
use crate::{
ColorFormattable,
Color,
TextStyle
};
#[derive(Debug, Clone, PartialEq)]
pub struct ColoredString {
content: String
}
impl ColoredString {
pub fn new<T: ToString>(text: T) -> Self {
Self {
content: text.to_string()
}
}
pub fn fg<C: ColorFormattable>(text: impl ToString, color: C) -> Self {
let formatted: String = format!("{}{}{}", Color::new(color, false), text.to_string(), Color::new(TextStyle::Reset, false));
Self {
content: formatted
}
}
pub fn bg<C: ColorFormattable>(text: impl ToString, color: C) -> Self {
let formatted: String = format!("{}{}{}", Color::new(color, true), text.to_string(), Color::new(TextStyle::Reset, false));
Self {
content: formatted
}
}
pub fn styled<F: ColorFormattable, B: ColorFormattable>(text: impl ToString, fg: F, bg: B) -> Self {
let formatted: String = format!("{}{}{}{}", Color::new(bg, true), Color::new(fg, false), text.to_string(), Color::new(TextStyle::Reset, false));
Self {
content: formatted
}
}
pub fn style<S: ColorFormattable>(text: impl ToString, style: S) -> Self {
let formatted: String = format!("{}{}{}", Color::new(style, false), text.to_string(), Color::new(TextStyle::Reset, false));
Self {
content: formatted
}
}
pub fn plain(text: impl ToString) -> Self {
Self {
content: text.to_string()
}
}
pub fn append(&mut self, other: impl Into<ColoredString>) -> () {
(&mut self.content).push_str(&other.into().content);
}
pub fn prepend(&mut self, other: impl Into<ColoredString>) -> () {
let new_content: String = format!("{}{}", other.into().content, self.content);
self.content = new_content;
}
pub fn as_str(&self) -> &str {
&self.content
}
pub fn len(&self) -> usize {
self.content.len()
}
pub fn is_empty(&self) -> bool {
self.content.is_empty()
}
pub fn clear(&mut self) {
(&mut self.content).clear();
}
pub fn bold(self) -> Self {
self.apply_style(TextStyle::Bold)
}
pub fn dim(self) -> Self {
self.apply_style(TextStyle::Dim)
}
pub fn italic(self) -> Self {
self.apply_style(TextStyle::Italic)
}
pub fn underline(self) -> Self {
self.apply_style(TextStyle::Underline)
}
pub fn blink(self) -> Self {
self.apply_style(TextStyle::Blink)
}
pub fn blink_rapid(self) -> Self {
self.apply_style(TextStyle::BlinkRapid)
}
pub fn reverse(self) -> Self {
self.apply_style(TextStyle::Reverse)
}
pub fn hidden(self) -> Self {
self.apply_style(TextStyle::Hidden)
}
pub fn strikethrough(self) -> Self {
self.apply_style(TextStyle::Strikethrough)
}
pub fn reset(self) -> Self {
self.apply_style(TextStyle::Reset)
}
fn apply_style(self, style: TextStyle) -> Self {
let styled_content: String = format!("{}{}{}", Color::new(style, false), self.content, Color::new(TextStyle::Reset, false));
Self {
content: styled_content
}
}
pub fn color<C: ColorFormattable>(self, color: C) -> Self {
let colored_content: String = format!("{}{}{}", Color::new(color, false), self.content, Color::new(TextStyle::Reset, false));
Self {
content: colored_content
}
}
pub fn on_color<C: ColorFormattable>(self, color: C) -> Self {
let bg_content: String = format!("{}{}{}", Color::new(color, true), self.content, Color::new(TextStyle::Reset, false));
Self {
content: bg_content
}
}
}
impl Display for ColoredString {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "{}", self.content)
}
}
impl From<String> for ColoredString {
fn from(s: String) -> Self {
Self::plain(s)
}
}
impl From<&str> for ColoredString {
fn from(s: &str) -> Self {
Self::plain(s)
}
}
impl From<ColoredString> for String {
fn from(cs: ColoredString) -> Self {
cs.content
}
}
impl Add for ColoredString {
type Output = Self;
fn add(self, other: Self) -> Self {
Self {
content: format!("{}{}", self.content, other.content)
}
}
}
impl Add<&str> for ColoredString {
type Output = Self;
fn add(self, other: &str) -> Self {
Self {
content: format!("{}{}", self.content, other)
}
}
}
impl Add<String> for ColoredString {
type Output = Self;
fn add(self, other: String) -> Self {
Self {
content: format!("{}{}", self.content, other)
}
}
}
impl Add<ColoredString> for &ColoredString {
type Output = ColoredString;
fn add(self, other: ColoredString) -> ColoredString {
ColoredString {
content: format!("{}{}", self.content, other.content)
}
}
}
impl Add<&ColoredString> for ColoredString {
type Output = Self;
fn add(self, other: &Self) -> Self {
Self {
content: format!("{}{}", self.content, other.content)
}
}
}
impl Add<&ColoredString> for &ColoredString {
type Output = ColoredString;
fn add(self, other: &ColoredString) -> ColoredString {
ColoredString {
content: format!("{}{}", self.content, other.content)
}
}
}
impl AsRef<str> for ColoredString {
fn as_ref(&self) -> &str {
&self.content
}
}