├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── ansi_code.rs ├── lib.rs ├── styles.rs └── styles ├── basic_color.rs ├── formatter.rs ├── paint_type.rs ├── palette.rs └── rgb.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: ["develop"] 6 | pull_request: 7 | branches: ["develop"] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Build 19 | run: cargo build --verbose 20 | - name: Run tests 21 | run: cargo test --verbose 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # These are backup files generated by rustfmt 7 | **/*.rs.bk 8 | 9 | # MSVC Windows builds of rustc generate these, which store debugging information 10 | *.pdb 11 | 12 | # Added by cargo 13 | 14 | /target 15 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "term_tools" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "term_tools" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "Colorize Your Terminal with Term-Tools: A Rust-powered Formatting Tool" 6 | authors = ["Siavash Siamhb7@protonmail.com"] 7 | homepage = "https://crates.io/crates/term_tools" 8 | repository = "https://github.com/Syaw0/term_tools" 9 | license-file = "./LICENSE" 10 | keywords = ["cli","terminal","rust","tool","coloize"] 11 | categories = ["command-line-interface","command-line-utilities"] 12 | 13 | [dependencies] 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Siavash 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **term_tools: Rich API for Colorizing Terminal** 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2FSyaw0%2Fterm_tools%2Frefs%2Fheads%2Fdevelop%2FCargo.toml&query=package.version&label=Version&color=red)](https://crates.io/term_tools) 4 | 5 | ## **Overview** 6 | 7 | term_tools is a Rust library that provides a rich API for colorizing terminal output. It allows you to create styled text strings with various colors, effects, and formatters. 8 | 9 | ## **Features** 10 | 11 | - **Colors**: Supports 16 basic colors, 256 palette colors, and RGB colors. 12 | - **Effects**: Supports slow blink and rapid blink. 13 | - **Formatters**: Supports reset, bold, faint, italic, underline, and overline formatters. 14 | - **Easy to use**: Simple and intuitive API for creating styled text strings. 15 | 16 | ## **Usage** 17 | 18 | To use term_tools, simply add the following line to your `Cargo.toml` file: 19 | 20 | ```toml 21 | [dependencies] 22 | term_tools = "0.1.0" 23 | ``` 24 | 25 | Then, import the library in your Rust code: 26 | 27 | ```rust 28 | use term_tools::styled; 29 | ``` 30 | 31 | Create a styled text string using the `styled` function: 32 | 33 | ```rust 34 | let styled_text = styled("Hello, World!") 35 | .red() 36 | .bold() 37 | .underline() 38 | .paint(); 39 | println!("{}", styled_text); 40 | ``` 41 | 42 | ## **Sequence of Styles** 43 | 44 | The sequence of styles is important when using the `fg` and `bg` methods. These methods set the foreground and background colors, respectively, for all subsequent styles. 45 | 46 | When you call `fg` or `bg`, all styles that come before it will be applied to the foreground or background, respectively. 47 | 48 | Here's an example: 49 | 50 | ```rust 51 | let styled_text = styled("Hello, World!") 52 | .red() // applies to foreground 53 | .fg() // sets foreground color to red 54 | .blue() // applies to background 55 | .bg() // sets background color to blue 56 | .paint(); 57 | ``` 58 | 59 | In this example, the `red` style is applied to the foreground, and the `blue` style is applied to the background. 60 | 61 | if there is only one call of `fg` or `bg` whole colors applied that `PaintType` for example: 62 | 63 | ```rust 64 | let styled_text = styled("Hello, World!") 65 | .red() // red color 66 | .blue() // blue color 67 | .bg() // apply background color 68 | .magenta() // magenta color 69 | .paint(); 70 | ``` 71 | 72 | in this example `paint` method will apply the background color of all colors. 73 | 74 | if there is not any `fg` or `bg` call , the default paint type assume as `Foreground` for example: 75 | 76 | ```rust 77 | let styled_text = styled("Hello, World!") 78 | .red() // red color 79 | .blue() // blue color 80 | .paint(); 81 | ``` 82 | 83 | in this example the `paint` method will use foreground color of the colors. 84 | 85 | ## **Examples** 86 | 87 | Here are some examples of using term_tools: 88 | 89 | - **Basic colors**: 90 | 91 | ```rust 92 | let styled_text = styled("Hello, World!") 93 | .red() 94 | .paint(); 95 | println!("{}", styled_text); 96 | ``` 97 | 98 | - **RGB colors**: 99 | 100 | ```rust 101 | let styled_text = styled("Hello, World!") 102 | .rgb(255, 0, 0) 103 | .paint(); 104 | println!("{}", styled_text); 105 | ``` 106 | 107 | - **Effects**: 108 | 109 | ```rust 110 | let styled_text = styled("Hello, World!") 111 | .bold() 112 | .underline() 113 | .paint(); 114 | println!("{}", styled_text); 115 | ``` 116 | 117 | - **Formatters**: 118 | 119 | ```rust 120 | let styled_text = styled("Hello, World!") 121 | .reset() 122 | .bold() 123 | .paint(); 124 | println!("{}", styled_text); 125 | ``` 126 | 127 | ## **License** 128 | 129 | term_tools is licensed under the MIT License. 130 | 131 | ## **Contributing** 132 | 133 | Contributions are welcome If you'd like to contribute to term_tools, please fork the repository and submit a pull request. 134 | 135 | I hope this helps Let me know if you'd like me to make any changes. 136 | -------------------------------------------------------------------------------- /src/ansi_code.rs: -------------------------------------------------------------------------------- 1 | /// A module for creating ansi escape code. 2 | /// 3 | /// This module provides an struct `ANSIEscapeCode` 4 | /// that represents ansi escape code, with `parameter` field. 5 | /// It also implements the `ANSIEscapeCode`, with `new` and `code` method 6 | /// which allows for generating anis escape code and getting a code. 7 | 8 | // ======================================================================= 9 | 10 | /// An struct representing ansi escape code. 11 | /// 12 | /// This struct has 1 field: `parameter` , which represent String of the ansi code. 13 | pub struct ANSIEscapeCode { 14 | parameter: String, 15 | } 16 | impl ANSIEscapeCode { 17 | /// Returns a ANSIEscapeCode instance with parameter . 18 | pub fn new(parameter: &str) -> Self { 19 | ANSIEscapeCode { parameter: parameter.to_string() } 20 | } 21 | 22 | /// Returns a String that represent the ansi code. 23 | pub fn code(&self) -> String { 24 | format!("\x1b[{}m", self.parameter) 25 | } 26 | } 27 | 28 | // ======================================================================= 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use super::*; 33 | 34 | #[test] 35 | fn create_simple_ansi_code() { 36 | let p = ANSIEscapeCode::new("33"); 37 | assert_eq!(p.code(), "\x1b[33m") 38 | } 39 | 40 | #[test] 41 | fn create_reset_ansi_code() { 42 | let reset_ansi = ANSIEscapeCode::new("0"); 43 | assert_eq!("\x1b[0m", reset_ansi.code()); 44 | } 45 | 46 | #[test] 47 | fn create_bright_cyan_ansi_code() { 48 | let reset_ansi = ANSIEscapeCode::new("96"); 49 | assert_eq!("\x1b[96m", reset_ansi.code()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Term_Tools: Rich API for Colorizing Terminal 2 | //! 3 | //! term_tools is a Rust library that provides a rich API for colorizing terminal output. 4 | //! It allows you to create styled text strings with various colors, effects, and formatters. 5 | 6 | mod ansi_code; 7 | mod styles; 8 | 9 | // ======================================================================= 10 | use crate::{ 11 | ansi_code::ANSIEscapeCode, 12 | styles::{ 13 | basic_color, 14 | formatter, 15 | paint_type::PaintType, 16 | palette::PaletteColor, 17 | rgb::Rgb, 18 | Styles, 19 | }, 20 | }; 21 | 22 | // ======================================================================= 23 | 24 | /// Creates a styled text string with the given text and styles. 25 | /// 26 | /// This function returns a `StyledText` object that can be customized with various styles, 27 | /// colors, and effects. The resulting styled text can be printed or used in other contexts. 28 | /// 29 | /// # Examples 30 | /// 31 | /// ``` 32 | /// use term_tools::styled; 33 | /// 34 | /// let txt = styled("Happy Day!") 35 | /// .rgb(204, 182, 122) 36 | /// .italic() 37 | /// .rapid_blink() 38 | /// .bg() 39 | /// .black() 40 | /// .fg() 41 | /// .paint(); 42 | /// println!("{txt}"); 43 | /// ``` 44 | /// 45 | /// # Styles 46 | /// 47 | /// The following styles can be applied to the text: 48 | /// 49 | /// * `rgb(r, g, b)`: Sets the text color to the given RGB values. 50 | /// * `italic()`: Sets the text to italic. 51 | /// * `rapid_blink()`: Sets the text to rapidly blink. 52 | /// * `bg()`: Sets the background color. 53 | /// * `fg()`: Sets the foreground color. 54 | /// * basic colors like : `red`,`black` and etc. 55 | /// 56 | /// # Colors 57 | /// 58 | /// The following colors can be used with the `rgb` method: 59 | /// 60 | /// * `rgb(r, g, b)`: Sets the color to the given RGB values. 61 | /// 62 | /// # Effects 63 | /// 64 | /// The following effects can be applied to the text: 65 | /// 66 | /// * `rapid_blink()`: Sets the text to rapidly blink. 67 | /// 68 | /// # Returns 69 | /// 70 | /// A `StyledText` object that can be printed or used in other contexts. 71 | pub fn styled(text: &str) -> StyledText { 72 | StyledText::new(text.to_string()) 73 | } 74 | 75 | /// A struct representing a styled text string. 76 | pub struct StyledText { 77 | text: String, 78 | start_styles: Vec, 79 | } 80 | 81 | impl StyledText { 82 | /// Creates a new `StyledText` object with the given text. 83 | fn new(text: String) -> Self { 84 | StyledText { 85 | text, 86 | start_styles: vec![], 87 | } 88 | } 89 | 90 | /// Paints the styled text string with the given styles. 91 | /// 92 | /// This method returns a string representing the styled text. 93 | pub fn paint(&mut self) -> String { 94 | let mut default_paint_type = PaintType::FG; 95 | 96 | let start_codes_list: Vec = self.start_styles 97 | .iter() 98 | .rev() 99 | .filter_map(|s| { 100 | if let Styles::StylePaintType(p) = s { 101 | default_paint_type = p.clone(); 102 | return None; 103 | } 104 | let t = s.make_styles(Some(&default_paint_type)); 105 | Some(ANSIEscapeCode::new(t.as_str()).code()) 106 | }) 107 | .collect::>() 108 | .into_iter() 109 | .rev() 110 | .collect(); 111 | let start_codes = start_codes_list.join(""); 112 | let end_codes = ANSIEscapeCode::new( 113 | &formatter::RESET.make_styles(Some(&default_paint_type)) 114 | ).code(); 115 | 116 | format!("{}{}{}", start_codes, self.text, end_codes) 117 | } 118 | 119 | /// Sets the foreground color of the colors you have called. 120 | /// 121 | /// # Example: 122 | /// ``` 123 | /// use term_tools::styled; 124 | /// let styled_text = styled("How you doing?").black().fg().red().bg().paint(); 125 | /// ``` 126 | /// the colors before this method will paint as foreground! 127 | /// so the black color will paint as foreground and red color paint 128 | /// as background color 129 | /// **if the one `fg` call, all the colors will paint as foreground no matter there is before or after `fg`** 130 | pub fn fg(&mut self) -> &mut Self { 131 | self.start_styles.push(Styles::StylePaintType(PaintType::FG)); 132 | self 133 | } 134 | 135 | /// Sets the background color of the colors you have called. 136 | /// 137 | /// # Example: 138 | /// ``` 139 | /// use term_tools::styled; 140 | /// let styled_text = styled("I'm feel Happy").bright_cyan().bg().blue().fg().paint(); 141 | /// ``` 142 | /// the colors before this method will paint as background! 143 | /// so the bright_cyan color will paint as background and blue color paint 144 | /// as foreground color 145 | /// **if the one `bg` call, all the colors will paint as background no matter there is before or after `bg`** 146 | pub fn bg(&mut self) -> &mut Self { 147 | self.start_styles.push(Styles::StylePaintType(PaintType::BG)); 148 | self 149 | } 150 | 151 | // Colors 152 | 153 | /// Sets the `rgb` color to the input text. 154 | /// 155 | /// # Example: 156 | /// ``` 157 | /// use term_tools::styled; 158 | /// let styled_text = styled("Our life is what our thoughts make it.").rgb(48,118,230).paint(); 159 | /// ``` 160 | pub fn rgb(&mut self, r: u8, g: u8, b: u8) -> &mut Self { 161 | self.start_styles.push(Styles::StyleRgb(Rgb { r, g, b })); 162 | self 163 | } 164 | 165 | /// Sets the `palette` color to the input text. 166 | /// 167 | /// # Example: 168 | /// ``` 169 | /// use term_tools::styled; 170 | /// let styled_text = styled("If it is not right, do not do it. If it is not true, do not say it.").palette(132).paint(); 171 | /// ``` 172 | /// 173 | /// the index should be 8 bit color between 0 to 255. 174 | pub fn palette(&mut self, index: u8) -> &mut Self { 175 | self.start_styles.push(Styles::StylePaletteColor(PaletteColor { index })); 176 | self 177 | } 178 | 179 | /// Sets the `black` color to the input text. 180 | /// 181 | /// # Example: 182 | /// ``` 183 | /// use term_tools::styled; 184 | /// let styled_text = styled("The best revenge is to not be like your enemies.").black().paint(); 185 | /// ``` 186 | pub fn black(&mut self) -> &mut Self { 187 | self.start_styles.push(basic_color::BLACK); 188 | self 189 | } 190 | 191 | /// Sets the `red` color to the input text. 192 | /// 193 | /// # Example: 194 | /// ``` 195 | /// use term_tools::styled; 196 | /// let styled_text = styled("To love only what happens, what was destined. No greater harmony.").red().paint(); 197 | /// ``` 198 | pub fn red(&mut self) -> &mut Self { 199 | self.start_styles.push(basic_color::RED); 200 | self 201 | } 202 | 203 | /// Sets the `green` color to the input text. 204 | /// 205 | /// # Example: 206 | /// ``` 207 | /// use term_tools::styled; 208 | /// let styled_text = styled("Everything we hear is opinion, not a fact. Everything we see is a perspective, not the truth.").green().paint(); 209 | /// ``` 210 | pub fn green(&mut self) -> &mut Self { 211 | self.start_styles.push(basic_color::GREEN); 212 | self 213 | } 214 | 215 | /// Sets the `yellow` color to the input text. 216 | /// 217 | /// # Example: 218 | /// ``` 219 | /// use term_tools::styled; 220 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").yellow().paint(); 221 | /// ``` 222 | pub fn yellow(&mut self) -> &mut Self { 223 | self.start_styles.push(basic_color::YELLOW); 224 | self 225 | } 226 | 227 | /// Sets the `blue` color to the input text. 228 | /// 229 | /// # Example: 230 | /// ``` 231 | /// use term_tools::styled; 232 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").blue().paint(); 233 | /// ``` 234 | pub fn blue(&mut self) -> &mut Self { 235 | self.start_styles.push(basic_color::BLUE); 236 | self 237 | } 238 | 239 | /// Sets the `magenta` color to the input text. 240 | /// 241 | /// # Example: 242 | /// ``` 243 | /// use term_tools::styled; 244 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").magenta().paint(); 245 | /// ``` 246 | pub fn magenta(&mut self) -> &mut Self { 247 | self.start_styles.push(basic_color::MAGENTA); 248 | self 249 | } 250 | 251 | /// Sets the `cyan` color to the input text. 252 | /// 253 | /// # Example: 254 | /// ``` 255 | /// use term_tools::styled; 256 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").cyan().paint(); 257 | /// ``` 258 | pub fn cyan(&mut self) -> &mut Self { 259 | self.start_styles.push(basic_color::CYAN); 260 | self 261 | } 262 | 263 | /// Sets the `white` color to the input text. 264 | /// 265 | /// # Example: 266 | /// ``` 267 | /// use term_tools::styled; 268 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").white().paint(); 269 | /// ``` 270 | pub fn white(&mut self) -> &mut Self { 271 | self.start_styles.push(basic_color::WHITE); 272 | self 273 | } 274 | 275 | /// Sets the `gray` color to the input text. 276 | /// 277 | /// # Example: 278 | /// ``` 279 | /// use term_tools::styled; 280 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").gray().paint(); 281 | /// ``` 282 | pub fn gray(&mut self) -> &mut Self { 283 | self.start_styles.push(basic_color::GRAY); 284 | self 285 | } 286 | 287 | /// Sets the `bright_red` color to the input text. 288 | /// 289 | /// # Example: 290 | /// ``` 291 | /// use term_tools::styled; 292 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_red().paint(); 293 | /// ``` 294 | pub fn bright_red(&mut self) -> &mut Self { 295 | self.start_styles.push(basic_color::BRIGHT_RED); 296 | self 297 | } 298 | 299 | /// Sets the `bright_green` color to the input text. 300 | /// 301 | /// # Example: 302 | /// ``` 303 | /// use term_tools::styled; 304 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_green().paint(); 305 | /// ``` 306 | pub fn bright_green(&mut self) -> &mut Self { 307 | self.start_styles.push(basic_color::BRIGHT_GREEN); 308 | self 309 | } 310 | 311 | /// Sets the `bright_yellow` color to the input text. 312 | /// 313 | /// # Example: 314 | /// ``` 315 | /// use term_tools::styled; 316 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_yellow().paint(); 317 | /// ``` 318 | pub fn bright_yellow(&mut self) -> &mut Self { 319 | self.start_styles.push(basic_color::BRIGHT_YELLOW); 320 | self 321 | } 322 | 323 | /// Sets the `bright_blue` color to the input text. 324 | /// 325 | /// # Example: 326 | /// ``` 327 | /// use term_tools::styled; 328 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_blue().paint(); 329 | /// ``` 330 | pub fn bright_blue(&mut self) -> &mut Self { 331 | self.start_styles.push(basic_color::BRIGHT_BLUE); 332 | self 333 | } 334 | 335 | /// Sets the `bright_magenta` color to the input text. 336 | /// 337 | /// # Example: 338 | /// ``` 339 | /// use term_tools::styled; 340 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_magenta().paint(); 341 | /// ``` 342 | /// use term_tools::styled; 343 | pub fn bright_magenta(&mut self) -> &mut Self { 344 | self.start_styles.push(basic_color::BRIGHT_MAGENTA); 345 | self 346 | } 347 | 348 | /// Sets the `bright_cyan` color to the input text. 349 | /// 350 | /// # Example: 351 | /// ``` 352 | /// use term_tools::styled; 353 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_cyan().paint(); 354 | /// ``` 355 | pub fn bright_cyan(&mut self) -> &mut Self { 356 | self.start_styles.push(basic_color::BRIGHT_CYAN); 357 | self 358 | } 359 | 360 | /// Sets the `bright_white` color to the input text. 361 | /// 362 | /// # Example: 363 | /// ``` 364 | /// use term_tools::styled; 365 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bright_white().paint(); 366 | /// ``` 367 | pub fn bright_white(&mut self) -> &mut Self { 368 | self.start_styles.push(basic_color::BRIGHT_WHITE); 369 | self 370 | } 371 | 372 | // Formatters 373 | 374 | /// Sets the `reset` effect to the input text. 375 | /// 376 | /// # Example: 377 | /// ``` 378 | /// use term_tools::styled; 379 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").red().reset().paint(); 380 | /// ``` 381 | /// ** this will reset all the effects, colors and formatters that are called before this** 382 | /// so in the top example the red color will never applied to the input text 383 | pub fn reset(&mut self) -> &mut Self { 384 | self.start_styles.push(formatter::RESET); 385 | self 386 | } 387 | 388 | /// Sets the `bold` format to the input text. 389 | /// 390 | /// # Example: 391 | /// ``` 392 | /// use term_tools::styled; 393 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").bold().paint(); 394 | /// ``` 395 | pub fn bold(&mut self) -> &mut Self { 396 | self.start_styles.push(formatter::BOLD); 397 | self 398 | } 399 | 400 | /// Sets the `faint` format to the input text. 401 | /// 402 | /// # Example: 403 | /// ``` 404 | /// use term_tools::styled; 405 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").faint().paint(); 406 | /// ``` 407 | pub fn faint(&mut self) -> &mut Self { 408 | self.start_styles.push(formatter::FAINT); 409 | self 410 | } 411 | 412 | /// Sets the `italic` format to the input text. 413 | /// 414 | /// # Example: 415 | /// ``` 416 | /// use term_tools::styled; 417 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").italic().paint(); 418 | /// ``` 419 | pub fn italic(&mut self) -> &mut Self { 420 | self.start_styles.push(formatter::ITALIC); 421 | self 422 | } 423 | 424 | /// Sets the `underline` format to the input text. 425 | /// 426 | /// # Example: 427 | /// ``` 428 | /// use term_tools::styled; 429 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").underline().paint(); 430 | /// ``` 431 | pub fn underline(&mut self) -> &mut Self { 432 | self.start_styles.push(formatter::UNDERLINE); 433 | self 434 | } 435 | 436 | /// Sets the `slow_blink` effect to the input text. 437 | /// 438 | /// # Example: 439 | /// ``` 440 | /// use term_tools::styled; 441 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").slow_blink().paint(); 442 | /// ``` 443 | /// 444 | /// **base on the terminal you are using this could not be applied** 445 | pub fn slow_blink(&mut self) -> &mut Self { 446 | self.start_styles.push(formatter::SLOW_BLINK); 447 | self 448 | } 449 | 450 | /// Sets the `rapid_blink` effect to the input text. 451 | /// 452 | /// # Example: 453 | /// ``` 454 | /// use term_tools::styled; 455 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").rapid_blink().paint(); 456 | /// ``` 457 | /// 458 | /// **base on the terminal you are using this could not be applied** 459 | pub fn rapid_blink(&mut self) -> &mut Self { 460 | self.start_styles.push(formatter::RAPID_BLINK); 461 | self 462 | } 463 | 464 | /// Sets the `overline` effect to the input text. 465 | /// 466 | /// # Example: 467 | /// ``` 468 | /// use term_tools::styled; 469 | /// let styled_text = styled("The present is all we have to live in . . . or to lose.").overline().paint(); 470 | /// ``` 471 | pub fn overline(&mut self) -> &mut Self { 472 | self.start_styles.push(formatter::OVERLINE); 473 | self 474 | } 475 | } 476 | -------------------------------------------------------------------------------- /src/styles.rs: -------------------------------------------------------------------------------- 1 | /// A module for working with styles and colors. 2 | /// 3 | /// This module provides a set of types and traits for representing 4 | /// different styles and colors, 5 | /// as well as a way to generate styles based on a given paint type. 6 | 7 | // ======================================================================= 8 | 9 | use basic_color::BasicColor; 10 | use formatter::Formatter; 11 | use paint_type::PaintType; 12 | use palette::PaletteColor; 13 | use rgb::Rgb; 14 | 15 | // ======================================================================= 16 | pub mod paint_type; 17 | pub mod formatter; 18 | pub mod basic_color; 19 | pub mod rgb; 20 | pub mod palette; 21 | 22 | // ======================================================================= 23 | 24 | /// An enum representing different styles. 25 | /// 26 | /// This enum has five variants, each representing a different type of style: 27 | /// `StyleRgb`, `StyleBasicColor`, `StylePaletteColor`, `StylePaintType`, and `StyleFormatter`. 28 | #[derive(Debug, Clone)] 29 | pub enum Styles { 30 | /// A style represented by an RGB color. 31 | StyleRgb(Rgb), 32 | /// A style represented by a basic color. 33 | StyleBasicColor(BasicColor), 34 | /// A style represented by a palette color. 35 | StylePaletteColor(PaletteColor), 36 | /// A style represented by a paint type. 37 | StylePaintType(PaintType), 38 | /// A style represented by a formatter. 39 | StyleFormatter(Formatter), 40 | } 41 | 42 | impl Styles { 43 | /// Generates String styles based on the given paint type. 44 | /// 45 | /// This method takes an optional `paint_type` parameter, which is used to determine the styles to generate. 46 | /// It returns a string representing the generated styles. 47 | pub fn make_styles(&self, paint_type: Option<&PaintType>) -> String { 48 | match self { 49 | Styles::StyleBasicColor(c) => c.make_styles(paint_type), 50 | Styles::StylePaintType(c) => c.make_styles(paint_type), 51 | Styles::StylePaletteColor(c) => c.make_styles(paint_type), 52 | Styles::StyleRgb(c) => c.make_styles(paint_type), 53 | Styles::StyleFormatter(c) => c.make_styles(paint_type), 54 | } 55 | } 56 | } 57 | 58 | /// A trait for types that can generate styles based on a given paint type. 59 | pub trait Stylify { 60 | /// Generates String styles based on the given paint type. 61 | /// 62 | /// This method takes an optional `paint_type` parameter, which is used to determine the styles to generate. 63 | /// It returns a string representing the generated styles. 64 | fn make_styles(&self, paint_type: Option<&PaintType>) -> String; 65 | } 66 | 67 | #[cfg(test)] 68 | mod tests { 69 | use super::*; 70 | 71 | #[test] 72 | fn test_make_styles() { 73 | let style = Styles::StyleRgb(Rgb { r: 255, g: 0, b: 0 }); 74 | let styles_default = style.make_styles(None); 75 | let styles_fg = style.make_styles(Some(&PaintType::FG)); 76 | let styles_bg = style.make_styles(Some(&PaintType::BG)); 77 | assert_eq!(styles_default, "38;2;255;0;0"); 78 | assert_eq!(styles_fg, "38;2;255;0;0"); 79 | assert_eq!(styles_bg, "48;2;255;0;0"); 80 | 81 | // 82 | let style = Styles::StyleBasicColor(BasicColor { fg: 34, bg: 44 }); 83 | let styles_default = style.make_styles(None); 84 | let styles_fg = style.make_styles(Some(&PaintType::FG)); 85 | let styles_bg = style.make_styles(Some(&PaintType::BG)); 86 | assert_eq!(styles_default, "34"); 87 | assert_eq!(styles_fg, "34"); 88 | assert_eq!(styles_bg, "44"); 89 | 90 | // 91 | let style = Styles::StylePaletteColor(PaletteColor { index: 44 }); 92 | let styles_default = style.make_styles(None); 93 | let styles_fg = style.make_styles(Some(&PaintType::FG)); 94 | let styles_bg = style.make_styles(Some(&PaintType::BG)); 95 | assert_eq!(styles_default, "38;5;44"); 96 | assert_eq!(styles_fg, "38;5;44"); 97 | assert_eq!(styles_bg, "48;5;44"); 98 | 99 | // 100 | let style = Styles::StylePaintType(PaintType::BG); 101 | let styles_default = style.make_styles(None); 102 | let styles_fg = style.make_styles(Some(&PaintType::FG)); 103 | let styles_bg = style.make_styles(Some(&PaintType::BG)); 104 | assert_eq!(styles_default, ""); 105 | assert_eq!(styles_fg, ""); 106 | assert_eq!(styles_bg, ""); 107 | 108 | // 109 | let style = Styles::StyleFormatter(Formatter { code: 3 }); 110 | let styles_default = style.make_styles(None); 111 | let styles_fg = style.make_styles(Some(&PaintType::FG)); 112 | let styles_bg = style.make_styles(Some(&PaintType::BG)); 113 | assert_eq!(styles_default, "3"); 114 | assert_eq!(styles_fg, "3"); 115 | assert_eq!(styles_bg, "3"); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/styles/basic_color.rs: -------------------------------------------------------------------------------- 1 | use super::{ paint_type::PaintType, Styles, Stylify }; 2 | 3 | // ======================================================================= 4 | 5 | /// A struct representing a basic color with foreground and background values. 6 | #[derive(Debug, Clone)] 7 | pub struct BasicColor { 8 | /// The foreground color value. 9 | pub fg: u8, 10 | /// The background color value. 11 | pub bg: u8, 12 | } 13 | 14 | impl Stylify for BasicColor { 15 | /// Returns a string representation of the color style. 16 | /// 17 | /// If `paint_type` is `None`, the foreground color is assumed. 18 | fn make_styles(&self, paint_type: Option<&PaintType>) -> String { 19 | let paint_type = paint_type.unwrap_or(&PaintType::FG); 20 | format!("{}", match paint_type { 21 | PaintType::FG => self.fg, 22 | PaintType::BG => self.bg, 23 | }) 24 | } 25 | } 26 | 27 | /// A macro for generating color constants. 28 | macro_rules! color_code { 29 | ($name:ident, { fg: $fg:expr, bg: $bg:expr }) => { 30 | pub const $name:Styles = Styles::StyleBasicColor(BasicColor { fg: $fg, bg: $bg }); 31 | }; 32 | } 33 | 34 | color_code!(BLACK,{fg: 30, bg: 40 }); 35 | color_code!(RED,{fg: 31, bg: 41}); 36 | color_code!(GREEN,{ fg: 32, bg: 42 }); 37 | color_code!(YELLOW,{ fg: 33, bg: 43 }); 38 | color_code!(BLUE,{fg: 34, bg: 44}); 39 | color_code!(MAGENTA,{ fg: 35, bg: 45}); 40 | color_code!(CYAN,{fg:36,bg:46}); 41 | color_code!(WHITE,{fg:37,bg:47}); 42 | color_code!(GRAY,{fg:90,bg:100}); 43 | color_code!(BRIGHT_RED,{fg:91,bg:101}); 44 | color_code!(BRIGHT_GREEN,{fg:92,bg:102}); 45 | color_code!(BRIGHT_YELLOW,{fg:93,bg:103}); 46 | color_code!(BRIGHT_BLUE,{fg:94,bg:104}); 47 | color_code!(BRIGHT_MAGENTA,{fg:95,bg:105}); 48 | color_code!(BRIGHT_CYAN,{fg:96,bg:106}); 49 | color_code!(BRIGHT_WHITE,{fg:97,bg:107}); 50 | 51 | #[cfg(test)] 52 | mod tests { 53 | use super::*; 54 | 55 | #[test] 56 | fn test_make_style_fg() { 57 | let color = BasicColor { fg: 30, bg: 40 }; 58 | let styles = color.make_styles(Some(&PaintType::FG)); 59 | assert_eq!(styles, "30") 60 | } 61 | 62 | #[test] 63 | fn test_make_style_default_fg() { 64 | let color = BasicColor { fg: 34, bg: 44 }; 65 | let styles = color.make_styles(None); 66 | assert_eq!(styles, "34") 67 | } 68 | 69 | #[test] 70 | fn test_make_style_bg() { 71 | let color = BasicColor { fg: 30, bg: 40 }; 72 | let styles = color.make_styles(Some(&PaintType::BG)); 73 | assert_eq!(styles, "40") 74 | } 75 | 76 | #[test] 77 | fn test_fg_and_bg_values() { 78 | let color = BasicColor { fg: 30, bg: 40 }; 79 | let styles_fg = color.make_styles(Some(&PaintType::FG)); 80 | let styles_bg = color.make_styles(Some(&PaintType::BG)); 81 | assert_eq!(styles_fg, "30"); 82 | assert_eq!(styles_bg, "40"); 83 | } 84 | 85 | #[test] 86 | fn test_fg_and_bg_values_with_none_paint_type() { 87 | let color = BasicColor { fg: 30, bg: 40 }; 88 | let styles_fg = color.make_styles(None); 89 | let styles_bg = color.make_styles(Some(&PaintType::BG)); 90 | assert_eq!(styles_fg, "30"); 91 | assert_eq!(styles_bg, "40"); 92 | } 93 | 94 | #[test] 95 | fn test_color_code_macro() { 96 | color_code!(TEST_COLOR,{fg:100,bg:200}); 97 | match TEST_COLOR { 98 | Styles::StyleBasicColor(BasicColor { fg, bg }) => { 99 | assert_eq!(fg, 100); 100 | assert_eq!(bg, 200); 101 | } 102 | _ => panic!("TEST_COLOR is not a BasicColor"), 103 | } 104 | } 105 | 106 | macro_rules! color_test { 107 | ($test_name:ident, $color_name:ident, $color:expr, $fg:expr, $bg:expr) => { 108 | #[test] 109 | fn $test_name(){ 110 | match $color_name{ 111 | Styles::StyleBasicColor(BasicColor{fg,bg})=>{ 112 | assert_eq!(fg,$fg); 113 | assert_eq!(bg,$bg); 114 | }, 115 | _=>{ 116 | panic!("This color is not a basic color!"); 117 | } 118 | } 119 | } 120 | }; 121 | } 122 | 123 | color_test!(black_color, BLACK, "Black", 30, 40); 124 | color_test!(red_color, RED, "Red", 31, 41); 125 | color_test!(green_color, GREEN, "Green", 32, 42); 126 | color_test!(yellow_color, YELLOW, "Yellow", 33, 43); 127 | color_test!(blue_color, BLUE, "Blue", 34, 44); 128 | color_test!(magenta_color, MAGENTA, "Magenta", 35, 45); 129 | color_test!(cyan_color, CYAN, "Cyan", 36, 46); 130 | color_test!(white_color, WHITE, "White", 37, 47); 131 | color_test!(gray_color, GRAY, "Gray", 90, 100); 132 | color_test!(bright_red_color, BRIGHT_RED, "Bright Red", 91, 101); 133 | color_test!(bright_green_color, BRIGHT_GREEN, "Bright Green", 92, 102); 134 | color_test!(bright_yellow_color, BRIGHT_YELLOW, "Bright Yellow", 93, 103); 135 | color_test!(bright_blue_color, BRIGHT_BLUE, "Bright Blue", 94, 104); 136 | color_test!(bright_magenta_color, BRIGHT_MAGENTA, "Bright Magenta", 95, 105); 137 | color_test!(bright_cyan_color, BRIGHT_CYAN, "Bright Cyan", 96, 106); 138 | color_test!(bright_white_color, BRIGHT_WHITE, "Bright White", 97, 107); 139 | } 140 | -------------------------------------------------------------------------------- /src/styles/formatter.rs: -------------------------------------------------------------------------------- 1 | use super::{ paint_type::PaintType, Styles, Stylify }; 2 | 3 | // ======================================================================= 4 | 5 | /// A struct representing a Formatter with code value. 6 | #[derive(Debug, Clone)] 7 | pub struct Formatter { 8 | pub code: u8, 9 | } 10 | 11 | impl Stylify for Formatter { 12 | /// Returns a string representation of the formatter style. 13 | /// 14 | /// The `PaintType` is not any involved in this method! 15 | fn make_styles(&self, _paint_type: Option<&PaintType>) -> String { 16 | format!("{}", self.code) 17 | } 18 | } 19 | 20 | /// A macro for generating formatter constants. 21 | macro_rules! formatter_code { 22 | ($name:ident, $code:expr) => { 23 | pub const $name: Styles = Styles::StyleFormatter(Formatter { code: $code }); 24 | }; 25 | } 26 | 27 | formatter_code!(RESET, 0); 28 | formatter_code!(BOLD, 1); 29 | formatter_code!(FAINT, 2); 30 | formatter_code!(ITALIC, 3); 31 | formatter_code!(UNDERLINE, 4); 32 | formatter_code!(SLOW_BLINK, 5); 33 | formatter_code!(RAPID_BLINK, 6); 34 | formatter_code!(OVERLINE, 53); 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn make_styles_fg() { 42 | let formatter = Formatter { code: 22 }; 43 | let styles = formatter.make_styles(Some(&PaintType::FG)); 44 | assert_eq!(styles, "22") 45 | } 46 | 47 | #[test] 48 | fn make_styles_bg() { 49 | let formatter = Formatter { code: 111 }; 50 | let styles = formatter.make_styles(Some(&PaintType::BG)); 51 | assert_eq!(styles, "111") 52 | } 53 | 54 | #[test] 55 | fn make_styles_default_paint_type() { 56 | let formatter = Formatter { code: 31 }; 57 | let styles = formatter.make_styles(None); 58 | assert_eq!(styles, "31") 59 | } 60 | 61 | #[test] 62 | fn test_code_values() { 63 | let formatter = Formatter { code: 90 }; 64 | let styles_fg = formatter.make_styles(Some(&PaintType::FG)); 65 | let styles_bg = formatter.make_styles(Some(&PaintType::BG)); 66 | assert_eq!(styles_fg, "90"); 67 | assert_eq!(styles_bg, "90"); 68 | } 69 | 70 | #[test] 71 | fn test_code_values_with_none_paint_type() { 72 | let formatter = Formatter { code: 47 }; 73 | let styles_fg = formatter.make_styles(None); 74 | let styles_bg = formatter.make_styles(Some(&PaintType::BG)); 75 | assert_eq!(styles_fg, "47"); 76 | assert_eq!(styles_bg, "47"); 77 | } 78 | 79 | #[test] 80 | fn test_formatter_code_macro() { 81 | formatter_code!(TEST_FORMATTER, 103); 82 | match TEST_FORMATTER { 83 | Styles::StyleFormatter(Formatter { code }) => { 84 | assert_eq!(code, 103); 85 | } 86 | _ => panic!("TEST_FORMATTER is not a Formatter"), 87 | } 88 | } 89 | 90 | /// A macro for generating formatter tests. 91 | macro_rules! formatter_test { 92 | ($test_name:ident, $formatter_name:ident, $code:expr) => { 93 | #[test] 94 | fn $test_name(){ 95 | match $formatter_name{ 96 | Styles::StyleFormatter(Formatter{code})=>{ 97 | assert_eq!(code,$code); 98 | }, 99 | _=>{ 100 | panic!("This formatter is not a Formatter!"); 101 | } 102 | } 103 | } 104 | }; 105 | } 106 | 107 | formatter_test!(test_reset_formatter, RESET, 0); 108 | formatter_test!(test_bold_formatter, BOLD, 1); 109 | formatter_test!(test_faint_formatter, FAINT, 2); 110 | formatter_test!(test_italic_formatter, ITALIC, 3); 111 | formatter_test!(test_underline_formatter, UNDERLINE, 4); 112 | formatter_test!(test_slow_blink_formatter, SLOW_BLINK, 5); 113 | formatter_test!(test_rapid_blink_formatter, RAPID_BLINK, 6); 114 | formatter_test!(test_overline_formatter, OVERLINE, 53); 115 | } 116 | -------------------------------------------------------------------------------- /src/styles/paint_type.rs: -------------------------------------------------------------------------------- 1 | /// A module for working with paint types. 2 | /// 3 | /// This module provides an enum `PaintType` that represents different types of paint. 4 | /// It also implements the `Stylify` trait for `PaintType`, which allows for generating styles based on the paint type. 5 | 6 | // ======================================================================= 7 | 8 | use super::Stylify; 9 | 10 | // ======================================================================= 11 | 12 | /// An enum representing different types of paint. 13 | /// 14 | /// This enum has two variants: `FG` and `BG`, which represent foreground and background paint, respectively. 15 | #[derive(Debug, Clone)] 16 | pub enum PaintType { 17 | /// Foreground paint. 18 | FG, 19 | /// Background paint. 20 | BG, 21 | } 22 | 23 | impl Stylify for PaintType { 24 | /// Generates styles based on the paint type. 25 | /// 26 | /// This method takes an optional `paint_type` parameter, which is ignored in this implementation. 27 | /// It returns an empty string, indicating that no styles are generated. 28 | fn make_styles(&self, _paint_type: Option<&PaintType>) -> String { 29 | String::new() 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | 37 | #[test] 38 | fn test_make_styles() { 39 | let paint_type = PaintType::FG; 40 | let styles = paint_type.make_styles(None); 41 | assert_eq!(styles, String::new()); 42 | 43 | let paint_type = PaintType::BG; 44 | let styles = paint_type.make_styles(Some(&PaintType::FG)); 45 | assert_eq!(styles, String::new()); 46 | } 47 | 48 | #[test] 49 | fn test_make_styles_null_input() { 50 | let paint_type = PaintType::FG; 51 | let styles = paint_type.make_styles(None); 52 | assert_eq!(styles, String::new()); 53 | } 54 | 55 | #[test] 56 | fn test_make_styles_multiple_calls() { 57 | let paint_type = PaintType::FG; 58 | let styles1 = paint_type.make_styles(None); 59 | let styles2 = paint_type.make_styles(None); 60 | assert_eq!(styles1, styles2); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/styles/palette.rs: -------------------------------------------------------------------------------- 1 | /// A module for creating palette color. 2 | /// 3 | /// This module provides an struct `PaletteColor` 4 | /// that represents palette color, index should be between 0 to 255 mean u8. 5 | /// It also implements the `Stylify` trait for `PaletteColor`, 6 | /// which allows for generating styles based on the paint type. 7 | 8 | // ======================================================================= 9 | 10 | use super::{ paint_type::PaintType, Stylify }; 11 | 12 | // ======================================================================= 13 | 14 | /// An struct representing index of palette color. 15 | /// 16 | /// This struct has 1 field: `index`, which represent 8 bit color code between 0 to 255. 17 | #[derive(Debug, Clone)] 18 | pub struct PaletteColor { 19 | pub index: u8, 20 | } 21 | 22 | impl Stylify for PaletteColor { 23 | /// Returns a string representation of the palette index code. 24 | /// 25 | /// If `paint_type` is `None`, the foreground color is assumed. 26 | fn make_styles(&self, paint_type: Option<&PaintType>) -> String { 27 | let paint_type = paint_type.unwrap_or(&PaintType::FG); 28 | format!( 29 | "{};5;{}", 30 | match paint_type { 31 | PaintType::FG => "38", 32 | PaintType::BG => "48", 33 | }, 34 | self.index 35 | ) 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | 43 | #[test] 44 | fn test_make_style_fg() { 45 | let color = PaletteColor { index: 42 }; 46 | let styles = color.make_styles(Some(&PaintType::FG)); 47 | assert_eq!(styles, "38;5;42") 48 | } 49 | 50 | #[test] 51 | fn test_make_style_default_fg() { 52 | let color = PaletteColor { index: 105 }; 53 | let styles = color.make_styles(None); 54 | assert_eq!(styles, "38;5;105") 55 | } 56 | 57 | #[test] 58 | fn test_make_style_bg() { 59 | let color = PaletteColor { index: 1 }; 60 | let styles = color.make_styles(Some(&PaintType::BG)); 61 | assert_eq!(styles, "48;5;1") 62 | } 63 | 64 | #[test] 65 | fn test_fg_and_bg_values() { 66 | let color = PaletteColor { index: 200 }; 67 | let styles_fg = color.make_styles(Some(&PaintType::FG)); 68 | let styles_bg = color.make_styles(Some(&PaintType::BG)); 69 | assert_eq!(styles_fg, "38;5;200"); 70 | assert_eq!(styles_bg, "48;5;200") 71 | } 72 | 73 | #[test] 74 | fn test_fg_and_bg_values_with_none_paint_type() { 75 | let color = PaletteColor { index: 108 }; 76 | let styles_fg = color.make_styles(None); 77 | let styles_bg = color.make_styles(Some(&PaintType::BG)); 78 | assert_eq!(styles_fg, "38;5;108"); 79 | assert_eq!(styles_bg, "48;5;108") 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/styles/rgb.rs: -------------------------------------------------------------------------------- 1 | /// A module for creating rgb color. 2 | /// 3 | /// This module provides an struct `Rgb` 4 | /// that represents rgb color, with r,g,b field. 5 | /// It also implements the `Stylify` trait for `Rgb`, 6 | /// which allows for generating styles based on the paint type. 7 | 8 | // ======================================================================= 9 | 10 | use super::{ paint_type::PaintType, Stylify }; 11 | 12 | // ======================================================================= 13 | 14 | /// An struct representing rgb color. 15 | /// 16 | /// This struct has 3 field: `r`, `g` and `b` , which each of them represent 8 bit color code between 0 to 255. 17 | #[derive(Debug, Clone)] 18 | pub struct Rgb { 19 | pub r: u8, 20 | pub g: u8, 21 | pub b: u8, 22 | } 23 | 24 | impl Stylify for Rgb { 25 | /// Returns a string representation of the rgb color code. 26 | /// 27 | /// If `paint_type` is `None`, the foreground color is assumed. 28 | fn make_styles(&self, paint_type: Option<&PaintType>) -> String { 29 | let paint_type = paint_type.unwrap_or(&PaintType::FG); 30 | format!( 31 | "{};2;{};{};{}", 32 | match paint_type { 33 | PaintType::FG => "38", 34 | PaintType::BG => "48", 35 | }, 36 | self.r, 37 | self.g, 38 | self.b 39 | ) 40 | } 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use super::*; 46 | 47 | #[test] 48 | fn test_make_style_fg() { 49 | let color = Rgb { r: 102, g: 23, b: 240 }; 50 | let styles = color.make_styles(Some(&PaintType::FG)); 51 | assert_eq!(styles, "38;2;102;23;240") 52 | } 53 | 54 | #[test] 55 | fn test_make_style_default_fg() { 56 | let color = Rgb { r: 2, g: 55, b: 100 }; 57 | let styles = color.make_styles(None); 58 | assert_eq!(styles, "38;2;2;55;100") 59 | } 60 | 61 | #[test] 62 | fn test_make_style_bg() { 63 | let color = Rgb { r: 255, g: 255, b: 43 }; 64 | let styles = color.make_styles(Some(&PaintType::BG)); 65 | assert_eq!(styles, "48;2;255;255;43") 66 | } 67 | 68 | #[test] 69 | fn test_fg_and_bg_values() { 70 | let color = Rgb { r: 78, g: 32, b: 210 }; 71 | let styles_fg = color.make_styles(Some(&PaintType::FG)); 72 | let styles_bg = color.make_styles(Some(&PaintType::BG)); 73 | assert_eq!(styles_fg, "38;2;78;32;210"); 74 | assert_eq!(styles_bg, "48;2;78;32;210") 75 | } 76 | 77 | #[test] 78 | fn test_fg_and_bg_values_with_none_paint_type() { 79 | let color = Rgb { r: 1, g: 91, b: 58 }; 80 | let styles_fg = color.make_styles(None); 81 | let styles_bg = color.make_styles(Some(&PaintType::BG)); 82 | assert_eq!(styles_fg, "38;2;1;91;58"); 83 | assert_eq!(styles_bg, "48;2;1;91;58") 84 | } 85 | } 86 | --------------------------------------------------------------------------------