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(
37 default,
38 skip_serializing_if = "is_false",
39 rename = "reverse",
40 alias = "inverse"
41 )]
42 pub inverse: bool,
43 #[serde(
45 default,
46 skip_serializing_if = "is_false",
47 rename = "strikethrough",
48 alias = "strike"
49 )]
50 pub strike: bool,
51}
52
53impl Style {
54 pub const fn plain() -> Self {
55 Self {
56 fg: None,
57 bg: None,
58 dim: false,
59 bold: false,
60 italic: false,
61 underline: false,
62 blink: false,
63 inverse: false,
64 strike: false,
65 }
66 }
67
68 #[must_use]
74 pub const fn overlay(self, top: Style) -> Style {
75 Style {
76 fg: match top.fg {
77 Some(v) => Some(v),
78 None => self.fg,
79 },
80 bg: match top.bg {
81 Some(v) => Some(v),
82 None => self.bg,
83 },
84 dim: self.dim || top.dim,
85 bold: self.bold || top.bold,
86 italic: self.italic || top.italic,
87 underline: self.underline || top.underline,
88 blink: self.blink || top.blink,
89 inverse: self.inverse || top.inverse,
90 strike: self.strike || top.strike,
91 }
92 }
93}