separate config module

This commit is contained in:
2024-12-30 03:30:08 +00:00
parent b8c38da85b
commit bec2bdc8f9
2 changed files with 94 additions and 88 deletions

91
src/config.rs Normal file
View File

@@ -0,0 +1,91 @@
use std::collections::HashMap;
use std::fs;
use kdl::KdlDocument;
/// Configuration for swayout.
pub struct Config {
/// Monitor name is independent of output name. It can be anything.
pub monitors: HashMap<String, Monitor>,
/// Definition of layouts: a map of the layout name to the outputs.
/// The outputs is a map of the monitor name (in `monitors`) to the configuration
/// of that monitor for this layout.
/// Available outputs that do not match a monitor in the map are disabled.
pub layouts: HashMap<String, HashMap<String, OutputConfig>>,
}
/// Defines a monitor by make, model, and serial.
pub struct Monitor {
pub make: String,
pub model: String,
pub serial: String,
}
/// Configuration for an enabled output.
pub struct OutputConfig {
/// mode. See man 5 sway-output
pub mode: String,
/// scale. See man 5 sway-output
pub scale: String,
/// x value for position. See man 5 sway-output
pub x: u16,
/// y value for position. See man 5 sway-output
pub y: u16,
/// transform. See man 5 sway-output
pub transform: String,
}
/// Get a `Config` from ~/.config/swayout/config.kdl.
/// (It really uses XDG config dirs.)
pub fn get_config() -> Config {
let xdg_dirs = xdg::BaseDirectories::with_prefix("swayout").unwrap();
if let Some(path) = xdg_dirs.find_config_file("config.kdl") {
let kdl = fs::read_to_string(path).expect("error reading file");
parse_config(kdl)
} else {
// no config files, use an empty rules
Config {
monitors: HashMap::new(),
layouts: HashMap::new(),
}
}
}
fn parse_config(kdl:String) -> Config {
let doc:KdlDocument = kdl.parse().expect("failed to parse config KDL");
let monitors:HashMap<String,Monitor> = doc.nodes().iter()
.filter(|node| node.name().value() == "monitor")
.map(|monitor_node| {
let name = String::from(monitor_node[0].as_string().unwrap());
let monitor = Monitor {
make : String::from(monitor_node["make"].as_string().unwrap()),
model : String::from(monitor_node["model"].as_string().unwrap()),
serial : String::from(monitor_node["serial"].as_string().unwrap()),
};
(name, monitor)
})
.collect();
let layouts:HashMap<String,HashMap<String,OutputConfig>> = doc.nodes().iter()
.filter(|node| node.name().value() == "layout")
.map(|layout_node| {
let layout_name = String::from(layout_node[0].as_string().unwrap());
let monitor_name_to_output_config:HashMap<String,OutputConfig> = layout_node
.children().unwrap().nodes().iter()
.map(|output_node| {
let output = String::from(output_node[0].as_string().unwrap());
let output_config = OutputConfig {
mode : String::from(output_node["mode"].as_string().unwrap()),
scale : String::from(output_node["scale"].as_string().unwrap()),
transform : String::from(output_node["transform"].as_string().unwrap()),
x : output_node["x"].as_i64().unwrap() as u16,
y : output_node["y"].as_i64().unwrap() as u16,
};
(output, output_config)
})
.collect();
(layout_name,monitor_name_to_output_config)
})
.collect();
Config { monitors, layouts }
}