diff --git a/espanso/src/cli/launcher/mod.rs b/espanso/src/cli/launcher/mod.rs index dd6f0db..9be664a 100644 --- a/espanso/src/cli/launcher/mod.rs +++ b/espanso/src/cli/launcher/mod.rs @@ -94,6 +94,24 @@ fn launcher_main(args: CliModuleArgs) -> i32 { }, }); + let is_auto_start_page_enabled = !preferences.has_selected_auto_start_option(); + let preferences_clone = preferences.clone(); + let auto_start_handler = Box::new(move |auto_start| { + preferences_clone.set_has_selected_auto_start_option(true); + + if auto_start { + match util::configure_auto_start(true) { + Ok(_) => true, + Err(error) => { + eprintln!("Service register returned error: {}", error); + false + } + } + } else { + true + } + }); + let is_add_path_page_enabled = if cfg!(not(target_os = "linux")) && !preferences.has_completed_wizard() { if cfg!(target_os = "macos") { @@ -133,6 +151,7 @@ fn launcher_main(args: CliModuleArgs) -> i32 { || is_move_bundle_page_enabled || is_legacy_version_page_enabled || is_migrate_page_enabled + || is_auto_start_page_enabled || is_add_path_page_enabled || is_accessibility_page_enabled || is_wrong_edition_page_enabled @@ -144,6 +163,7 @@ fn launcher_main(args: CliModuleArgs) -> i32 { is_legacy_version_page_enabled, is_wrong_edition_page_enabled, is_migrate_page_enabled, + is_auto_start_page_enabled, is_add_path_page_enabled, is_accessibility_page_enabled, window_icon_path: icon_paths @@ -162,6 +182,7 @@ fn launcher_main(args: CliModuleArgs) -> i32 { handlers: WizardHandlers { is_legacy_version_running: Some(is_legacy_version_running_handler), backup_and_migrate: Some(backup_and_migrate_handler), + auto_start: Some(auto_start_handler), add_to_path: Some(add_to_path_handler), enable_accessibility: Some(enable_accessibility_handler), is_accessibility_enabled: Some(is_accessibility_enabled_handler), diff --git a/espanso/src/cli/launcher/util.rs b/espanso/src/cli/launcher/util.rs index 3a93e0c..e4fd3b0 100644 --- a/espanso/src/cli/launcher/util.rs +++ b/espanso/src/cli/launcher/util.rs @@ -19,13 +19,14 @@ use std::{path::Path, process::Command}; -use anyhow::Result; +use anyhow::{bail, Result}; use espanso_path::Paths; use thiserror::Error; use crate::{ exit_code::{MIGRATE_CLEAN_FAILURE, MIGRATE_DIRTY_FAILURE}, lock::acquire_legacy_lock, + util::set_command_flags, }; pub fn is_legacy_version_running(runtime_path: &Path) -> bool { @@ -106,3 +107,26 @@ pub fn show_already_running_warning() -> Result<()> { child.wait()?; Ok(()) } + +pub fn configure_auto_start(auto_start: bool) -> Result<()> { + let espanso_exe_path = std::env::current_exe()?; + let mut command = Command::new(&espanso_exe_path.to_string_lossy().to_string()); + let mut args = vec!["service"]; + if auto_start { + args.push("register"); + } else { + args.push("unregister"); + } + + command.args(&args); + set_command_flags(&mut command); + + let mut child = command.spawn()?; + let result = child.wait()?; + + if result.success() { + Ok(()) + } else { + bail!("service registration returned non-zero exit code"); + } +} diff --git a/espanso/src/cli/service/win.rs b/espanso/src/cli/service/win.rs index 3fa25dd..f41b383 100644 --- a/espanso/src/cli/service/win.rs +++ b/espanso/src/cli/service/win.rs @@ -24,6 +24,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use thiserror::Error; +use crate::util::set_command_flags; use crate::{error_eprintln, warn_eprintln}; pub fn register() -> Result<()> { @@ -145,13 +146,15 @@ fn create_shortcut_target_file( target_path: &Path, arguments: &str, ) -> Result<()> { - let output = Command::new("powershell") - .arg("-c") - .arg("$WshShell = New-Object -comObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut($env:SHORTCUT_PATH); $Shortcut.TargetPath = $env:TARGET_PATH; $Shortcut.Arguments = $env:TARGET_ARGS; $Shortcut.Save()") - .env("SHORTCUT_PATH", shortcut_path.to_string_lossy().to_string()) - .env("TARGET_PATH", target_path.to_string_lossy().to_string()) - .env("TARGET_ARGS", arguments) - .output()?; + let mut command = Command::new("powershell"); + command.arg("-c"); + command.arg("$WshShell = New-Object -comObject WScript.Shell; $Shortcut = $WshShell.CreateShortcut($env:SHORTCUT_PATH); $Shortcut.TargetPath = $env:TARGET_PATH; $Shortcut.Arguments = $env:TARGET_ARGS; $Shortcut.Save()"); + command.env("SHORTCUT_PATH", shortcut_path.to_string_lossy().to_string()); + command.env("TARGET_PATH", target_path.to_string_lossy().to_string()); + command.env("TARGET_ARGS", arguments); + + set_command_flags(&mut command); + let output = command.output()?; if !output.status.success() { return Err(ShortcutError::PowershellNonZeroExitCode.into()); diff --git a/espanso/src/preferences/default.rs b/espanso/src/preferences/default.rs index e7747c1..d04ccca 100644 --- a/espanso/src/preferences/default.rs +++ b/espanso/src/preferences/default.rs @@ -28,6 +28,7 @@ const HAS_COMPLETED_WIZARD_KEY: &str = "has_completed_wizard"; const HAS_DISPLAYED_WELCOME_KEY: &str = "has_displayed_welcome"; const SHOULD_DISPLAY_TROUBLESHOOT_FOR_NON_FATAL_ERRORS: &str = "should_display_troubleshoot_for_non_fatal_errors"; +const HAS_SELECTED_AUTO_START_OPTION: &str = "has_selected_auto_start_option"; #[derive(Clone)] pub struct DefaultPreferences { @@ -80,4 +81,12 @@ impl Preferences for DefaultPreferences { fn set_should_display_troubleshoot_for_non_fatal_errors(&self, value: bool) { self.set(SHOULD_DISPLAY_TROUBLESHOOT_FOR_NON_FATAL_ERRORS, value); } + + fn has_selected_auto_start_option(&self) -> bool { + self.get(HAS_SELECTED_AUTO_START_OPTION).unwrap_or(false) + } + + fn set_has_selected_auto_start_option(&self, value: bool) { + self.set(HAS_SELECTED_AUTO_START_OPTION, value); + } } diff --git a/espanso/src/preferences/mod.rs b/espanso/src/preferences/mod.rs index 569fb37..5739217 100644 --- a/espanso/src/preferences/mod.rs +++ b/espanso/src/preferences/mod.rs @@ -31,6 +31,9 @@ pub trait Preferences: Send + Sync + Clone { fn should_display_troubleshoot_for_non_fatal_errors(&self) -> bool; fn set_should_display_troubleshoot_for_non_fatal_errors(&self, value: bool); + + fn has_selected_auto_start_option(&self) -> bool; + fn set_has_selected_auto_start_option(&self, value: bool); } pub fn get_default(runtime_dir: &Path) -> Result {