1use serde::{Deserialize, Serialize};
2
3fn is_false(v: &bool) -> bool {
4 !*v
5}
6
7pub fn is_plain_style(s: &Style) -> bool {
9 *s == Style::plain()
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
17pub struct Style {
18 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub fg: Option<u8>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub bg: Option<u8>,
22 #[serde(default, skip_serializing_if = "is_false")]
24 pub dim: bool,
25 #[serde(default, skip_serializing_if = "is_false")]
26 pub bold: bool,
27 #[serde(default, skip_serializing_if = "is_false")]
29 pub italic: bool,
30 #[serde(default, skip_serializing_if = "is_false")]
31 pub underline: bool,
32 #[serde(default, skip_serializing_if = "is_false")]
34 pub blink: bool,
35 #[serde(default, skip_serializing_if = "is_false", rename = "reverse")]
37 pub inverse: bool,
38 #[serde(default, skip_serializing_if = "is_false", rename = "strikethrough")]
40 pub strike: bool,
41}
42
43impl Style {
44 pub const fn plain() -> Self {
45 Self {
46 fg: None,
47 bg: None,
48 dim: false,
49 bold: false,
50 italic: false,
51 underline: false,
52 blink: false,
53 inverse: false,
54 strike: false,
55 }
56 }
57
58 #[must_use]
64 pub const fn overlay(self, top: Style) -> Style {
65 Style {
66 fg: match top.fg {
67 Some(v) => Some(v),
68 None => self.fg,
69 },
70 bg: match top.bg {
71 Some(v) => Some(v),
72 None => self.bg,
73 },
74 dim: self.dim || top.dim,
75 bold: self.bold || top.bold,
76 italic: self.italic || top.italic,
77 underline: self.underline || top.underline,
78 blink: self.blink || top.blink,
79 inverse: self.inverse || top.inverse,
80 strike: self.strike || top.strike,
81 }
82 }
83}