Diff
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 2fc4649..4e30d22 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -4,6 +4,7 @@ use crate::keyboard::handlers::Key;
use crate::keyboard::keycodes;
use crate::keyboard::{Arg, KeyAction};
use serde::Deserialize;
+use std::collections::HashMap;
use x11rb::protocol::xproto::{KeyButMask, Keycode};
#[derive(Debug, Deserialize)]
@@ -156,8 +157,57 @@ impl KeyData {
}
}
+fn preprocess_variables(input: &str) -> Result<String, ConfigError> {
+ let mut variables: HashMap<String, String> = HashMap::new();
+ let mut result = String::new();
+
+ for line in input.lines() {
+ let trimmed = line.trim();
+
+ if trimmed.starts_with("#DEFINE") {
+ let rest = trimmed.strip_prefix("#DEFINE").unwrap().trim();
+
+ if let Some(eq_pos) = rest.find('=') {
+ let var_name = rest[..eq_pos].trim();
+ let value = rest[eq_pos + 1..].trim().trim_end_matches(',');
+
+ if !var_name.starts_with('$') {
+ return Err(ConfigError::InvalidVariableName(var_name.to_string()));
+ }
+
+ variables.insert(var_name.to_string(), value.to_string());
+ } else {
+ return Err(ConfigError::InvalidDefine(trimmed.to_string()));
+ }
+
+ result.push('\n');
+ } else {
+ let mut processed_line = line.to_string();
+ for (var_name, value) in &variables {
+ processed_line = processed_line.replace(var_name, value);
+ }
+ result.push_str(&processed_line);
+ result.push('\n');
+ }
+ }
+
+ for line in result.lines() {
+ if let Some(var_start) = line.find('$') {
+ let rest = &line[var_start..];
+ let var_end = rest[1..]
+ .find(|c: char| !c.is_alphanumeric() && c != '_')
+ .unwrap_or(rest.len() - 1)
+ + 1;
+ let undefined_var = &rest[..var_end];
+ return Err(ConfigError::UndefinedVariable(undefined_var.to_string()));
+ }
+ }
+ Ok(result)
+}
+
pub fn parse_config(input: &str) -> Result<crate::Config, ConfigError> {
- let config_data: ConfigData = ron::from_str(input)?;
+ let preprocessed = preprocess_variables(input)?;
+ let config_data: ConfigData = ron::from_str(&preprocessed)?;
config_data_to_config(config_data)
}
diff --git a/src/errors.rs b/src/errors.rs
index f698f07..0a43192 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -25,6 +25,9 @@ pub enum ConfigError {
UnknownAction(String),
UnknownBlockCommand(String),
MissingCommandArg { command: String, field: String },
+ InvalidVariableName(String),
+ InvalidDefine(String),
+ UndefinedVariable(String),
}
impl std::fmt::Display for WmError {
@@ -67,6 +70,15 @@ impl std::fmt::Display for ConfigError {
Self::MissingCommandArg { command, field } => {
write!(f, "{} command requires {}", command, field)
}
+ Self::InvalidVariableName(name) => {
+ write!(f, "Invalid variable name '{}': must start with $", name)
+ }
+ Self::InvalidDefine(line) => {
+ write!(f, "Invalid #DEFINE syntax: '{}'. Expected: #DEFINE $var_name = value", line)
+ }
+ Self::UndefinedVariable(var) => {
+ write!(f, "Undefined variable '{}': define it with #DEFINE before use", var)
+ }
}
}
}
diff --git a/templates/config.ron b/templates/config.ron
index 69af9f1..80b676e 100644
--- a/templates/config.ron
+++ b/templates/config.ron
@@ -2,19 +2,31 @@
// OXWM Configuration File
// Edit this file and reload with Mod+Shift+R (no compilation needed!)
+#DEFINE $terminal = "st"
+#DEFINE $color_blue = 0x6dade3
+#DEFINE $color_grey = 0xbbbbbb
+#DEFINE $color_green = 0x9ece6a
+#DEFINE $color_red = 0xf7768e
+#DEFINE $color_cyan = 0x0db9d7
+#DEFINE $color_purple = 0xad8ee6
+#DEFINE $color_lavender = 0xa9b1d6
+#DEFINE $color_bg = 0x1a1b26
+#DEFINE $color_fg = 0xbbbbbb
+#DEFINE $color_light_blue = 0x7aa2f7
+
(
border_width: 2,
- border_focused: 0x6dade3,
- border_unfocused: 0xbbbbbb,
+ border_focused: $color_blue,
+ border_unfocused: $color_grey,
font: "monospace:style=Bold:size=10",
-
+
gaps_enabled: true,
gap_inner_horizontal: 5,
gap_inner_vertical: 5,
gap_outer_horizontal: 5,
gap_outer_vertical: 5,
-
- terminal: "st",
+
+ terminal: $terminal,
modkey: Mod4,
tags: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
@@ -24,7 +36,7 @@
],
keybindings: [
- (modifiers: [Mod4], key: Return, action: Spawn, arg: "st"),
+ (modifiers: [Mod4], key: Return, action: Spawn, arg: $terminal),
(modifiers: [Mod4], key: D, action: Spawn, arg: ["sh", "-c", "dmenu_run -l 10"]),
(modifiers: [Mod4], key: S, action: Spawn, arg: ["sh", "-c", "maim -s | xclip -selection clipboard -t image/png"]),
(modifiers: [Mod4], key: Q, action: KillClient),
@@ -73,15 +85,15 @@
],
status_blocks: [
- (format: "Ram: {used}/{total} GB", command: "Ram", interval_secs: 5, color: 0x7aa2f7, underline: true),
- (format: " │ ", command: "Static", interval_secs: 18446744073709551615, color: 0xa9b1d6, underline: false),
- (format: "Kernel: {}", command: "Shell", command_arg: "uname -r", interval_secs: 18446744073709551615, color: 0xf7768e, underline: true),
- (format: " │ ", command: "Static", interval_secs: 18446744073709551615, color: 0xa9b1d6, underline: false),
- (format: "{}", command: "DateTime", command_arg: "%a, %b %d - %-I:%M %P", interval_secs: 1, color: 0x0db9d7, underline: true),
+ (format: "Ram: {used}/{total} GB", command: "Ram", interval_secs: 5, color: $color_light_blue, underline: true),
+ (format: " │ ", command: "Static", interval_secs: 18446744073709551615, color: $color_lavender, underline: false),
+ (format: "Kernel: {}", command: "Shell", command_arg: "uname -r", interval_secs: 18446744073709551615, color: $color_red, underline: true),
+ (format: " │ ", command: "Static", interval_secs: 18446744073709551615, color: $color_lavender, underline: false),
+ (format: "{}", command: "DateTime", command_arg: "%a, %b %d - %-I:%M %P", interval_secs: 1, color: $color_cyan, underline: true),
],
-
- scheme_normal: (foreground: 0xbbbbbb, background: 0x1a1b26, underline: 0x444444),
- scheme_occupied: (foreground: 0x0db9d7, background: 0x1a1b26, underline: 0x0db9d7),
- scheme_selected: (foreground: 0x0db9d7, background: 0x1a1b26, underline: 0xad8ee6),
+
+ scheme_normal: (foreground: $color_fg, background: $color_bg, underline: 0x444444),
+ scheme_occupied: (foreground: $color_cyan, background: $color_bg, underline: $color_cyan),
+ scheme_selected: (foreground: $color_cyan, background: $color_bg, underline: $color_purple),
)
diff --git a/test-config.ron b/test-config.ron
index ac3303a..1553106 100644
--- a/test-config.ron
+++ b/test-config.ron
@@ -2,19 +2,31 @@
// OXWM Configuration File
// Edit this file and reload with Mod+Shift+R (no compilation needed!)
+#DEFINE $terminal = "alacritty"
+#DEFINE $color_blue = 0x6dade3
+#DEFINE $color_grey = 0xbbbbbb
+#DEFINE $color_green = 0x9ece6a
+#DEFINE $color_red = 0xf7768e
+#DEFINE $color_cyan = 0x0db9d7
+#DEFINE $color_purple = 0xad8ee6
+#DEFINE $color_lavender = 0xa9b1d6
+#DEFINE $color_bg = 0x1a1b26
+#DEFINE $color_fg = 0xbbbbbb
+#DEFINE $color_light_blue = 0x7aa2f7
+
(
border_width: 2,
- border_focused: 0x6dade3,
- border_unfocused: 0xbbbbbb,
+ border_focused: $color_blue,
+ border_unfocused: $color_grey,
font: "JetBrainsMono Nerd Font:style=Bold:size=12",
-
+
gaps_enabled: true,
gap_inner_horizontal: 5,
gap_inner_vertical: 5,
gap_outer_horizontal: 5,
gap_outer_vertical: 5,
-
- terminal: "st",
+
+ terminal: $terminal,
modkey: Mod1,
tags: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
@@ -30,7 +42,7 @@
],
keybindings: [
- (modifiers: [Mod1], key: Return, action: Spawn, arg: "st"),
+ (modifiers: [Mod1], key: Return, action: Spawn, arg: $terminal),
(modifiers: [Mod1], key: D, action: Spawn, arg: ["sh", "-c", "dmenu_run -l 10"]),
(modifiers: [Mod1], key: S, action: Spawn, arg: ["sh", "-c", "maim -s | xclip -selection clipboard -t image/png"]),
(modifiers: [Mod1], key: Q, action: KillClient),
@@ -84,7 +96,7 @@
full: " Bat: {}%",
),
interval_secs: 30,
- color: 0x9ece6a,
+ color: $color_green,
underline: true,
),
@@ -93,7 +105,7 @@
format: " │ ",
command: "Static",
interval_secs: 18446744073709551615,
- color: 0xa9b1d6,
+ color: $color_lavender,
underline: false,
),
@@ -102,7 +114,7 @@
format: " {used}/{total} GB",
command: "Ram",
interval_secs: 5,
- color: 0x7aa2f7,
+ color: $color_light_blue,
underline: true,
),
@@ -111,7 +123,7 @@
format: " │ ",
command: "Static",
interval_secs: 18446744073709551615,
- color: 0xa9b1d6,
+ color: $color_lavender,
underline: false,
),
@@ -121,7 +133,7 @@
command: "Shell",
command_arg: "uname -r",
interval_secs: 18446744073709551615,
- color: 0xf7768e,
+ color: $color_red,
underline: true,
),
@@ -130,7 +142,7 @@
format: " │ ",
command: "Static",
interval_secs: 18446744073709551615,
- color: 0xa9b1d6,
+ color: $color_lavender,
underline: false,
),
@@ -140,13 +152,13 @@
command: "DateTime",
command_arg: "%a, %b %d - %-I:%M %P",
interval_secs: 1,
- color: 0x0db9d7,
+ color: $color_cyan,
underline: true,
),
],
- scheme_normal: (foreground: 0xbbbbbb, background: 0x1a1b26, underline: 0x444444),
- scheme_occupied: (foreground: 0x0db9d7, background: 0x1a1b26, underline: 0x0db9d7),
- scheme_selected: (foreground: 0x0db9d7, background: 0x1a1b26, underline: 0xad8ee6),
+ scheme_normal: (foreground: $color_fg, background: $color_bg, underline: 0x444444),
+ scheme_occupied: (foreground: $color_cyan, background: $color_bg, underline: $color_cyan),
+ scheme_selected: (foreground: $color_cyan, background: $color_bg, underline: $color_purple),
)