1use serde::{Deserialize, Serialize};
2use smart_default::SmartDefault;
3use std::fmt::Display;
4
5#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
6#[serde(default, deny_unknown_fields)]
7pub struct Config {
8 #[default = true]
9 pub layerrules: bool,
10 #[default(None)]
11 pub launcher: Option<Launcher>,
12 #[default(Some(Windows::default()))]
13 pub windows: Option<Windows>,
14}
15
16#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
17#[serde(default, deny_unknown_fields)]
18pub struct Launcher {
19 #[default(None)]
20 pub default_terminal: Option<Box<str>>,
21 #[default = 650]
22 pub width: u32,
23 #[default = 5]
24 pub max_items: u8,
25 #[default = true]
26 pub show_when_empty: bool,
27 #[default = 250]
28 pub animate_launch_ms: u64,
29 #[default(Plugins::default())]
30 pub plugins: Plugins,
31}
32
33#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
34#[serde(default, deny_unknown_fields)]
35pub struct Plugins {
36 #[default(Some(Default::default()))]
37 pub applications: Option<ApplicationsPluginConfig>,
38 #[default(Some(Default::default()))]
39 pub terminal: Option<EmptyConfig>,
40 #[default(None)]
41 pub shell: Option<EmptyConfig>,
42 #[default(Some(Default::default()))]
43 pub websearch: Option<WebSearchConfig>,
44 #[default(Some(Default::default()))]
45 pub calc: Option<EmptyConfig>,
46}
47
48#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
49#[serde(default, deny_unknown_fields)]
50pub struct EmptyConfig {}
51
52#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
53#[serde(default, deny_unknown_fields)]
54pub struct ApplicationsPluginConfig {
55 #[default = 4]
56 pub run_cache_weeks: u8,
57 #[default = true]
58 pub show_execs: bool,
59}
60
61#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
62#[serde(default, deny_unknown_fields)]
63pub struct WebSearchConfig {
64 #[default(vec![SearchEngine {
65 url: "https://www.google.com/search?q={}".into(),
66 name: "Google".into(),
67 key: 'g',
68 }])]
69 pub engines: Vec<SearchEngine>,
70}
71
72#[derive(Debug, Clone, Deserialize, Serialize)]
73#[serde(deny_unknown_fields)]
74pub struct SearchEngine {
75 pub url: String,
76 pub name: String,
77 pub key: char,
78}
79
80#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
81#[serde(default, deny_unknown_fields)]
82pub struct Windows {
83 #[default = 8.5]
84 pub scale: f64,
85 #[default = 5]
86 pub workspaces_per_row: u8,
87 #[default = true]
88 pub strip_html_from_workspace_title: bool,
89 pub overview: Option<Overview>,
90 pub switch: Option<Switch>,
91}
92
93#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
94#[serde(default, deny_unknown_fields)]
95pub struct Overview {
96 pub open: OpenOverview,
97 pub navigate: Navigate,
98 pub other: OtherOverview,
99}
100
101#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
102#[serde(default, deny_unknown_fields)]
103pub struct OtherOverview {
104 #[default(Vec::new())]
105 pub filter_by: Vec<FilterBy>,
106 #[default = false]
107 pub hide_filtered: bool,
108}
109
110#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
111#[serde(default, deny_unknown_fields)]
112pub struct OpenOverview {
113 #[default = "super"]
114 pub key: KeyMaybeMod,
115 #[default(Mod::Super)]
116 pub modifier: Mod,
117}
118
119#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
120#[serde(default, deny_unknown_fields)]
121pub struct Navigate {
122 #[default = "tab"]
123 pub forward: String,
124 #[default(Reverse::Mod(Mod::Shift))]
125 pub reverse: Reverse,
126}
127
128#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
129#[serde(default, deny_unknown_fields)]
130pub struct Switch {
131 pub open: OpenSwitch,
132 pub navigate: Navigate,
133 pub other: OtherSwitch,
134}
135
136#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
137#[serde(default, deny_unknown_fields)]
138pub struct OpenSwitch {
139 #[default(Mod::Super)]
140 pub modifier: Mod,
141}
142
143#[derive(SmartDefault, Debug, Clone, Deserialize, Serialize)]
144#[serde(default, deny_unknown_fields)]
145pub struct OtherSwitch {
146 #[default(Vec::new())]
147 pub filter_by: Vec<FilterBy>,
148 #[default = true]
149 pub hide_filtered: bool,
150}
151
152#[derive(Debug, Clone, Copy, Deserialize, Serialize, Eq, PartialEq)]
153#[serde(rename_all = "snake_case")]
154pub enum FilterBy {
155 SameClass,
156 CurrentWorkspace,
157 CurrentMonitor,
158}
159
160#[derive(Debug, Clone, Deserialize, Serialize)]
161#[serde(rename_all = "snake_case")]
162pub enum Reverse {
163 Key(String),
164 Mod(Mod),
165}
166#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
167#[serde(rename_all = "snake_case")]
168pub enum Mod {
169 Alt,
170 Ctrl,
171 Super,
172 Shift,
173}
174
175impl Display for Mod {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 match self {
178 Mod::Alt => write!(f, "alt"),
179 Mod::Ctrl => write!(f, "ctrl"),
180 Mod::Super => write!(f, "super"),
181 Mod::Shift => write!(f, "shift"),
182 }
183 }
184}
185
186#[derive(Debug, Clone, Deserialize, Serialize)]
187pub struct KeyMaybeMod(String);
188impl From<&str> for KeyMaybeMod {
189 fn from(s: &str) -> Self {
190 Self(s.to_string())
191 }
192}
193
194impl KeyMaybeMod {
197 pub fn to_key(&self) -> String {
198 match &*self.0.to_ascii_lowercase() {
199 "alt" => "alt_l".to_string(),
200 "ctrl" => "ctrl_l".to_string(),
201 "super" => "super_l".to_string(),
202 "shift" => "shift_l".to_string(),
203 a => a.to_string(),
204 }
205 }
206}
207
208impl Mod {
209 pub fn mod_to_keys(&self) -> [&'static str; 2] {
210 match self {
211 Mod::Alt => ["alt_l", "alt_r"],
212 Mod::Ctrl => ["control_l", "control_r"], Mod::Super => ["super_l", "super_r"],
214 Mod::Shift => ["shift_l", "shift_r"],
215 }
216 }
217}