Add RichText type

This commit is contained in:
Fabrice Reix 2024-05-29 16:24:05 +02:00
parent e471a9aee6
commit 165077ed21
No known key found for this signature in database
GPG Key ID: BF5213154B2E7155
2 changed files with 128 additions and 0 deletions

View File

@ -19,3 +19,4 @@ pub mod ast;
pub mod error;
pub mod format;
pub mod parser;
pub mod richtext;

View File

@ -0,0 +1,127 @@
/*
* Hurl (https://hurl.dev)
* Copyright (C) 2024 Orange
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
use colored::Colorize;
/// An String with color and style
#[derive(Clone, Debug, PartialEq, Eq)]
#[allow(unused)]
struct RichText<'a> {
tokens: Vec<Token<'a>>,
}
#[allow(unused)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Format {
Plain,
Ansi,
}
#[allow(unused)]
#[derive(Clone, Debug, PartialEq, Eq)]
struct Token<'a> {
content: &'a str,
fg: Option<Color>,
bold: bool,
}
#[allow(unused)]
#[derive(Clone, Debug, PartialEq, Eq)]
enum Color {
Red,
Green,
Blue,
}
#[allow(unused)]
impl<'a> RichText<'a> {
pub fn new() -> RichText<'a> {
RichText { tokens: vec![] }
}
pub fn add_token(&mut self, content: &'a str, fg: Option<Color>, bold: bool) {
let token = Token::new(content, fg, bold);
self.tokens.push(token);
}
pub fn text(mut self, content: &'a str) -> RichText {
self.add_token(content, None, false);
self
}
pub fn red(mut self, content: &'a str) -> RichText {
self.add_token(content, Some(Color::Red), false);
self
}
pub fn to_string(&self, format: Format) -> String {
self.tokens
.iter()
.map(|token| token.to_string(format))
.collect::<Vec<String>>()
.join("")
}
}
impl<'a> Token<'a> {
pub fn new(content: &'a str, fg: Option<Color>, bold: bool) -> Token {
Token { content, fg, bold }
}
pub fn to_string(&self, format: Format) -> String {
match format {
Format::Plain => self.plain(),
Format::Ansi => self.ansi(),
}
}
fn plain(&self) -> String {
self.content.to_string()
}
fn ansi(&self) -> String {
let mut s = self.content.to_string();
if let Some(color) = &self.fg {
s = match color {
Color::Red => s.red().to_string(),
Color::Green => s.green().to_string(),
Color::Blue => s.blue().to_string(),
};
}
if self.bold {
s = s.bold().to_string();
}
s
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hello() {
colored::control::set_override(true);
let message = RichText::new().text("Hello ").red("Bob").text("!");
assert_eq!(message.to_string(Format::Plain), "Hello Bob!");
assert_eq!(
message.to_string(Format::Ansi),
"Hello \u{1b}[31mBob\u{1b}[0m!"
);
}
}