oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
10,480 bytes raw
1
use crate::bar::{BlockCommand, BlockConfig};
2
use crate::errors::ConfigError;
3
use crate::keyboard::handlers::Key;
4
use crate::keyboard::keycodes;
5
use crate::keyboard::{Arg, KeyAction};
6
use serde::Deserialize;
7
use x11rb::protocol::xproto::{KeyButMask, Keycode};
8
9
#[derive(Debug, Deserialize)]
10
pub enum ModKey {
11
    Mod1,
12
    Mod2,
13
    Mod3,
14
    Mod4,
15
    Mod5,
16
    Shift,
17
    Control,
18
}
19
20
impl ModKey {
21
    fn to_keybut_mask(&self) -> KeyButMask {
22
        match self {
23
            ModKey::Mod1 => KeyButMask::MOD1,
24
            ModKey::Mod2 => KeyButMask::MOD2,
25
            ModKey::Mod3 => KeyButMask::MOD3,
26
            ModKey::Mod4 => KeyButMask::MOD4,
27
            ModKey::Mod5 => KeyButMask::MOD5,
28
            ModKey::Shift => KeyButMask::SHIFT,
29
            ModKey::Control => KeyButMask::CONTROL,
30
        }
31
    }
32
}
33
34
#[rustfmt::skip]
35
#[derive(Debug, Deserialize)]
36
pub enum KeyData {
37
    Return,
38
    Q,
39
    Escape,
40
    Space,
41
    Tab,
42
    Backspace,
43
    Delete,
44
    F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
45
    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, R, S, T, U, V, W, X, Y, Z,
46
    Key0,
47
    Key1,
48
    Key2,
49
    Key3,
50
    Key4,
51
    Key5,
52
    Key6,
53
    Key7,
54
    Key8,
55
    Key9,
56
    Left,
57
    Right,
58
    Up,
59
    Down,
60
    Home,
61
    End,
62
    PageUp,
63
    PageDown,
64
    Insert,
65
    Minus,
66
    Equal,
67
    BracketLeft,
68
    BracketRight,
69
    Semicolon,
70
    Apostrophe,
71
    Grave,
72
    Backslash,
73
    Comma,
74
    Period,
75
    Slash,
76
}
77
78
impl KeyData {
79
    fn to_keycode(&self) -> Keycode {
80
        match self {
81
            KeyData::Return => keycodes::RETURN,
82
            KeyData::Q => keycodes::Q,
83
            KeyData::Escape => keycodes::ESCAPE,
84
            KeyData::Space => keycodes::SPACE,
85
            KeyData::Tab => keycodes::TAB,
86
            KeyData::Backspace => keycodes::BACKSPACE,
87
            KeyData::Delete => keycodes::DELETE,
88
            KeyData::F1 => keycodes::F1,
89
            KeyData::F2 => keycodes::F2,
90
            KeyData::F3 => keycodes::F3,
91
            KeyData::F4 => keycodes::F4,
92
            KeyData::F5 => keycodes::F5,
93
            KeyData::F6 => keycodes::F6,
94
            KeyData::F7 => keycodes::F7,
95
            KeyData::F8 => keycodes::F8,
96
            KeyData::F9 => keycodes::F9,
97
            KeyData::F10 => keycodes::F10,
98
            KeyData::F11 => keycodes::F11,
99
            KeyData::F12 => keycodes::F12,
100
            KeyData::A => keycodes::A,
101
            KeyData::B => keycodes::B,
102
            KeyData::C => keycodes::C,
103
            KeyData::D => keycodes::D,
104
            KeyData::E => keycodes::E,
105
            KeyData::F => keycodes::F,
106
            KeyData::G => keycodes::G,
107
            KeyData::H => keycodes::H,
108
            KeyData::I => keycodes::I,
109
            KeyData::J => keycodes::J,
110
            KeyData::K => keycodes::K,
111
            KeyData::L => keycodes::L,
112
            KeyData::M => keycodes::M,
113
            KeyData::N => keycodes::N,
114
            KeyData::O => keycodes::O,
115
            KeyData::P => keycodes::P,
116
            KeyData::R => keycodes::R,
117
            KeyData::S => keycodes::S,
118
            KeyData::T => keycodes::T,
119
            KeyData::U => keycodes::U,
120
            KeyData::V => keycodes::V,
121
            KeyData::W => keycodes::W,
122
            KeyData::X => keycodes::X,
123
            KeyData::Y => keycodes::Y,
124
            KeyData::Z => keycodes::Z,
125
            KeyData::Key0 => keycodes::KEY_0,
126
            KeyData::Key1 => keycodes::KEY_1,
127
            KeyData::Key2 => keycodes::KEY_2,
128
            KeyData::Key3 => keycodes::KEY_3,
129
            KeyData::Key4 => keycodes::KEY_4,
130
            KeyData::Key5 => keycodes::KEY_5,
131
            KeyData::Key6 => keycodes::KEY_6,
132
            KeyData::Key7 => keycodes::KEY_7,
133
            KeyData::Key8 => keycodes::KEY_8,
134
            KeyData::Key9 => keycodes::KEY_9,
135
            KeyData::Left => keycodes::LEFT,
136
            KeyData::Right => keycodes::RIGHT,
137
            KeyData::Up => keycodes::UP,
138
            KeyData::Down => keycodes::DOWN,
139
            KeyData::Home => keycodes::HOME,
140
            KeyData::End => keycodes::END,
141
            KeyData::PageUp => keycodes::PAGE_UP,
142
            KeyData::PageDown => keycodes::PAGE_DOWN,
143
            KeyData::Insert => keycodes::INSERT,
144
            KeyData::Minus => keycodes::MINUS,
145
            KeyData::Equal => keycodes::EQUAL,
146
            KeyData::BracketLeft => keycodes::LEFT_BRACKET,
147
            KeyData::BracketRight => keycodes::RIGHT_BRACKET,
148
            KeyData::Semicolon => keycodes::SEMICOLON,
149
            KeyData::Apostrophe => keycodes::APOSTROPHE,
150
            KeyData::Grave => keycodes::GRAVE,
151
            KeyData::Backslash => keycodes::BACKSLASH,
152
            KeyData::Comma => keycodes::COMMA,
153
            KeyData::Period => keycodes::PERIOD,
154
            KeyData::Slash => keycodes::SLASH,
155
        }
156
    }
157
}
158
159
pub fn parse_config(input: &str) -> Result<crate::Config, ConfigError> {
160
    let config_data: ConfigData = ron::from_str(input)?;
161
    config_data_to_config(config_data)
162
}
163
164
#[derive(Debug, Deserialize)]
165
struct ConfigData {
166
    border_width: u32,
167
    border_focused: u32,
168
    border_unfocused: u32,
169
    font: String,
170
171
    gaps_enabled: bool,
172
    gap_inner_horizontal: u32,
173
    gap_inner_vertical: u32,
174
    gap_outer_horizontal: u32,
175
    gap_outer_vertical: u32,
176
177
    terminal: String,
178
    modkey: ModKey,
179
180
    tags: Vec<String>,
181
    keybindings: Vec<KeybindingData>,
182
    status_blocks: Vec<StatusBlockData>,
183
184
    scheme_normal: ColorSchemeData,
185
    scheme_occupied: ColorSchemeData,
186
    scheme_selected: ColorSchemeData,
187
}
188
189
#[derive(Debug, Deserialize)]
190
struct KeybindingData {
191
    modifiers: Vec<ModKey>,
192
    key: KeyData,
193
    action: KeyAction,
194
    #[serde(default)]
195
    arg: ArgData,
196
}
197
198
#[derive(Debug, Deserialize)]
199
#[serde(untagged)]
200
enum ArgData {
201
    None,
202
    String(String),
203
    Int(i32),
204
    Array(Vec<String>),
205
}
206
207
impl Default for ArgData {
208
    fn default() -> Self {
209
        ArgData::None
210
    }
211
}
212
213
#[derive(Debug, Deserialize)]
214
struct StatusBlockData {
215
    format: String,
216
    command: String,
217
    #[serde(default)]
218
    command_arg: Option<String>,
219
    #[serde(default)]
220
    battery_formats: Option<BatteryFormats>,
221
    interval_secs: u64,
222
    color: u32,
223
    underline: bool,
224
}
225
226
#[derive(Debug, Deserialize)]
227
struct BatteryFormats {
228
    charging: String,
229
    discharging: String,
230
    full: String,
231
}
232
233
#[derive(Debug, Deserialize)]
234
struct ColorSchemeData {
235
    foreground: u32,
236
    background: u32,
237
    underline: u32,
238
}
239
240
fn config_data_to_config(data: ConfigData) -> Result<crate::Config, ConfigError> {
241
    let modkey = data.modkey.to_keybut_mask();
242
243
    let mut keybindings = Vec::new();
244
    for kb_data in data.keybindings {
245
        let modifiers = kb_data
246
            .modifiers
247
            .iter()
248
            .map(|m| m.to_keybut_mask())
249
            .collect();
250
251
        let key = kb_data.key.to_keycode();
252
        let action = kb_data.action;
253
        let arg = arg_data_to_arg(kb_data.arg)?;
254
255
        keybindings.push(Key::new(modifiers, key, action, arg));
256
    }
257
258
    let mut status_blocks = Vec::new();
259
    for block_data in data.status_blocks {
260
        let command = match block_data.command.as_str() {
261
            "DateTime" => {
262
                let fmt = block_data
263
                    .command_arg
264
                    .ok_or_else(|| ConfigError::MissingCommandArg {
265
                        command: "DateTime".to_string(),
266
                        field: "command_arg".to_string(),
267
                    })?;
268
                BlockCommand::DateTime(fmt)
269
            }
270
            "Shell" => {
271
                let cmd = block_data
272
                    .command_arg
273
                    .ok_or_else(|| ConfigError::MissingCommandArg {
274
                        command: "Shell".to_string(),
275
                        field: "command_arg".to_string(),
276
                    })?;
277
                BlockCommand::Shell(cmd)
278
            }
279
            "Ram" => BlockCommand::Ram,
280
            "Static" => {
281
                let text = block_data.command_arg.unwrap_or_default();
282
                BlockCommand::Static(text)
283
            }
284
            "Battery" => {
285
                let formats =
286
                    block_data
287
                        .battery_formats
288
                        .ok_or_else(|| ConfigError::MissingCommandArg {
289
                            command: "Battery".to_string(),
290
                            field: "battery_formats".to_string(),
291
                        })?;
292
                BlockCommand::Battery {
293
                    format_charging: formats.charging,
294
                    format_discharging: formats.discharging,
295
                    format_full: formats.full,
296
                }
297
            }
298
            _ => return Err(ConfigError::UnknownBlockCommand(block_data.command)),
299
        };
300
301
        status_blocks.push(BlockConfig {
302
            format: block_data.format,
303
            command,
304
            interval_secs: block_data.interval_secs,
305
            color: block_data.color,
306
            underline: block_data.underline,
307
        });
308
    }
309
310
    Ok(crate::Config {
311
        border_width: data.border_width,
312
        border_focused: data.border_focused,
313
        border_unfocused: data.border_unfocused,
314
        font: data.font,
315
        gaps_enabled: data.gaps_enabled,
316
        gap_inner_horizontal: data.gap_inner_horizontal,
317
        gap_inner_vertical: data.gap_inner_vertical,
318
        gap_outer_horizontal: data.gap_outer_horizontal,
319
        gap_outer_vertical: data.gap_outer_vertical,
320
        terminal: data.terminal,
321
        modkey,
322
        tags: data.tags,
323
        keybindings,
324
        status_blocks,
325
        scheme_normal: crate::ColorScheme {
326
            foreground: data.scheme_normal.foreground,
327
            background: data.scheme_normal.background,
328
            underline: data.scheme_normal.underline,
329
        },
330
        scheme_occupied: crate::ColorScheme {
331
            foreground: data.scheme_occupied.foreground,
332
            background: data.scheme_occupied.background,
333
            underline: data.scheme_occupied.underline,
334
        },
335
        scheme_selected: crate::ColorScheme {
336
            foreground: data.scheme_selected.foreground,
337
            background: data.scheme_selected.background,
338
            underline: data.scheme_selected.underline,
339
        },
340
    })
341
}
342
343
fn arg_data_to_arg(data: ArgData) -> Result<Arg, ConfigError> {
344
    match data {
345
        ArgData::None => Ok(Arg::None),
346
        ArgData::String(s) => Ok(Arg::Str(s)),
347
        ArgData::Int(n) => Ok(Arg::Int(n)),
348
        ArgData::Array(arr) => Ok(Arg::Array(arr)),
349
    }
350
}