1use crate::colors::Colors;
5use crate::layout::Layout;
6use std::io::stdout;
7use std::io::Result;
8use std::io::Write;
9use std::process::Command;
10
11#[derive(Clone, Debug)]
15pub struct Keybind {
16 modifier: String,
17 keymap: String,
18 command: String,
19}
20pub struct KeyboardLayout<T> {
22 pub rules: Option<T>,
23 pub model: Option<T>,
24 pub variant: Option<T>,
25 pub options: Option<T>,
26 pub layout: Option<T>,
27}
28#[derive(Debug)]
33pub struct Config {
34 keybinds: Vec<Keybind>,
35 colors: Colors,
36 layout: Layout,
37 modifier: String,
38}
39
40impl Config {
42 fn serialize_to_owned(&self, arr: &Vec<[&str; 2]>) -> Vec<Vec<String>> {
44 let mut new_arr: Vec<Vec<String>> = Vec::new();
45
46 for keybind in arr {
47 new_arr.push(vec![String::from(keybind[0]), String::from(keybind[1])])
48 }
49
50 new_arr
51 }
52
53 pub fn print_keybindings(&self) {
54 let mut writer = stdout();
55 write!(writer, "{:?}", self.keybinds).unwrap();
56 }
57}
58
59impl Config {
61 pub fn set_keybind(&mut self, keys: &str, command: &str) -> &mut Self {
73 let keybind = Keybind {
74 modifier: self.modifier.clone(),
75 keymap: String::from(keys),
76 command: String::from(command),
77 };
78
79 self.keybinds.push(keybind);
80 self
81 }
82 pub fn set_keybinds(&mut self, keybinds: Vec<[&str; 2]>) -> &mut Self {
101 let keybinds = self.serialize_to_owned(&keybinds);
102
103 for keybind in keybinds {
104 self.set_keybind(&keybind[0], &keybind[1]);
105 }
106
107 self
108 }
109
110 pub fn set_mouse_keybinds(
121 &mut self,
122 left: Option<&str>,
123 right: Option<&str>,
124 middle: Option<&str>,
125 ) -> &mut Self {
126 if let Some(left_command) = left {
127 self.apply_mouse_keybind("left", left_command);
128 }
129 if let Some(right_command) = right {
130 self.apply_mouse_keybind("right", right_command);
131 }
132 if let Some(middle_command) = middle {
133 self.apply_mouse_keybind("middle", middle_command);
134 }
135 self
136 }
137
138 fn apply_mouse_keybind(&self, position: &str, command: &str) {
139 let pos: &str = match position {
140 "left" => "BTN_LEFT",
141
142 "right" => "BTN_RIGHT",
143
144 "middle" => "BTN_MIDDLE",
145
146 _ => "BTN_LEFT",
147 };
148 Command::new("riverctl")
149 .args([
150 "map-pointer",
151 "normal",
152 self.modifier.as_str(),
153 pos,
154 command,
155 ])
156 .spawn()
157 .expect("Can't set the mouse keybind")
158 .wait()
159 .unwrap();
160 }
161
162 fn apply_keybind(&self, keybind: Keybind) {
163 let command: Vec<&str> = keybind.command.split_whitespace().collect();
164 match command.len() {
165 1 => {
166 Command::new("riverctl")
167 .args([
168 "map",
169 "normal",
170 keybind.modifier.as_str(),
171 keybind.keymap.as_str(),
172 command[0],
173 ])
174 .spawn()
175 .expect("Can't set the keybind\n")
176 .wait()
177 .unwrap();
178 }
179 2 => {
180 let args = [
181 "map",
182 "normal",
183 keybind.modifier.as_str(),
184 keybind.keymap.as_str(),
185 command[0],
186 command[1],
187 ];
188 Command::new("riverctl")
189 .args(args)
190 .spawn()
191 .expect("Can't set the keybind\n")
192 .wait()
193 .unwrap();
194 }
195 0 => {
196 panic!("There are no commands provided for the riverctl!\n")
197 }
198 _ => {
199 let args: Vec<&str> = [
200 "map",
201 "normal",
202 keybind.modifier.as_str(),
203 keybind.keymap.as_str(),
204 ]
205 .iter()
206 .chain(&command)
207 .copied()
208 .collect();
209 Command::new("riverctl")
210 .args(args)
211 .spawn()
212 .expect("Can't set the keybind\n")
213 .wait()
214 .unwrap();
215 }
216 }
217 }
218}
219
220impl Default for Config {
221 fn default() -> Self {
226 Config {
227 keybinds: vec![],
228 colors: Colors::default(),
229 layout: Layout::default(),
230 modifier: String::from("Super"),
231 }
232 }
233}
234
235impl Config {
237 pub fn set_repeat(&mut self, repeat_rate: u32, repeat_delay: u32) -> &mut Self {
243 Command::new("riverctl")
244 .args([
245 "set-repeat",
246 repeat_rate.to_string().as_str(),
247 repeat_delay.to_string().as_str(),
248 ])
249 .spawn()
250 .expect("Can't set xkb settings")
251 .wait()
252 .unwrap();
253
254 self
255 }
256
257 pub fn set_layout_generator(&mut self, layout: Layout) -> &mut Self {
258 self.layout = layout;
259 self
260 }
261 pub fn set_keyboard_layout(&mut self, layout: KeyboardLayout<&str>) -> &mut Self {
264 let rules = layout.rules.unwrap_or("");
265 let model = layout.model.unwrap_or("");
266 let variant = layout.variant.unwrap_or("");
267 let options = layout.options.unwrap_or("");
268
269 let layout = match layout.layout {
270 Some(layout) => layout,
271 None => panic!("Keyboard layout is not set"),
272 };
273
274 Command::new("riverctl")
275 .args([
276 "keyboard-layout",
277 "-rules",
278 rules,
279 "-model",
280 model,
281 "-variant",
282 variant,
283 "-options",
284 options,
285 layout,
286 ])
287 .spawn()
288 .expect("Can't set the keyboard layout!\n")
289 .wait()
290 .unwrap();
291 self
292 }
293
294 pub fn change_super(&mut self, key: &str) -> &mut Self {
322 self.modifier = String::from(key);
323 self
324 }
325
326 pub fn set_tags(&mut self, modifier: &str, switch_modifier: &str) -> &mut Self {
328 let tags: Vec<u32> = (0..9).collect();
329 let tag_ids: Vec<u32> = tags.iter().map(|x| 2_u32.pow(*x)).collect();
330 let mut keybinds: Vec<Keybind> = Vec::new();
331 let mut idx = 0;
332 while idx < tags.len() {
333 keybinds.push(Keybind {
334 modifier: String::from(modifier),
335 keymap: (tags[idx] + 1).to_string(),
336 command: String::from("set-focused-tags ") + tag_ids[idx].to_string().as_str(),
337 });
338 keybinds.push(Keybind {
339 modifier: String::from(switch_modifier),
340 keymap: (tags[idx] + 1).to_string(),
341 command: String::from("set-view-tags ") + tag_ids[idx].to_string().as_str(),
342 });
343 idx += 1;
344 }
345 for keybind in keybinds {
346 self.keybinds.push(keybind);
347 }
348 self
349 }
350
351 pub fn autostart(&mut self, applications: Vec<&str>) -> &mut Self {
364 for app in applications {
365 Command::new("riverctl")
366 .args(["spawn", app])
367 .spawn()
368 .expect("Can't spawn autostart programs")
369 .wait()
370 .unwrap();
371 }
372 self
373 }
374
375 fn apply_colors(&mut self) -> &mut Self {
376 let background_color = format!("{:#X}", self.colors.background_color);
377 let border_color_focused = format!("{:#X}", self.colors.border_color_focused);
378 let border_color_unfocused = format!("{:#X}", self.colors.border_color_unfocused);
379
380 let commands = vec![
381 ["background-color", background_color.as_str()],
382 ["border-color-focused", border_color_focused.as_str()],
383 ["border-color-unfocused", border_color_unfocused.as_str()],
384 ];
385
386 for command in commands {
387 Command::new("riverctl")
388 .args(command)
389 .spawn()
390 .expect("Can't set colors with riverctl\n")
391 .wait()
392 .unwrap();
393 }
394
395 self
396 }
397
398 pub fn apply(&mut self) -> Result<()> {
402 for keybind in &self.keybinds {
403 let keybind = keybind.clone();
404 self.apply_keybind(keybind);
405 }
406 self.layout.spawn();
407 Ok(())
408 }
409}