term_tools/
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
6mod ansi_code;
7mod styles;
8
9// =======================================================================
10use 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.
71pub fn styled(text: &str) -> StyledText {
72    StyledText::new(text.to_string())
73}
74
75/// A struct representing a styled text string.
76pub struct StyledText {
77    text: String,
78    start_styles: Vec<Styles>,
79}
80
81impl 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<String> = 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::<Vec<_>>()
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}