diff --git a/.gitignore b/.gitignore index ea8c4bf..07c12f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +result diff --git a/Cargo.lock b/Cargo.lock index 2dd16f2..31c937e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,18 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "argh" -version = "0.1.12" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219" +checksum = "211818e820cda9ca6f167a64a5c808837366a6dfd807157c64c1304c486cd033" dependencies = [ "argh_derive", "argh_shared", @@ -20,67 +20,67 @@ dependencies = [ [[package]] name = "argh_derive" -version = "0.1.12" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a" +checksum = "c442a9d18cef5dde467405d27d461d080d68972d6d0dfd0408265b6749ec427d" dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "argh_shared" -version = "0.1.12" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531" +checksum = "e5ade012bac4db278517a0132c8c10c6427025868dca16c801087c28d5a411f1" dependencies = [ "serde", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "mini-internal" -version = "0.1.34" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb752642ceeaad440a788ea0ee23c0317117068f49dc1f25fd23b26146a225d" +checksum = "34dea53b00d87f21b1535cbef93765c75f159dbbfeef16152f0b6b3bf28f3bb6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "miniserde" -version = "0.1.34" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c007c51ce98f5f76964762e92fe98967f9fa65943415fd0d0dc6b6bf6bd3da0d" +checksum = "e8f82621301d3b99a1542736de96e5df69865b235987d6470b28c7aa670cfeb1" dependencies = [ "itoa", "mini-internal", - "ryu", + "zmij", ] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -95,36 +95,51 @@ dependencies = [ ] [[package]] -name = "ryu" -version = "1.0.15" +name = "serde" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] [[package]] -name = "serde" -version = "1.0.188" +name = "serde_core" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.4", ] [[package]] name = "syn" -version = "2.0.29" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", @@ -133,6 +148,12 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/flake.lock b/flake.lock index 57a483e..3793eeb 100644 --- a/flake.lock +++ b/flake.lock @@ -1,15 +1,37 @@ { "nodes": { + "fenix": { + "inputs": { + "nixpkgs": [ + "naersk-package", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1752475459, + "narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=", + "owner": "nix-community", + "repo": "fenix", + "rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { - "lastModified": 1692799911, - "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -20,16 +42,17 @@ }, "naersk-package": { "inputs": { + "fenix": "fenix", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1692351612, - "narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=", + "lastModified": 1782220280, + "narHash": "sha256-thLTFbp9D5Qknmh8q/v4FRpLGphUSijT3E86cbLYTXo=", "owner": "nix-community", "repo": "naersk", - "rev": "78789c30d64dea2396c9da516bbcc8db3a475207", + "rev": "9aa07bb0256d300219b30622d2454e85f7f3667e", "type": "github" }, "original": { @@ -40,11 +63,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1693158576, - "narHash": "sha256-aRTTXkYvhXosGx535iAFUaoFboUrZSYb1Ooih/auGp0=", + "lastModified": 1788179007, + "narHash": "sha256-hn1oU2rue2SYK8dAr8+WNZWtbsz1S2W5mnHlSEuh3bo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a999c1cc0c9eb2095729d5aa03e0d8f7ed256780", + "rev": "34ab99075ac4f7e40cf037eef32cb1c360bb85e9", "type": "github" }, "original": { @@ -61,6 +84,23 @@ "nixpkgs": "nixpkgs" } }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1752428706, + "narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "591e3b7624be97e4443ea7b5542c191311aa141d", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, diff --git a/src/main.rs b/src/main.rs index 1c52cda..fc19dbd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,20 +21,60 @@ struct Client { address: String, } -fn launch_command(args: &Args) -> std::io::Result { - Command::new("hyprctl") - .arg("keyword") - .arg("exec") - .arg(&args.launch) - .spawn() +enum ConfigType { + Hyprlang, + Lua, } -fn focus_window(address: &str) -> std::io::Result { - Command::new("hyprctl") - .arg("dispatch") - .arg("focuswindow") - .arg(format!("address:{address}")) - .spawn() +fn config_type() -> ConfigType { + let output = Command::new("hyprctl") + .arg("eval") + .arg("print('lua')") + .output(); + + if let Ok(output) = output { + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + let text = format!("{stdout}{stderr}"); + if text.contains("eval is only supported with the lua config manager") { + return ConfigType::Hyprlang; + } + if output.status.success() { + return ConfigType::Lua; + } + } + + ConfigType::Hyprlang +} + +fn lua_string(s: &str) -> String { + format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")) +} + +fn launch_command(args: &Args, config_type: &ConfigType) -> std::io::Result { + let mut command = Command::new("hyprctl"); + match config_type { + ConfigType::Hyprlang => command.arg("keyword").arg("exec").arg(&args.launch), + ConfigType::Lua => command + .arg("dispatch") + .arg(format!("hl.dsp.exec_cmd({})", lua_string(&args.launch))), + } + .spawn() +} + +fn focus_window(address: &str, config_type: &ConfigType) -> std::io::Result { + let mut command = Command::new("hyprctl"); + match config_type { + ConfigType::Hyprlang => command + .arg("dispatch") + .arg("focuswindow") + .arg(format!("address:{address}")), + ConfigType::Lua => command.arg("dispatch").arg(format!( + "hl.dsp.focus({{ window = {} }})", + lua_string(&format!("address:{address}")) + )), + } + .spawn() } fn get_current_matching_window(class: &str) -> Result { @@ -55,6 +95,7 @@ fn get_current_matching_window(class: &str) -> Result { fn main() -> Result<()> { // Get arguments let args: Args = argh::from_env(); + let config_type = config_type(); // Launch hyprctl let json = Command::new("hyprctl").arg("clients").arg("-j").output(); @@ -77,20 +118,20 @@ fn main() -> Result<()> { // Focus next window based on first if let Some(index) = candidates.iter().position(|client| client.address == address) { if let Some(next_client) = candidates.iter().cycle().skip(index + 1).next() { - focus_window(&next_client.address)?; + focus_window(&next_client.address, &config_type)?; } } } else { // Focus first window, otherwise launch command match candidates.first() { - Some(Client { address, .. }) => focus_window(address)?, - _ => launch_command(&args)?, + Some(Client { address, .. }) => focus_window(address, &config_type)?, + _ => launch_command(&args, &config_type)?, }; } } // If hyprctl fails, just launch it _ => { - launch_command(&args)?; + launch_command(&args, &config_type)?; } }