Merge pull request #317 from federico-terzi/dev

Version 0.6.2
This commit is contained in:
Federico Terzi 2020-06-10 20:53:56 +02:00 committed by GitHub
commit 5e0ea8ef38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 171 additions and 29 deletions

29
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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.

View File

@ -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();

View File

@ -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.

View File

@ -129,7 +129,7 @@ fn default_show_notifications() -> bool {
true
}
fn default_auto_restart() -> bool {
false
true
}
fn default_show_icon() -> bool {
true

View File

@ -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(&params, &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(&params, &vec![]);
assert!(output.is_some());
assert_eq!(output.unwrap(), "hello world\n");
}
@ -146,7 +179,7 @@ mod tests {
let output = extension.calculate(&params, &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(&params, &vec!["jon".to_owned()]);
assert!(output.is_some());
assert_eq!(output.unwrap(), "hello world jon\n");
assert_eq!(output.unwrap(), "hello world jon");
}
}

View File

@ -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();

View File

@ -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>

View File

@ -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!")

View File

@ -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")
}
}