commit
						5e0ea8ef38
					
				
							
								
								
									
										29
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										29
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -21,6 +21,11 @@ dependencies = [
 | 
			
		|||
 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "arc-swap"
 | 
			
		||||
version = "0.4.7"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "arrayref"
 | 
			
		||||
version = "0.3.5"
 | 
			
		||||
| 
						 | 
				
			
			@ -366,7 +371,7 @@ dependencies = [
 | 
			
		|||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "espanso"
 | 
			
		||||
version = "0.6.1"
 | 
			
		||||
version = "0.6.2"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
| 
						 | 
				
			
			@ -386,6 +391,7 @@ dependencies = [
 | 
			
		|||
 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "signal-hook 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "simplelog 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
| 
						 | 
				
			
			@ -1349,6 +1355,24 @@ dependencies = [
 | 
			
		|||
 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "signal-hook"
 | 
			
		||||
version = "0.1.15"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "signal-hook-registry"
 | 
			
		||||
version = "1.2.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "simplelog"
 | 
			
		||||
version = "0.7.1"
 | 
			
		||||
| 
						 | 
				
			
			@ -1800,6 +1824,7 @@ dependencies = [
 | 
			
		|||
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
 | 
			
		||||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
 | 
			
		||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 | 
			
		||||
"checksum arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
 | 
			
		||||
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
 | 
			
		||||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
 | 
			
		||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
 | 
			
		||||
| 
						 | 
				
			
			@ -1947,6 +1972,8 @@ dependencies = [
 | 
			
		|||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
 | 
			
		||||
"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a"
 | 
			
		||||
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
 | 
			
		||||
"checksum signal-hook 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff2db2112d6c761e12522c65f7768548bd6e8cd23d2a9dae162520626629bd6"
 | 
			
		||||
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
 | 
			
		||||
"checksum simplelog 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe8c881061cce7ee205784634eda7a61922925e7cc2833188467d3a560e027"
 | 
			
		||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
 | 
			
		||||
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
[package]
 | 
			
		||||
name = "espanso"
 | 
			
		||||
version = "0.6.1"
 | 
			
		||||
version = "0.6.2"
 | 
			
		||||
authors = ["Federico Terzi <federicoterzi96@gmail.com>"]
 | 
			
		||||
license = "GPL-3.0"
 | 
			
		||||
description = "Cross-platform Text Expander written in Rust"
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ notify = "4.0.13"
 | 
			
		|||
 | 
			
		||||
[target.'cfg(unix)'.dependencies]
 | 
			
		||||
libc = "0.2.62"
 | 
			
		||||
signal-hook = "0.1.15"
 | 
			
		||||
 | 
			
		||||
[build-dependencies]
 | 
			
		||||
cmake = "0.1.31"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,6 +87,16 @@ void send_string(const char * string) {
 | 
			
		|||
 | 
			
		||||
        // Send the event
 | 
			
		||||
 | 
			
		||||
        // Check if the shift key is down, and if so, release it
 | 
			
		||||
        // To see why: https://github.com/federico-terzi/espanso/issues/279
 | 
			
		||||
        if (CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, 0x38)) {
 | 
			
		||||
            CGEventRef e2 = CGEventCreateKeyboardEvent(NULL, 0x38, false);
 | 
			
		||||
            CGEventPost(kCGHIDEventTap, e2);
 | 
			
		||||
            CFRelease(e2);
 | 
			
		||||
 | 
			
		||||
            usleep(2000);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Because of a bug ( or undocumented limit ) of the CGEventKeyboardSetUnicodeString method
 | 
			
		||||
        // the string gets truncated after 20 characters, so we need to send multiple events.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -210,16 +210,18 @@ LRESULT CALLBACK window_procedure(HWND window, unsigned int msg, WPARAM wp, LPAR
 | 
			
		|||
 | 
			
		||||
            // Convert the input data
 | 
			
		||||
            RAWINPUT* raw = reinterpret_cast<RAWINPUT*>(lpb.data());
 | 
			
		||||
 | 
			
		||||
            // Make sure it's a keyboard type event, relative to a key press.
 | 
			
		||||
            if (raw->header.dwType == RIM_TYPEKEYBOARD)
 | 
			
		||||
            {
 | 
			
		||||
                // We only want KEY UP AND KEY DOWN events
 | 
			
		||||
                if (raw->data.keyboard.Message != WM_KEYDOWN && raw->data.keyboard.Message != WM_KEYUP) {
 | 
			
		||||
                if (raw->data.keyboard.Message != WM_KEYDOWN && raw->data.keyboard.Message != WM_KEYUP &&
 | 
			
		||||
                    raw->data.keyboard.Message != WM_SYSKEYDOWN) {
 | 
			
		||||
                    return 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                int is_key_down = raw->data.keyboard.Message == WM_KEYDOWN;
 | 
			
		||||
                // The alt key sends a SYSKEYDOWN instead of KEYDOWN event
 | 
			
		||||
                int is_key_down = raw->data.keyboard.Message == WM_KEYDOWN ||
 | 
			
		||||
                                  raw->data.keyboard.Message == WM_SYSKEYDOWN;
 | 
			
		||||
 | 
			
		||||
                DWORD currentTick = GetTickCount();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
name: espanso
 | 
			
		||||
version: 0.6.1
 | 
			
		||||
version: 0.6.2
 | 
			
		||||
summary: A Cross-platform Text Expander written in Rust
 | 
			
		||||
description: |
 | 
			
		||||
  espanso is a Cross-platform, Text Expander written in Rust.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -129,7 +129,7 @@ fn default_show_notifications() -> bool {
 | 
			
		|||
    true
 | 
			
		||||
}
 | 
			
		||||
fn default_auto_restart() -> bool {
 | 
			
		||||
    false
 | 
			
		||||
   true
 | 
			
		||||
}
 | 
			
		||||
fn default_show_icon() -> bool {
 | 
			
		||||
    true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ impl super::Extension for ScriptExtension {
 | 
			
		|||
 | 
			
		||||
            match output {
 | 
			
		||||
                Ok(output) => {
 | 
			
		||||
                    let output_str = String::from_utf8_lossy(output.stdout.as_slice());
 | 
			
		||||
                    let mut output_str = String::from_utf8_lossy(output.stdout.as_slice()).to_string();
 | 
			
		||||
                    let error_str = String::from_utf8_lossy(output.stderr.as_slice());
 | 
			
		||||
                    let error_str = error_str.to_string();
 | 
			
		||||
                    let error_str = error_str.trim();
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +98,20 @@ impl super::Extension for ScriptExtension {
 | 
			
		|||
                        warn!("Script command reported error: \n{}", error_str);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return Some(output_str.into_owned());
 | 
			
		||||
                    // If specified, trim the output
 | 
			
		||||
                    let trim_opt = params.get(&Value::from("trim"));
 | 
			
		||||
                    let should_trim = if let Some(value) = trim_opt {
 | 
			
		||||
                        let val = value.as_bool();
 | 
			
		||||
                        val.unwrap_or(true)
 | 
			
		||||
                    }else{
 | 
			
		||||
                        true
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    if should_trim {
 | 
			
		||||
                        output_str = output_str.trim().to_owned()
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return Some(output_str);
 | 
			
		||||
                }
 | 
			
		||||
                Err(e) => {
 | 
			
		||||
                    error!("Could not execute script '{:?}', error: {}", args, e);
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +142,26 @@ mod tests {
 | 
			
		|||
        let extension = ScriptExtension::new();
 | 
			
		||||
        let output = extension.calculate(¶ms, &vec![]);
 | 
			
		||||
 | 
			
		||||
        assert!(output.is_some());
 | 
			
		||||
        assert_eq!(output.unwrap(), "hello world");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    #[cfg(not(target_os = "windows"))]
 | 
			
		||||
    fn test_script_basic_no_trim() {
 | 
			
		||||
        let mut params = Mapping::new();
 | 
			
		||||
        params.insert(
 | 
			
		||||
            Value::from("args"),
 | 
			
		||||
            Value::from(vec!["echo", "hello world"]),
 | 
			
		||||
        );
 | 
			
		||||
        params.insert(
 | 
			
		||||
            Value::from("trim"),
 | 
			
		||||
            Value::from(false),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let extension = ScriptExtension::new();
 | 
			
		||||
        let output = extension.calculate(¶ms, &vec![]);
 | 
			
		||||
 | 
			
		||||
        assert!(output.is_some());
 | 
			
		||||
        assert_eq!(output.unwrap(), "hello world\n");
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +179,7 @@ mod tests {
 | 
			
		|||
        let output = extension.calculate(¶ms, &vec!["jon".to_owned()]);
 | 
			
		||||
 | 
			
		||||
        assert!(output.is_some());
 | 
			
		||||
        assert_eq!(output.unwrap(), "hello world\n");
 | 
			
		||||
        assert_eq!(output.unwrap(), "hello world");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
| 
						 | 
				
			
			@ -163,6 +196,6 @@ mod tests {
 | 
			
		|||
        let output = extension.calculate(¶ms, &vec!["jon".to_owned()]);
 | 
			
		||||
 | 
			
		||||
        assert!(output.is_some());
 | 
			
		||||
        assert_eq!(output.unwrap(), "hello world jon\n");
 | 
			
		||||
        assert_eq!(output.unwrap(), "hello world jon");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/main.rs
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -407,6 +407,8 @@ fn daemon_main(config_set: ConfigSet) {
 | 
			
		|||
        })
 | 
			
		||||
        .expect("Unable to spawn worker monitor thread");
 | 
			
		||||
 | 
			
		||||
    register_signals(config_set.default.clone());
 | 
			
		||||
 | 
			
		||||
    std::thread::sleep(Duration::from_millis(200));
 | 
			
		||||
 | 
			
		||||
    if config_set.default.auto_restart {
 | 
			
		||||
| 
						 | 
				
			
			@ -471,6 +473,35 @@ fn daemon_main(config_set: ConfigSet) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(target_os = "windows")]
 | 
			
		||||
fn register_signals(_: Configs) {}
 | 
			
		||||
 | 
			
		||||
#[cfg(not(target_os = "windows"))]
 | 
			
		||||
fn register_signals(config: Configs) {
 | 
			
		||||
    // On Unix, also listen for signals so that we can terminate the
 | 
			
		||||
    // worker if the daemon receives a signal
 | 
			
		||||
    use signal_hook::{iterator::Signals, SIGTERM, SIGINT};
 | 
			
		||||
    let signals = Signals::new(&[SIGTERM, SIGINT]).expect("unable to register for signals");
 | 
			
		||||
    thread::Builder::new()
 | 
			
		||||
        .name("signal monitor".to_string())
 | 
			
		||||
        .spawn(move || {
 | 
			
		||||
            for signal in signals.forever() {
 | 
			
		||||
                info!("Received signal: {:?}, terminating worker", signal);
 | 
			
		||||
                send_command_or_warn(
 | 
			
		||||
                    Service::Worker,
 | 
			
		||||
                    config,
 | 
			
		||||
                    IPCCommand::exit_worker(),
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                std::thread::sleep(Duration::from_millis(200));
 | 
			
		||||
 | 
			
		||||
                info!("terminating espanso.");
 | 
			
		||||
                std::process::exit(0);
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        .expect("Unable to spawn signal monitor thread");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn watcher_background(sender: Sender<Event>) {
 | 
			
		||||
    // Create a channel to receive the events.
 | 
			
		||||
    let (tx, rx) = channel();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,11 @@
 | 
			
		|||
<dict>
 | 
			
		||||
    <key>Label</key>
 | 
			
		||||
    <string>com.federicoterzi.espanso</string>
 | 
			
		||||
    <key>EnvironmentVariables</key>
 | 
			
		||||
    <dict>
 | 
			
		||||
        <key>PATH</key>
 | 
			
		||||
        <string>{{{PATH}}}</string>
 | 
			
		||||
    </dict>
 | 
			
		||||
    <key>ProgramArguments</key>
 | 
			
		||||
    <array>
 | 
			
		||||
        <string>{{{espanso_path}}}</string>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,12 @@ pub fn register(_config_set: ConfigSet) {
 | 
			
		|||
            espanso_path.to_str().unwrap_or_default(),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Copy the user PATH variable and inject it in the Plist file so that
 | 
			
		||||
        // it gets loaded by Launchd.
 | 
			
		||||
        // To see why this is necessary: https://github.com/federico-terzi/espanso/issues/233
 | 
			
		||||
        let user_path = std::env::var("PATH").unwrap_or("".to_owned());
 | 
			
		||||
        let plist_content = plist_content.replace("{{{PATH}}}", &user_path);
 | 
			
		||||
 | 
			
		||||
        std::fs::write(plist_file.clone(), plist_content).expect("Unable to write plist file");
 | 
			
		||||
 | 
			
		||||
        println!("Entry created correctly!")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,12 +91,6 @@ impl MacSystemManager {
 | 
			
		|||
    /// Check whether an application is currently holding the Secure Input.
 | 
			
		||||
    /// Return None if no application has claimed SecureInput, Some((AppName, AppPath)) otherwise.
 | 
			
		||||
    pub fn get_secure_input_application() -> Option<(String, String)> {
 | 
			
		||||
        use regex::Regex;
 | 
			
		||||
 | 
			
		||||
        lazy_static! {
 | 
			
		||||
            static ref APP_REGEX: Regex = Regex::new("/([^/]+).app/").unwrap();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        unsafe {
 | 
			
		||||
            let pid = MacSystemManager::get_secure_input_pid();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -112,26 +106,59 @@ impl MacSystemManager {
 | 
			
		|||
                    if let Ok(path) = string {
 | 
			
		||||
                        if !path.trim().is_empty() {
 | 
			
		||||
                            let process = path.trim().to_string();
 | 
			
		||||
                            let caps = APP_REGEX.captures(&process);
 | 
			
		||||
                            let app_name = if let Some(caps) = caps {
 | 
			
		||||
                                caps.get(1).map_or("", |m| m.as_str()).to_owned()
 | 
			
		||||
                            let app_name = if let Some(name) = Self::get_app_name_from_path(&process) {
 | 
			
		||||
                                name
 | 
			
		||||
                            } else {
 | 
			
		||||
                                process.to_owned()
 | 
			
		||||
                            };
 | 
			
		||||
 | 
			
		||||
                            Some((app_name, process))
 | 
			
		||||
                        } else {
 | 
			
		||||
                            None
 | 
			
		||||
                            return Some((app_name, process));
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        None
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    None
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                None
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            None
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_app_name_from_path(path: &str) -> Option<String> {
 | 
			
		||||
        use regex::Regex;
 | 
			
		||||
 | 
			
		||||
        lazy_static! {
 | 
			
		||||
            static ref APP_REGEX: Regex = Regex::new("/([^/]+).(app|bundle)/").unwrap();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let caps = APP_REGEX.captures(&path);
 | 
			
		||||
        if let Some(caps) = caps {
 | 
			
		||||
            Some(caps.get(1).map_or("", |m| m.as_str()).to_owned())
 | 
			
		||||
        } else {
 | 
			
		||||
            None
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_get_app_name_from_path() {
 | 
			
		||||
        let app_name = MacSystemManager::get_app_name_from_path("/Applications/iTerm.app/Contents/MacOS/iTerm2");
 | 
			
		||||
        assert_eq!(app_name.unwrap(), "iTerm")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_get_app_name_from_path_no_app_name() {
 | 
			
		||||
        let app_name = MacSystemManager::get_app_name_from_path("/another/directory");
 | 
			
		||||
        assert!(app_name.is_none())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_get_app_name_from_path_security_bundle() {
 | 
			
		||||
        let app_name = MacSystemManager::get_app_name_from_path("/System/Library/Frameworks/Security.framework/Versions/A/MachServices/SecurityAgent.bundle/Contents/MacOS/SecurityAgent");
 | 
			
		||||
        assert_eq!(app_name.unwrap(), "SecurityAgent")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user