might be finished

This commit is contained in:
nyx
2024-10-11 18:29:18 -04:00
parent 27a5824998
commit 8cbf3f0ba4
2 changed files with 71 additions and 42 deletions
+69 -39
View File
@@ -1,10 +1,9 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct HyprlandConfig {
content: Vec<String>,
sections: HashMap<String, usize>,
added_entries: HashMap<String, HashSet<String>>,
sections: HashMap<String, (usize, usize)>,
}
impl HyprlandConfig {
@@ -13,55 +12,86 @@ impl HyprlandConfig {
}
pub fn parse(&mut self, config_str: &str) {
let mut current_section = String::new();
let mut section_start = 0;
let mut section_stack = Vec::new();
for (i, line) in config_str.lines().enumerate() {
let trimmed = line.trim();
if trimmed.ends_with('{') {
current_section = trimmed.trim_end_matches('{').trim().to_string();
section_start = i;
} else if trimmed == "}" {
if !current_section.is_empty() {
self.sections.insert(current_section.clone(), section_start);
current_section.clear();
}
let section_name = trimmed.trim_end_matches('{').trim().to_string();
section_stack.push((section_name, i));
} else if trimmed == "}" && !section_stack.is_empty() {
let (name, start) = section_stack.pop().unwrap();
let full_name = section_stack
.iter()
.map(|(n, _)| n.as_str())
.chain(std::iter::once(name.as_str()))
.collect::<Vec<_>>()
.join(".");
self.sections.insert(full_name, (start, i));
}
self.content.push(line.to_string());
}
}
pub fn to_string(&self) -> String {
let mut result = self.content.join("\n");
for (category, entries) in &self.added_entries {
for entry in entries {
if !self.entry_exists(category, entry) {
result.push_str(&format!("\n{}", entry));
}
}
}
result
}
fn entry_exists(&self, category: &str, entry: &str) -> bool {
self.content.iter().any(|line| line.trim() == entry)
self.content.join("\n")
}
pub fn add_entry(&mut self, category: &str, entry: &str) {
if !self.entry_exists(category, entry) {
if let Some(&section_start) = self.sections.get(category) {
let insert_position = self.content[section_start..]
.iter()
.position(|line| line.trim() == "}")
.map(|pos| section_start + pos)
.unwrap_or(self.content.len());
self.content
.insert(insert_position, format!(" {}", entry));
} else {
self.added_entries
.entry(category.to_string())
.or_insert_with(HashSet::new)
.insert(entry.to_string());
let parts: Vec<&str> = category.split('.').collect();
let mut current_section = String::new();
let mut depth = 0;
for (i, part) in parts.iter().enumerate() {
if i > 0 {
current_section.push('.');
}
current_section.push_str(part);
if let Some(&(start, end)) = self.sections.get(&current_section) {
if i == parts.len() - 1 {
let key = entry.split('=').next().unwrap().trim();
let existing_line = self.content[start..=end]
.iter()
.position(|line| line.trim().starts_with(key))
.map(|pos| start + pos);
if let Some(line_num) = existing_line {
self.content[line_num] = format!("{}{}", " ".repeat(depth + 1), entry);
} else {
self.content
.insert(end, format!("{}{}", " ".repeat(depth + 1), entry));
}
return;
}
} else {
let new_section = format!("{}{} {{", " ".repeat(depth), part);
let insert_pos = if let Some(&(_, end)) = self.sections.get(&parts[..i].join(".")) {
end + 1
} else {
self.content.len()
};
self.content.insert(insert_pos, new_section);
self.content.insert(
insert_pos + 1,
format!("{}{}", " ".repeat(depth + 1), entry),
);
self.content
.insert(insert_pos + 2, format!("{}}}", " ".repeat(depth)));
for (section, &mut (ref mut start, ref mut end)) in self.sections.iter_mut() {
if *start >= insert_pos {
*start += 3;
*end += 3;
} else if *end >= insert_pos {
*end += 3;
}
}
self.sections
.insert(current_section.clone(), (insert_pos, insert_pos + 2));
return;
}
depth += 1;
}
}
}
+2 -3
View File
@@ -10,10 +10,9 @@ fn main() {
let mut parsed_config = parse_config(&config_str);
parsed_config.add_entry("general", "new_option = value");
parsed_config.add_entry("decoration", "rounding = 10");
parsed_config.add_entry("decoration", "blur" "enabled = true");
parsed_config.add_entry("decoration", "blur" "size = 10");
parsed_config.add_entry("decoration.blur", "enabled = true");
parsed_config.add_entry("decoration.blur", "size = 10");
let updated_config_str = parsed_config.to_string();