1use serde::{Deserialize, Deserializer};
2use smart_default::SmartDefault;
3use std::collections::HashMap;
4use std::sync::Arc;
5
6use crate::blocks::BlockConfig;
7use crate::click::ClickHandler;
8use crate::errors::*;
9use crate::formatting::config::Config as FormatConfig;
10use crate::icons::{Icon, Icons};
11use crate::themes::{Theme, ThemeOverrides, ThemeUserConfig};
12
13#[derive(Deserialize, Debug)]
14pub struct Config {
15 #[serde(flatten)]
16 pub shared: SharedConfig,
17
18 #[serde(default)]
20 pub invert_scrolling: bool,
21
22 #[serde(default)]
24 pub double_click_delay: u64,
25
26 #[serde(default = "default_error_format")]
27 pub error_format: FormatConfig,
28 #[serde(default = "default_error_fullscreen")]
29 pub error_fullscreen_format: FormatConfig,
30
31 #[serde(default)]
32 #[serde(rename = "block")]
33 pub blocks: Vec<BlockConfigEntry>,
34}
35
36#[derive(Deserialize, Debug, Clone)]
37pub struct SharedConfig {
38 #[serde(default)]
39 #[serde(deserialize_with = "deserialize_theme_config")]
40 pub theme: Arc<Theme>,
41 #[serde(default)]
42 pub icons: Arc<Icons>,
43 #[serde(default = "default_icons_format")]
44 pub icons_format: Arc<String>,
45}
46
47impl Default for SharedConfig {
48 fn default() -> Self {
49 Self {
50 theme: Default::default(),
51 icons: Default::default(),
52 icons_format: default_icons_format(),
53 }
54 }
55}
56
57fn default_error_format() -> FormatConfig {
58 " {$short_error_message|X} ".parse().unwrap()
59}
60
61fn default_error_fullscreen() -> FormatConfig {
62 " $full_error_message ".parse().unwrap()
63}
64
65fn default_icons_format() -> Arc<String> {
66 Arc::new("{icon}".into())
67}
68
69impl SharedConfig {
70 pub fn get_icon(&self, icon: &str, value: Option<f64>) -> Result<String> {
71 if icon.is_empty() {
72 Ok(String::new())
73 } else {
74 Ok(self.icons_format.replace(
75 "{icon}",
76 self.icons
77 .get(icon, value)
78 .or_error(|| format!("Icon '{icon}' not found"))?,
79 ))
80 }
81 }
82}
83
84#[derive(Deserialize, Debug)]
85pub struct BlockConfigEntry {
86 #[serde(flatten)]
87 pub common: CommonBlockConfig,
88 #[serde(flatten)]
89 pub config: BlockConfig,
90}
91
92#[derive(Deserialize, Debug, SmartDefault)]
93#[serde(default)]
94pub struct CommonBlockConfig {
95 pub click: ClickHandler,
96 pub signal: Option<i32>,
97 pub icons_format: Option<String>,
98 pub theme_overrides: Option<ThemeOverrides>,
99 pub icons_overrides: Option<HashMap<String, Icon>>,
100 pub merge_with_next: bool,
101
102 #[default(5)]
103 pub error_interval: u64,
104 pub error_format: FormatConfig,
105 pub error_fullscreen_format: FormatConfig,
106
107 pub if_command: Option<String>,
108}
109
110fn deserialize_theme_config<'de, D>(deserializer: D) -> Result<Arc<Theme>, D::Error>
111where
112 D: Deserializer<'de>,
113{
114 let theme_config = ThemeUserConfig::deserialize(deserializer)?;
115 let theme = Theme::try_from(theme_config).serde_error()?;
116 Ok(Arc::new(theme))
117}