oxwm

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