ailloli_ui_terminal_core/
style.rs

1//! Provider-neutral terminal colors and SGR text attributes.
2
3use serde::{Deserialize, Serialize};
4
5/// Terminal foreground/background color selection.
6///
7/// `Ansi` normally carries one of the 16 base palette indices, but all `u8`
8/// values are representable. `Indexed` covers the full 0–255 extended palette.
9/// RGB components are unpremultiplied 0–255 channel values.
10///
11/// # Examples
12///
13/// ```
14/// use ailloli_ui_terminal_core::TerminalColor;
15/// let red = TerminalColor::Rgb(255, 0, 0);
16/// assert_ne!(red, TerminalColor::DefaultFg);
17/// ```
18#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
19pub enum TerminalColor {
20    /// Renderer/theme default foreground.
21    DefaultFg,
22    /// Renderer/theme default background.
23    DefaultBg,
24    /// Base ANSI palette index, conventionally 0–15 but not validated.
25    Ansi(u8),
26    /// Extended 256-color palette index, 0–255.
27    Indexed(u8),
28    /// Explicit red, green, and blue channels, each 0–255.
29    Rgb(u8, u8, u8),
30}
31
32/// Complete style attached to a terminal cell.
33///
34/// Flags are independent; no normalization prevents combinations such as
35/// `bold && dim` or foreground/background defaults used in either field.
36///
37/// # Examples
38///
39/// ```
40/// use ailloli_ui_terminal_core::{TerminalColor, TerminalStyle};
41/// let style = TerminalStyle::default();
42/// assert_eq!((style.fg, style.bg), (TerminalColor::DefaultFg, TerminalColor::DefaultBg));
43/// assert!(!style.bold && !style.inverse);
44/// ```
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46pub struct TerminalStyle {
47    /// Foreground color selection.
48    pub fg: TerminalColor,
49    /// Background color selection.
50    pub bg: TerminalColor,
51    /// Bold/intensified text request.
52    pub bold: bool,
53    /// Italic text request.
54    pub italic: bool,
55    /// Underline text request.
56    pub underline: bool,
57    /// Swap effective foreground and background at rendering time.
58    pub inverse: bool,
59    /// Dim/faint text request.
60    pub dim: bool,
61    /// Strikethrough text request.
62    pub strike: bool,
63}
64
65impl TerminalStyle {
66    /// Returns the default SGR style with every flag disabled.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use ailloli_ui_terminal_core::{TerminalColor, TerminalStyle};
72    /// assert_eq!(TerminalStyle::reset().fg, TerminalColor::DefaultFg);
73    /// assert_eq!(TerminalStyle::reset(), TerminalStyle::default());
74    /// ```
75    pub const fn reset() -> Self {
76        Self {
77            fg: TerminalColor::DefaultFg,
78            bg: TerminalColor::DefaultBg,
79            bold: false,
80            italic: false,
81            underline: false,
82            inverse: false,
83            dim: false,
84            strike: false,
85        }
86    }
87
88    /// Replaces this value with [`Self::reset`].
89    ///
90    /// # Examples
91    ///
92    /// ```
93    /// use ailloli_ui_terminal_core::TerminalStyle;
94    /// let mut style = TerminalStyle { bold: true, ..TerminalStyle::default() };
95    /// style.reset_sgr();
96    /// assert!(!style.bold);
97    /// ```
98    pub fn reset_sgr(&mut self) {
99        *self = Self::reset();
100    }
101}
102
103impl Default for TerminalStyle {
104    fn default() -> Self {
105        Self::reset()
106    }
107}