Skip to content

Commit

Permalink
implement parsing ps dont mind the main changes thats for testing pur…
Browse files Browse the repository at this point in the history
…poses
  • Loading branch information
nnyyxxxx committed Oct 11, 2024
1 parent d6c25f9 commit a2c719f
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ categories = ["gui"]
edition = "2021"

[dependencies]
gtk = { version = "0.9.2", package = "gtk4", features = ["v4_16"] }
gtk = { version = "0.9.2", package = "gtk4", features = ["v4_16"] }
hyprland-parser = { path = "hyprland-parser" }
6 changes: 6 additions & 0 deletions hyprland-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "hyprland-parser"
version = "0.1.0"
edition = "2021"

[dependencies]
179 changes: 179 additions & 0 deletions hyprland-parser/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
use std::collections::HashMap;

#[derive(Debug, Default)]
pub struct HyprlandConfig {
general: HashMap<String, String>,
decoration: HashMap<String, String>,
animations: HashMap<String, String>,
input: HashMap<String, String>,
gestures: HashMap<String, String>,
group: HashMap<String, String>,
misc: HashMap<String, String>,
binds: HashMap<String, String>,
xwayland: HashMap<String, String>,
opengl: HashMap<String, String>,
render: HashMap<String, String>,
cursor: HashMap<String, String>,
debug: HashMap<String, String>,
blur: HashMap<String, String>,
touchpad: HashMap<String, String>,
touchdevice: HashMap<String, String>,
tablet: HashMap<String, String>,
groupbar: HashMap<String, String>,
exec: Vec<String>,
exec_once: Vec<String>,
monitor: Vec<String>,
windowrule: Vec<String>,
windowrulev2: Vec<String>,
bind: Vec<String>,
bindm: Vec<String>,
}

impl HyprlandConfig {
pub fn new() -> Self {
Self::default()
}

pub fn parse(&mut self, config_str: &str) {
let mut section_stack = Vec::new();

for line in config_str.lines() {
let trimmed = line.trim();
if trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}

if trimmed.ends_with('{') {
let section = trimmed.trim_end_matches('{').trim().to_string();
section_stack.push(section);
continue;
}

if trimmed == "}" {
section_stack.pop();
continue;
}

if trimmed.starts_with("exec = ") {
self.exec.push(trimmed[6..].to_string());
} else if trimmed.starts_with("exec-once = ") {
self.exec_once.push(trimmed[11..].to_string());
} else if trimmed.starts_with("monitor = ") {
self.monitor.push(trimmed[9..].to_string());
} else if trimmed.starts_with("windowrule = ") {
self.windowrule.push(trimmed[12..].to_string());
} else if trimmed.starts_with("windowrulev2 = ") {
self.windowrulev2.push(trimmed[14..].to_string());
} else if trimmed.starts_with("bind = ") {
self.bind.push(trimmed[6..].to_string());
} else if trimmed.starts_with("bindm = ") {
self.bindm.push(trimmed[7..].to_string());
} else {
let parts: Vec<&str> = trimmed.splitn(2, '=').collect();
if parts.len() == 2 {
let key = parts[0].trim();
let value = parts[1].trim();
let current_section = section_stack.join(":");
match current_section.as_str() {
"general" => self.general.insert(key.to_string(), value.to_string()),
"decoration" => self.decoration.insert(key.to_string(), value.to_string()),
"animations" => self.animations.insert(key.to_string(), value.to_string()),
"input" => self.input.insert(key.to_string(), value.to_string()),
"gestures" => self.gestures.insert(key.to_string(), value.to_string()),
"group" => self.group.insert(key.to_string(), value.to_string()),
"misc" => self.misc.insert(key.to_string(), value.to_string()),
"binds" => self.binds.insert(key.to_string(), value.to_string()),
"xwayland" => self.xwayland.insert(key.to_string(), value.to_string()),
"opengl" => self.opengl.insert(key.to_string(), value.to_string()),
"render" => self.render.insert(key.to_string(), value.to_string()),
"cursor" => self.cursor.insert(key.to_string(), value.to_string()),
"debug" => self.debug.insert(key.to_string(), value.to_string()),
"decoration:blur" => self.blur.insert(key.to_string(), value.to_string()),
"input:touchpad" => self.touchpad.insert(key.to_string(), value.to_string()),
"input:touchdevice" => self.touchdevice.insert(key.to_string(), value.to_string()),
"input:tablet" => self.tablet.insert(key.to_string(), value.to_string()),
"group:groupbar" => self.groupbar.insert(key.to_string(), value.to_string()),
_ => None,
};
}
}
}
}

pub fn to_string(&self) -> String {
let mut config = String::new();

for (key, value) in &self.general {
config.push_str(&format!("{} = {}\n", key, value));
}

let sections = [
("decoration", &self.decoration),
("animations", &self.animations),
("input", &self.input),
("gestures", &self.gestures),
("group", &self.group),
("misc", &self.misc),
("binds", &self.binds),
("xwayland", &self.xwayland),
("opengl", &self.opengl),
("render", &self.render),
("cursor", &self.cursor),
("debug", &self.debug),
];

for (section, map) in sections {
if !map.is_empty() {
config.push_str(&format!("\n{} {{\n", section));
for (key, value) in map {
config.push_str(&format!(" {} = {}\n", key, value));
}
config.push_str("}\n");
}
}

if !self.blur.is_empty() {
config.push_str("\ndecoration:blur {\n");
for (key, value) in &self.blur {
config.push_str(&format!(" {} = {}\n", key, value));
}
config.push_str("}\n");
}

let lists = [
("exec", &self.exec),
("exec-once", &self.exec_once),
("monitor", &self.monitor),
("windowrule", &self.windowrule),
("windowrulev2", &self.windowrulev2),
("bind", &self.bind),
("bindm", &self.bindm),
];

for (prefix, list) in lists {
for item in list {
config.push_str(&format!("{} = {}\n", prefix, item));
}
}

config
}

pub fn insert_general(&mut self, key: String, value: String) {
self.general.insert(key, value);
}

pub fn add_exec(&mut self, command: String) {
self.exec.push(command);
}

pub fn add_bind(&mut self, binding: String) {
self.bind.push(binding);
}
}

pub fn parse_config(config_str: &str) -> HyprlandConfig {
let mut config = HyprlandConfig::new();
config.parse(config_str);
config
}
22 changes: 22 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use hyprland_parser::parse_config;
use std::fs;
use std::path::PathBuf;

fn main() {
let home = std::env::var("HOME").unwrap();
let config_path = PathBuf::from(home).join(".config/hypr/hyprland.conf");

let config_str = fs::read_to_string(&config_path).unwrap();

let mut parsed_config = parse_config(&config_str);

parsed_config.insert_general("new_option".to_string(), "value".to_string());
parsed_config.add_exec("some_command --with-args".to_string());
parsed_config.add_bind("$mod, T, exec, kitty".to_string());

let updated_config_str = parsed_config.to_string();

fs::write(&config_path, updated_config_str).unwrap();

println!("Updated hyprland.conf with new configurations.");
}

0 comments on commit a2c719f

Please sign in to comment.