Skip to content

Commit e40fc6d

Browse files
committed
Allow one or more format to be used
1 parent db4db28 commit e40fc6d

File tree

4 files changed

+88
-7
lines changed

4 files changed

+88
-7
lines changed

src/blocks/prelude.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ pub(crate) use crate::REQWEST_CLIENT;
44
pub(crate) use crate::REQWEST_CLIENT_IPV4;
55
pub use crate::click::MouseButton;
66
pub use crate::errors::*;
7-
pub use crate::formatting::{Values, config::Config as FormatConfig, value::Value};
7+
pub use crate::formatting::{
8+
Values, config::Config as FormatConfig, config::MaybeMultiConfig as MaybeMultiFormatConfig,
9+
value::Value,
10+
};
811
pub use crate::util::{default, new_dbus_connection, new_system_dbus_connection};
912
pub use crate::widget::{State, Widget};
1013
pub use crate::wrappers::{Seconds, ShellString};

src/blocks/time.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! Key | Values | Default
66
//! -----------|--------|--------
7-
//! `format` | Format string. See [chrono docs](https://docs.rs/chrono/0.3.0/chrono/format/strftime/index.html#specifiers) for all options. | `" $icon $timestamp.datetime() "`
7+
//! `format` | MultiFormat string. See [chrono docs](https://docs.rs/chrono/0.3.0/chrono/format/strftime/index.html#specifiers) for all options. | `[" $icon $timestamp.datetime() "]`
88
//! `interval` | Update interval in seconds | `10`
99
//! `timezone` | A timezone specifier (e.g. "Europe/Lisbon") | Local timezone
1010
//!
@@ -55,9 +55,10 @@ use chrono_tz::Tz;
5555
use super::prelude::*;
5656

5757
#[derive(Deserialize, Debug, SmartDefault)]
58-
#[serde(deny_unknown_fields, default)]
58+
#[serde(default)]
5959
pub struct Config {
60-
pub format: FormatConfig,
60+
#[serde(flatten)]
61+
pub format: MaybeMultiFormatConfig,
6162
#[default(10.into())]
6263
pub interval: Seconds,
6364
pub timezone: Option<Timezone>,
@@ -77,7 +78,7 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
7778
(MouseButton::Right, None, "prev_timezone"),
7879
])?;
7980

80-
let format = config
81+
let mut formats = config
8182
.format
8283
.with_default(" $icon $timestamp.datetime() ")?;
8384

@@ -104,7 +105,7 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
104105
timer.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
105106

106107
loop {
107-
let mut widget = Widget::new().with_format(format.clone());
108+
let mut widget = Widget::new().with_format(formats.get_format().clone());
108109
let now = Utc::now();
109110

110111
widget.set_values(map! {
@@ -129,6 +130,12 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
129130
"prev_timezone" => {
130131
timezone = timezone_iter.nth(prev_step_length);
131132
},
133+
"next_format" => {
134+
formats.next_format();
135+
},
136+
"prev_format" => {
137+
formats.prev_format();
138+
},
132139
_ => (),
133140
}
134141
}

src/formatting.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,33 @@ pub enum FormatError {
162162
Other(#[from] Error),
163163
}
164164

165+
#[derive(Debug, Clone)]
166+
pub struct MultiFormat {
167+
// The length is always at least one, so we don't need to worry about
168+
// dividing by zero when doing the modulo math to calculate the
169+
// previous and next formats.
170+
formats: Vec<Format>,
171+
index: usize,
172+
}
173+
174+
impl MultiFormat {
175+
pub fn new(formats: Vec<Format>) -> Self {
176+
Self { formats, index: 0 }
177+
}
178+
179+
pub fn get_format(&self) -> &Format {
180+
&self.formats[self.index]
181+
}
182+
183+
pub fn next_format(&mut self) {
184+
self.index = (self.index + 1) % self.formats.len();
185+
}
186+
187+
pub fn prev_format(&mut self) {
188+
self.index = (self.index + (self.formats.len() - 1)) % self.formats.len();
189+
}
190+
}
191+
165192
#[derive(Debug, Clone)]
166193
pub struct Format {
167194
full: FormatTemplate,

src/formatting/config.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use super::{Format, template::FormatTemplate};
1+
use super::{Format, MultiFormat, template::FormatTemplate};
22
use crate::errors::*;
33
use serde::de::{MapAccess, Visitor};
44
use serde::{Deserialize, Deserializer, de};
5+
use smart_default::SmartDefault;
56
use std::fmt;
67
use std::str::FromStr;
78

@@ -83,6 +84,49 @@ impl Config {
8384
}
8485
}
8586

87+
#[derive(Deserialize, Debug, Clone, SmartDefault)]
88+
#[serde(untagged)]
89+
pub enum MaybeMultiConfig {
90+
#[default]
91+
Split {
92+
format: Option<Config>,
93+
format_alt: Option<Config>,
94+
},
95+
Multiple {
96+
format: Vec<Config>,
97+
},
98+
}
99+
100+
impl MaybeMultiConfig {
101+
pub fn with_default(&self, default_full: &str) -> Result<MultiFormat> {
102+
self.with_defaults(default_full, "")
103+
}
104+
105+
pub fn with_defaults(&self, default_full: &str, default_short: &str) -> Result<MultiFormat> {
106+
Ok(MultiFormat::new(match self {
107+
MaybeMultiConfig::Multiple { format: configs } if configs.is_empty() => {
108+
vec![Config::default().with_defaults(default_full, default_short)?]
109+
}
110+
MaybeMultiConfig::Multiple { format: configs } => configs
111+
.iter()
112+
.map(|config| config.with_defaults("", ""))
113+
.collect::<Result<Vec<_>>>()?,
114+
MaybeMultiConfig::Split { format, format_alt } => {
115+
let mut formats = Vec::new();
116+
if let Some(format) = format {
117+
formats.push(format.with_defaults("", "")?);
118+
} else {
119+
formats.push(Config::default().with_defaults(default_full, default_short)?);
120+
}
121+
if let Some(format_alt) = format_alt {
122+
formats.push(format_alt.with_defaults("", "")?);
123+
}
124+
formats
125+
}
126+
}))
127+
}
128+
}
129+
86130
impl FromStr for Config {
87131
type Err = Error;
88132

0 commit comments

Comments
 (0)