diff --git a/Cargo.lock b/Cargo.lock index cb136817..69ad8d0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1117,9 +1117,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" diff --git a/komorebi-core/src/config_generation.rs b/komorebi-core/src/config_generation.rs index 9136b46d..f2c6fe8e 100644 --- a/komorebi-core/src/config_generation.rs +++ b/komorebi-core/src/config_generation.rs @@ -57,12 +57,22 @@ pub struct IdWithIdentifier { id: String, } +#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +pub struct IdWithIdentifierAndComment { + kind: ApplicationIdentifier, + id: String, + #[serde(skip_serializing_if = "Option::is_none")] + comment: Option, +} + #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct ApplicationConfiguration { name: String, identifier: IdWithIdentifier, + #[serde(skip_serializing_if = "Option::is_none")] options: Option>, - float_identifiers: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + float_identifiers: Option>, } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] @@ -73,7 +83,13 @@ impl ApplicationConfigurationGenerator { Ok(serde_yaml::from_str(content)?) } - pub fn generate(content: &str) -> Result> { + pub fn format(content: &str) -> Result { + let mut cfgen = Self::load(content)?; + cfgen.sort_by(|a, b| a.name.cmp(&b.name)); + Ok(serde_yaml::to_string(&cfgen)?) + } + + pub fn generate_ahk(content: &str) -> Result> { let mut cfgen = Self::load(content)?; cfgen.sort_by(|a, b| a.name.cmp(&b.name)); @@ -93,6 +109,7 @@ impl ApplicationConfigurationGenerator { if let ApplicationOptions::TrayAndMultiWindow = opt { lines.push(String::from("; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line")); } + lines.push(opt.cfgen(&app.identifier.kind, &app.identifier.id)); } } @@ -107,10 +124,16 @@ impl ApplicationConfigurationGenerator { // Don't want to send duped signals especially as configs get larger if !float_rules.contains(&float_rule) { float_rules.push(float_rule.clone()); + + if let Some(comment) = float.comment { + lines.push(format!("; {}", comment)); + }; + lines.push(float_rule); } } } + lines.push(String::from("")); } diff --git a/komorebic.lib.sample.ahk b/komorebic.lib.sample.ahk index 2f3a437c..86b58948 100644 --- a/komorebic.lib.sample.ahk +++ b/komorebic.lib.sample.ahk @@ -304,8 +304,12 @@ AhkLibrary() { Run, komorebic.exe ahk-library, , Hide } -ApplicationSpecificConfiguration(path) { - Run, komorebic.exe application-specific-configuration %path%, , Hide +AhkAppSpecificConfiguration(path) { + Run, komorebic.exe ahk-app-specific-configuration %path%, , Hide +} + +FormatAppSpecificConfiguration(path) { + Run, komorebic.exe format-app-specific-configuration %path%, , Hide } NotificationSchema() { diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 50b29fd7..893e0aa3 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -422,10 +422,22 @@ struct Unsubscribe { named_pipe: String, } -#[derive(Parser, AhkFunction)] -pub struct ApplicationSpecificConfiguration { - /// YAML file from which the application-specific configurations should be loaded - path: String, +macro_rules! gen_application_specific_configuration_subcommand_args { + // SubCommand Pattern + ( $( $name:ident ),+ $(,)? ) => { + $( + #[derive(clap::Parser, derive_ahk::AhkFunction)] + pub struct $name { + /// YAML file from which the application-specific configurations should be loaded + path: String, + } + )+ + }; +} + +gen_application_specific_configuration_subcommand_args! { + AhkAppSpecificConfiguration, + FormatAppSpecificConfiguration, } #[derive(Parser)] @@ -649,10 +661,14 @@ enum SubCommand { ToggleMouseFollowsFocus, /// Generate a library of AutoHotKey helper functions AhkLibrary, - /// Generate a collection of common application configurations to use in komorebi.ahk + /// Generate common app-specific configurations and fixes to use in komorebi.ahk #[clap(arg_required_else_help = true)] - #[clap(alias = "app-specific-configuration")] - ApplicationSpecificConfiguration(ApplicationSpecificConfiguration), + #[clap(alias = "ahk-asc")] + AhkAppSpecificConfiguration(AhkAppSpecificConfiguration), + /// Format a YAML file for use with the 'ahk-app-specific-configuration' command + #[clap(arg_required_else_help = true)] + #[clap(alias = "fmt-asc")] + FormatAppSpecificConfiguration(FormatAppSpecificConfiguration), /// Generate a JSON Schema of subscription notifications NotificationSchema, } @@ -1147,9 +1163,9 @@ fn main() -> Result<()> { SubCommand::WindowHidingBehaviour(arg) => { send_message(&*SocketMessage::WindowHidingBehaviour(arg.hiding_behaviour).as_bytes()?)?; } - SubCommand::ApplicationSpecificConfiguration(arg) => { + SubCommand::AhkAppSpecificConfiguration(arg) => { let content = fs::read_to_string(resolve_windows_path(&arg.path)?)?; - let lines = ApplicationConfigurationGenerator::generate(&content)?; + let lines = ApplicationConfigurationGenerator::generate_ahk(&content)?; let mut generated_config = HOME_DIR.clone(); generated_config.push("komorebi.generated.ahk"); @@ -1174,6 +1190,21 @@ fn main() -> Result<()> { println!("\n#Include %A_ScriptDir%\\komorebi.generated.ahk"); } + SubCommand::FormatAppSpecificConfiguration(arg) => { + let file_path = resolve_windows_path(&arg.path)?; + let content = fs::read_to_string(&file_path)?; + let formatted_content = ApplicationConfigurationGenerator::format(&content)?; + + let mut file = OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(file_path)?; + + file.write_all(formatted_content.as_bytes())?; + + println!("File successfully formatted for PRs to https://github.com/LGUG2Z/komorebi-application-specific-configuration"); + } SubCommand::NotificationSchema => { let home = HOME_DIR.clone(); let mut socket = home;