Krolyxon
Commit 96dd350

rmptuisrcconfigtheme.rs

91 lines · 2.4 KB · Rust

1use std::str::FromStr;
2
3use ratatui::style::{Color, Modifier, Style};
4use serde::{Deserialize, Deserializer, de};
5
6/// Colors used throughout the UI.
7#[derive(Clone, Debug, Deserialize)]
8#[serde(deny_unknown_fields)]
9pub struct Theme {
10 #[serde(deserialize_with = "color")]
11 pub accent: Color,
12 #[serde(deserialize_with = "color")]
13 pub text: Color,
14 #[serde(deserialize_with = "color")]
15 pub dim: Color,
16 #[serde(deserialize_with = "color")]
17 pub selection_fg: Color,
18 #[serde(deserialize_with = "color")]
19 pub selection_bg: Color,
20 #[serde(deserialize_with = "color")]
21 pub playing: Color,
22 #[serde(deserialize_with = "color")]
23 pub marked: Color,
24 #[serde(deserialize_with = "color")]
25 pub directory: Color,
26 #[serde(deserialize_with = "color")]
27 pub border: Color,
28 #[serde(deserialize_with = "color")]
29 pub error: Color,
30 #[serde(deserialize_with = "colors")]
31 pub visualizer: Vec<Color>,
32}
33
34impl Theme {
35 pub fn text(&self) -> Style {
36 Style::new().fg(self.text)
37 }
38
39 pub fn dim(&self) -> Style {
40 Style::new().fg(self.dim)
41 }
42
43 pub fn accent(&self) -> Style {
44 Style::new().fg(self.accent)
45 }
46
47 pub fn border(&self) -> Style {
48 Style::new().fg(self.border)
49 }
50
51 /// The highlighted row of a focused list.
52 pub fn selection(&self) -> Style {
53 Style::new().fg(self.selection_fg).bg(self.selection_bg)
54 }
55
56 /// The highlighted row of a list without focus.
57 pub fn selection_inactive(&self) -> Style {
58 Style::new().add_modifier(Modifier::REVERSED)
59 }
60
61 pub fn playing(&self) -> Style {
62 Style::new().fg(self.playing).add_modifier(Modifier::BOLD)
63 }
64
65 pub fn marked(&self) -> Style {
66 Style::new().fg(self.marked)
67 }
68
69 pub fn directory(&self) -> Style {
70 Style::new().fg(self.directory).add_modifier(Modifier::BOLD)
71 }
72
73 pub fn error(&self) -> Style {
74 Style::new().fg(self.error)
75 }
76}
77
78fn parse_color<E: de::Error>(value: &str) -> Result<Color, E> {
79 Color::from_str(value).map_err(|_| E::custom(format!("invalid color `{value}`")))
80}
81
82fn color<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Color, D::Error> {
83 parse_color(&String::deserialize(deserializer)?)
84}
85
86fn colors<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<Color>, D::Error> {
87 Vec::<String>::deserialize(deserializer)?
88 .iter()
89 .map(|value| parse_color(value))
90 .collect()
91}