add support for sourced files (#57)

* add functionality needed for sourced files to work

* fix entry handling

* run fmt

* allow dead code

* fix nested entries

* fix nested option filling
This commit is contained in:
nyx
2024-11-01 14:05:55 -04:00
committed by GitHub
parent 204f1097f3
commit 4f3dd91367
2 changed files with 171 additions and 14 deletions

View File

@@ -2834,17 +2834,113 @@ impl ConfigWidget {
}
}
fn extract_value(&self, config: &HyprlandConfig, _category: &str, name: &str) -> String {
let config_str = config.to_string();
for line in config_str.lines() {
if line.trim().starts_with(&format!("{} = ", name)) {
return line
.split('=')
.nth(1)
.map(|s| s.trim().to_string())
.unwrap_or_default();
fn extract_value(&self, config: &HyprlandConfig, category: &str, name: &str) -> String {
let mut value = String::new();
let parts: Vec<&str> = name.split(':').collect();
if parts.len() > 1 {
if let Some(&(parent_start, parent_end)) = config.sections.get(category) {
if parent_start < config.content.len() && parent_end < config.content.len() {
let subsection = format!("{} {{", parts[0]);
let mut in_subsection = false;
for line in &config.content[parent_start..=parent_end] {
let trimmed = line.trim();
if trimmed == subsection {
in_subsection = true;
continue;
}
if in_subsection {
if trimmed == "}" {
break;
}
if trimmed.starts_with(parts[1])
&& trimmed[parts[1].len()..].trim_start().starts_with('=')
{
if let Some(val) = trimmed.split('=').nth(1) {
value = val.trim().to_string();
break;
}
}
}
}
}
}
} else {
if let Some(&(start, end)) = config.sections.get(category) {
if start < config.content.len() && end < config.content.len() {
for line in &config.content[start..=end] {
let trimmed = line.trim();
if trimmed.starts_with(name)
&& trimmed[name.len()..].trim_start().starts_with('=')
{
if let Some(val) = line.split('=').nth(1) {
value = val.trim().to_string();
break;
}
}
}
}
}
}
String::new()
if value.is_empty() {
for idx in 0..config.sourced_content.len() {
let section_key = format!("{}_{}", category, idx);
if let Some(&(start, end)) = config.sourced_sections.get(&section_key) {
let sourced = &config.sourced_content[idx];
if start < sourced.len() && end < sourced.len() {
if parts.len() > 1 {
let subsection = format!("{} {{", parts[0]);
let mut in_subsection = false;
for line in &sourced[start..=end] {
let trimmed = line.trim();
if trimmed == subsection {
in_subsection = true;
continue;
}
if in_subsection {
if trimmed == "}" {
break;
}
if trimmed.starts_with(parts[1])
&& trimmed[parts[1].len()..].trim_start().starts_with('=')
{
if let Some(val) = trimmed.split('=').nth(1) {
value = val.trim().to_string();
break;
}
}
}
}
} else {
for line in &sourced[start..=end] {
let trimmed = line.trim();
if trimmed.starts_with(name)
&& trimmed[name.len()..].trim_start().starts_with('=')
{
if let Some(val) = line.split('=').nth(1) {
value = val.trim().to_string();
break;
}
}
}
}
}
}
if !value.is_empty() {
break;
}
}
}
value
}
}

View File

@@ -120,6 +120,26 @@ fn save_config_file(gui: Rc<RefCell<gui::ConfigGUI>>) {
);
return;
}
for sourced_path in &parsed_config.sourced_paths {
let sourced_backup = Path::new(sourced_path).with_file_name(format!(
"{}{}",
Path::new(sourced_path)
.file_name()
.unwrap()
.to_str()
.unwrap(),
BACKUP_SUFFIX
));
if let Err(e) = fs::copy(sourced_path, &sourced_backup) {
gui_ref.custom_error_popup(
"Backup failed",
&format!("Failed to create backup for sourced file: {}", e),
true,
);
return;
}
}
}
gui_ref.apply_changes(&mut parsed_config);
@@ -127,7 +147,7 @@ fn save_config_file(gui: Rc<RefCell<gui::ConfigGUI>>) {
let updated_config_str = parsed_config.to_string();
match fs::write(&path, updated_config_str) {
Ok(_) => println!("Configuration saved to: ~/{}", CONFIG_PATH),
Ok(_) => println!("Configuration saved successfully"),
Err(e) => {
gui_ref.custom_error_popup(
"Saving failed",
@@ -151,13 +171,54 @@ fn undo_changes(gui: Rc<RefCell<gui::ConfigGUI>>) {
));
if backup_path.exists() {
let config_str = match fs::read_to_string(&path) {
Ok(s) => s,
Err(e) => {
gui_ref.custom_error_popup(
"Reading failed",
&format!("Failed to read configuration: {}", e),
true,
);
return;
}
};
let parsed_config = parse_config(&config_str);
for sourced_path in &parsed_config.sourced_paths {
let sourced_backup = Path::new(sourced_path).with_file_name(format!(
"{}{}",
Path::new(sourced_path)
.file_name()
.unwrap()
.to_str()
.unwrap(),
BACKUP_SUFFIX
));
if sourced_backup.exists() {
if let Err(e) = fs::copy(&sourced_backup, sourced_path) {
gui_ref.custom_error_popup(
"Undo Failed",
&format!("Failed to restore sourced file from backup: {}", e),
true,
);
return;
}
if let Err(e) = fs::remove_file(&sourced_backup) {
gui_ref.custom_error_popup(
"Backup Deletion Failed",
&format!("Failed to delete sourced backup file: {}", e),
true,
);
}
}
}
match fs::copy(&backup_path, &path) {
Ok(_) => {
println!("Configuration restored from backup");
if let Ok(config_str) = fs::read_to_string(&path) {
let parsed_config = parse_config(&config_str);
gui_ref.load_config(&parsed_config);
gui_ref.get_changes().borrow_mut().clear();
if let Err(e) = fs::remove_file(&backup_path) {
@@ -169,7 +230,7 @@ fn undo_changes(gui: Rc<RefCell<gui::ConfigGUI>>) {
} else {
gui_ref.custom_info_popup(
"Undo Successful",
"Configuration restored from backup and backup file deleted.",
"Configuration restored from backup and backup files deleted.",
true,
);
}