i3status_rs/formatting/
config.rs

1use super::{Format, template::FormatTemplate};
2use crate::errors::*;
3use serde::de::{MapAccess, Visitor};
4use serde::{Deserialize, Deserializer, de};
5use std::fmt;
6use std::str::FromStr;
7
8#[derive(Debug, Default, Clone)]
9pub struct Config {
10    pub full: Option<FormatTemplate>,
11    pub short: Option<FormatTemplate>,
12}
13
14impl Config {
15    pub fn with_default(&self, default_full: &str) -> Result<Format> {
16        self.with_defaults(default_full, "")
17    }
18
19    pub fn with_defaults(&self, default_full: &str, default_short: &str) -> Result<Format> {
20        let full = match self.full.clone() {
21            Some(full) => full,
22            None => default_full.parse()?,
23        };
24
25        let short = match self.short.clone() {
26            Some(short) => short,
27            None => default_short.parse()?,
28        };
29
30        let mut intervals = Vec::new();
31        full.init_intervals(&mut intervals);
32        short.init_intervals(&mut intervals);
33
34        Ok(Format {
35            full,
36            short,
37            intervals,
38        })
39    }
40
41    pub fn with_default_config(&self, default_config: &Self) -> Format {
42        let full = self
43            .full
44            .clone()
45            .or_else(|| default_config.full.clone())
46            .unwrap_or_default();
47        let short = self
48            .short
49            .clone()
50            .or_else(|| default_config.short.clone())
51            .unwrap_or_default();
52
53        let mut intervals = Vec::new();
54        full.init_intervals(&mut intervals);
55        short.init_intervals(&mut intervals);
56
57        Format {
58            full,
59            short,
60            intervals,
61        }
62    }
63
64    pub fn with_default_format(&self, default_format: &Format) -> Format {
65        let full = self
66            .full
67            .clone()
68            .unwrap_or_else(|| default_format.full.clone());
69        let short = self
70            .short
71            .clone()
72            .unwrap_or_else(|| default_format.short.clone());
73
74        let mut intervals = Vec::new();
75        full.init_intervals(&mut intervals);
76        short.init_intervals(&mut intervals);
77
78        Format {
79            full,
80            short,
81            intervals,
82        }
83    }
84}
85
86impl FromStr for Config {
87    type Err = Error;
88
89    fn from_str(s: &str) -> Result<Self, Self::Err> {
90        Ok(Self {
91            full: Some(s.parse()?),
92            short: None,
93        })
94    }
95}
96
97impl<'de> Deserialize<'de> for Config {
98    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99    where
100        D: Deserializer<'de>,
101    {
102        #[derive(Deserialize)]
103        #[serde(field_identifier, rename_all = "lowercase")]
104        enum Field {
105            Full,
106            Short,
107        }
108
109        struct FormatTemplateVisitor;
110
111        impl<'de> Visitor<'de> for FormatTemplateVisitor {
112            type Value = Config;
113
114            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
115                formatter.write_str("format structure")
116            }
117
118            /// Handle configs like:
119            ///
120            /// ```toml
121            /// format = "{layout}"
122            /// ```
123            fn visit_str<E>(self, full: &str) -> Result<Config, E>
124            where
125                E: de::Error,
126            {
127                full.parse().serde_error()
128            }
129
130            /// Handle configs like:
131            ///
132            /// ```toml
133            /// [block.format]
134            /// full = "{layout}"
135            /// short = "{layout^2}"
136            /// ```
137            fn visit_map<V>(self, mut map: V) -> Result<Config, V::Error>
138            where
139                V: MapAccess<'de>,
140            {
141                let mut full: Option<FormatTemplate> = None;
142                let mut short: Option<FormatTemplate> = None;
143                while let Some(key) = map.next_key()? {
144                    match key {
145                        Field::Full => {
146                            if full.is_some() {
147                                return Err(de::Error::duplicate_field("full"));
148                            }
149                            full = Some(map.next_value::<String>()?.parse().serde_error()?);
150                        }
151                        Field::Short => {
152                            if short.is_some() {
153                                return Err(de::Error::duplicate_field("short"));
154                            }
155                            short = Some(map.next_value::<String>()?.parse().serde_error()?);
156                        }
157                    }
158                }
159                Ok(Config { full, short })
160            }
161        }
162
163        deserializer.deserialize_any(FormatTemplateVisitor)
164    }
165}