#[cfg(feature = "mutation")]
use hyprlang::{Config, ConfigValue};
#[cfg(feature = "mutation")]
fn run_example() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Hyprlang Mutation & Serialization Example ===\n");
let mut config = Config::new();
config.parse(
r#"
# Configuration for my app
$GAPS = 10
$SCALE = 2
$FILE_MANAGER = nautilus
general {
border_size = 3
gaps_in = $GAPS
gaps_out = {{GAPS * 2}}
active_opacity = 0.9
}
decoration {
rounding = 10
shadow {
enabled = true
range = 20
}
}
"#,
)?;
println!("📖 Initial configuration loaded\n");
println!("🔧 Mutating configuration values...\n");
config.set_int("general:border_size", 5);
println!("✓ Changed border_size: {} -> 5", 3);
config.set_float("general:active_opacity", 1.0);
println!("✓ Changed active_opacity: {} -> 1.0", 0.9);
config.set("decoration:blur", ConfigValue::Int(1));
println!("✓ Added new value: decoration:blur = 1");
let old_value = config.remove("decoration:rounding")?;
println!("✓ Removed decoration:rounding (was: {})", old_value);
println!("\n📝 Mutating variables...\n");
config.set_variable("GAPS".to_string(), "15".to_string());
println!("✓ Changed $GAPS: 10 -> 15");
if let Some(mut file_manager) = config.get_variable_mut("FILE_MANAGER") {
let old_value = file_manager.get().to_string();
file_manager.set("thunar")?;
println!(
"✓ Changed ${}: {} -> thunar",
file_manager.name(),
old_value
);
}
config.set_variable("COLOR_THEME".to_string(), "dark".to_string());
println!("✓ Added new variable: $COLOR_THEME = dark");
if let Some(old_value) = config.remove_variable("SCALE") {
println!("✓ Removed $SCALE (was: {})", old_value);
}
println!("\n⚡ Mutating handler calls...\n");
config.register_handler_fn("bind", |_ctx| Ok(()));
config.register_handler_fn("exec-once", |_ctx| Ok(()));
config.add_handler_call("bind", "SUPER, A, exec, terminal".to_string())?;
config.add_handler_call("bind", "SUPER, B, exec, browser".to_string())?;
config.add_handler_call("exec-once", "waybar".to_string())?;
println!("✓ Added 2 bind handlers");
println!("✓ Added 1 exec-once handler");
let removed = config.remove_handler_call("bind", 0)?;
println!("✓ Removed bind[0]: {}", removed);
println!("\n✅ Verifying mutations...\n");
assert_eq!(config.get_int("general:border_size")?, 5);
println!(" border_size = {}", config.get_int("general:border_size")?);
assert_eq!(config.get_float("general:active_opacity")?, 1.0);
println!(
" active_opacity = {}",
config.get_float("general:active_opacity")?
);
assert_eq!(config.get_variable("GAPS"), Some("15"));
println!(" $GAPS = {}", config.get_variable("GAPS").unwrap());
assert_eq!(config.get_variable("FILE_MANAGER"), Some("thunar"));
println!(
" $FILE_MANAGER = {}",
config.get_variable("FILE_MANAGER").unwrap()
);
assert!(config.get_handler_calls("bind").is_some());
println!(
" bind handlers: {:?}",
config.get_handler_calls("bind").unwrap()
);
println!("\n💾 Serializing configuration...\n");
let serialized = config.serialize();
println!("Serialized config (synthetic format, first 400 chars):");
println!("{}", &serialized[..serialized.len().min(400)]);
if serialized.len() > 400 {
println!("... (truncated)\n");
} else {
println!();
}
let temp_file = "/tmp/hyprlang_mutation_example.conf";
config.save_as(temp_file)?;
println!("✓ Saved to: {}", temp_file);
let mut config2 = Config::new();
config2.parse_file(std::path::Path::new(temp_file))?;
assert_eq!(config2.get_int("general:border_size")?, 5);
assert_eq!(config2.get_variable("GAPS"), Some("15"));
println!("✓ Verified round-trip: parse -> mutate -> save -> parse");
std::fs::remove_file(temp_file).ok();
println!("\n🎉 All mutations and serialization working correctly!");
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(feature = "mutation")]
{
run_example()
}
#[cfg(not(feature = "mutation"))]
{
eprintln!("❌ This example requires the 'mutation' feature to be enabled.");
eprintln!("\nPlease run with:");
eprintln!(" cargo run --example mutation_example --features mutation");
std::process::exit(1);
}
}