From cec11f39cb02cf3350215734f8ca09f49008e687 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sun, 27 Jun 2021 15:46:09 +0200 Subject: [PATCH] feat(core): extend env-path module to Windows --- Cargo.lock | 11 +++++ espanso/Cargo.toml | 2 + espanso/src/cli/launcher/mod.rs | 7 ++- espanso/src/path/linux.rs | 35 ++++++++++++++ espanso/src/path/mod.rs | 19 +++++++- espanso/src/path/win.rs | 81 +++++++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 espanso/src/path/linux.rs create mode 100644 espanso/src/path/win.rs diff --git a/Cargo.lock b/Cargo.lock index 8963d5b..c49b12d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,7 +451,9 @@ dependencies = [ "simplelog", "tempdir", "thiserror", + "widestring", "winapi 0.3.9", + "winreg", ] [[package]] @@ -2011,6 +2013,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winreg" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16cdb3898397cf7f624c294948669beafaeebc5577d5ec53d0afb76633593597" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "winres" version = "0.1.11" diff --git a/espanso/Cargo.toml b/espanso/Cargo.toml index daf7be1..0f570a2 100644 --- a/espanso/Cargo.toml +++ b/espanso/Cargo.toml @@ -59,6 +59,8 @@ notify = "4.0.17" [target.'cfg(windows)'.dependencies] named_pipe = "0.4.1" winapi = { version = "0.3.9", features = ["wincon"] } +winreg = "0.9.0" +widestring = "0.4.3" [target.'cfg(target_os="macos")'.dependencies] espanso-mac-utils = { path = "../espanso-mac-utils" } \ No newline at end of file diff --git a/espanso/src/cli/launcher/mod.rs b/espanso/src/cli/launcher/mod.rs index f034604..132f55f 100644 --- a/espanso/src/cli/launcher/mod.rs +++ b/espanso/src/cli/launcher/mod.rs @@ -76,8 +76,11 @@ fn launcher_main(args: CliModuleArgs) -> i32 { if cfg!(target_os = "macos") { !crate::path::is_espanso_in_path() } else { - // TODO: enable "Add to PATH" page only when NOT in portable mode - !crate::path::is_espanso_in_path() + if paths.is_portable_mode { + false + } else { + !crate::path::is_espanso_in_path() + } } } else { false diff --git a/espanso/src/path/linux.rs b/espanso/src/path/linux.rs new file mode 100644 index 0000000..391f67e --- /dev/null +++ b/espanso/src/path/linux.rs @@ -0,0 +1,35 @@ +/* + * This file is part of espanso. + * + * Copyright (C) 2019-2021 Federico Terzi + * + * espanso is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * espanso is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with espanso. If not, see . + */ + +use anyhow::Result; + +pub fn is_espanso_in_path() -> bool { + // Not supported on Linux + true +} + +pub fn add_espanso_to_path(_: bool) -> Result<()> { + // Not supported on Linux + Ok(()) +} + +pub fn remove_espanso_from_path(_: bool) -> Result<()> { + // Not supported on Linux + Ok(()) +} \ No newline at end of file diff --git a/espanso/src/path/mod.rs b/espanso/src/path/mod.rs index 3baeb66..0a91140 100644 --- a/espanso/src/path/mod.rs +++ b/espanso/src/path/mod.rs @@ -19,7 +19,6 @@ #[cfg(target_os = "macos")] mod macos; - #[cfg(target_os = "macos")] pub use macos::add_espanso_to_path; #[cfg(target_os = "macos")] @@ -27,4 +26,20 @@ pub use macos::remove_espanso_from_path; #[cfg(target_os = "macos")] pub use macos::is_espanso_in_path; -// TODO: add Linux stub \ No newline at end of file +#[cfg(target_os = "windows")] +mod win; +#[cfg(target_os = "windows")] +pub use win::add_espanso_to_path; +#[cfg(target_os = "windows")] +pub use win::remove_espanso_from_path; +#[cfg(target_os = "windows")] +pub use win::is_espanso_in_path; + +#[cfg(target_os = "linux")] +mod linux; +#[cfg(target_os = "linux")] +pub use linux::add_espanso_to_path; +#[cfg(target_os = "linux")] +pub use linux::remove_espanso_from_path; +#[cfg(target_os = "linux")] +pub use linux::is_espanso_in_path; diff --git a/espanso/src/path/win.rs b/espanso/src/path/win.rs new file mode 100644 index 0000000..7d4ea31 --- /dev/null +++ b/espanso/src/path/win.rs @@ -0,0 +1,81 @@ +/* + * This file is part of espanso. + * + * Copyright (C) 2019-2021 Federico Terzi + * + * espanso is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * espanso is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with espanso. If not, see . + */ + +use anyhow::Result; +use winreg::enums::*; +use winreg::RegKey; + +pub fn is_espanso_in_path() -> bool { + read_paths().iter().any(|path| path.contains("espanso")) +} + +pub fn add_espanso_to_path(_: bool) -> Result<()> { + let mut paths = read_paths(); + let exe_path = std::env::current_exe().expect("unable to obtain exec path"); + let parent_path = exe_path.parent().expect("unable to obtain parent path"); + + // Add espanso to path list + paths.push(parent_path.to_string_lossy().to_string()); + + let path = paths.join(";"); + write_user_path_value(path)?; + + // Send broadcast to let other applications know that the env variables have changed + send_change_broadcast(); + + Ok(()) +} + +pub fn remove_espanso_from_path(_: bool) -> Result<()> { + let paths = read_paths(); + let paths_without_espanso: Vec = paths.into_iter().filter(|path| !path.contains("espanso")).collect(); + let path = paths_without_espanso.join(";"); + write_user_path_value(path) +} + +fn read_user_path_value() -> Result { + let hkcu = RegKey::predef(HKEY_CURRENT_USER); + let env = hkcu.open_subkey("Environment")?; + let path: String = env.get_value("Path")?; + Ok(path) +} + +fn read_paths() -> Vec { + let path_value = read_user_path_value().unwrap_or_default(); + let paths = path_value.split(";"); + paths.map(String::from).collect() +} + +fn write_user_path_value(value: String) -> Result<()> { + let hkcu = RegKey::predef(HKEY_CURRENT_USER); + let env = hkcu.open_subkey_with_flags("Environment", KEY_ALL_ACCESS)?; + env.set_value("Path", &value)?; + Ok(()) +} + +fn send_change_broadcast() { + use winapi::um::winuser::{SendMessageTimeoutW, HWND_BROADCAST, WM_SETTINGCHANGE}; + + let wide_string = widestring::WideString::from("Environment".to_string()); + + unsafe { + let mut res: usize = 0; + SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, wide_string.as_ptr() as isize, 2, 1000, &mut res); + } +} \ No newline at end of file