Fix formatting

This commit is contained in:
Federico Terzi 2020-08-15 19:35:14 +02:00
parent 161017f024
commit 411078a503
20 changed files with 312 additions and 179 deletions

View File

@ -244,7 +244,7 @@ pub struct Configs {
#[serde(default = "default_secure_input_watcher_interval")]
pub secure_input_watcher_interval: i32,
#[serde(default = "default_mac_post_inject_delay")]
pub mac_post_inject_delay: u64,
@ -282,7 +282,7 @@ pub struct Configs {
pub global_vars: Vec<MatchVariable>,
#[serde(default = "default_modulo_path")]
pub modulo_path: Option<String>
pub modulo_path: Option<String>,
}
// Macro used to validate config fields

View File

@ -19,7 +19,7 @@
use crate::clipboard::ClipboardManager;
use crate::config::BackendType;
use crate::config::{Configs, ConfigManager};
use crate::config::{ConfigManager, Configs};
use crate::event::{ActionEventReceiver, ActionType, SystemEvent, SystemEventReceiver};
use crate::keyboard::KeyboardManager;
use crate::matcher::{Match, MatchReceiver};
@ -158,9 +158,7 @@ impl<
if cfg!(target_os = "linux") {
let all_ascii = target_string.chars().all(|c| c.is_ascii());
if all_ascii {
debug!(
"All elements of the replacement are ascii, using Inject backend"
);
debug!("All elements of the replacement are ascii, using Inject backend");
&BackendType::Inject
} else {
debug!("There are non-ascii characters, using Clipboard backend");
@ -273,7 +271,10 @@ impl<
// Disallow undo backspace if cursor positioning is used
if cursor_rewind.is_none() {
expansion_data = Some((m.triggers[trigger_offset].clone(), target_string.chars().count() as i32));
expansion_data = Some((
m.triggers[trigger_offset].clone(),
target_string.chars().count() as i32,
));
}
if let Some(moves) = cursor_rewind {
@ -310,7 +311,9 @@ impl<
// giving back the control. Otherwise, the injected actions will be handled back
// by espanso itself.
if cfg!(target_os = "macos") {
std::thread::sleep(std::time::Duration::from_millis(config.mac_post_inject_delay));
std::thread::sleep(std::time::Duration::from_millis(
config.mac_post_inject_delay,
));
}
// Re-allow espanso to interpret actions
@ -350,7 +353,8 @@ impl<
if let Some(ref last_expansion_data) = *last_expansion_data {
let (trigger_string, injected_text_len) = last_expansion_data;
// Delete the previously injected text, minus one character as it has been consumed by the backspace
self.keyboard_manager.delete_string(&config, *injected_text_len - 1);
self.keyboard_manager
.delete_string(&config, *injected_text_len - 1);
// Restore previous text
self.inject_text(&config, trigger_string, false);
}

View File

@ -18,8 +18,8 @@
*/
use crate::clipboard::ClipboardManager;
use serde_yaml::Mapping;
use crate::extension::ExtensionResult;
use serde_yaml::Mapping;
use std::collections::HashMap;
pub struct ClipboardExtension {
@ -37,7 +37,12 @@ impl super::Extension for ClipboardExtension {
String::from("clipboard")
}
fn calculate(&self, _: &Mapping, _: &Vec<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
_: &Mapping,
_: &Vec<String>,
_: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
if let Some(clipboard) = self.clipboard_manager.get_clipboard() {
Some(ExtensionResult::Single(clipboard))
} else {

View File

@ -17,10 +17,10 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use chrono::{DateTime, Local, Duration};
use crate::extension::ExtensionResult;
use chrono::{DateTime, Duration, Local};
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use crate::extension::ExtensionResult;
pub struct DateExtension {}
@ -35,13 +35,18 @@ impl super::Extension for DateExtension {
String::from("date")
}
fn calculate(&self, params: &Mapping, _: &Vec<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
_: &Vec<String>,
_: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let mut now: DateTime<Local> = Local::now();
// Compute the given offset
let offset = params.get(&Value::from("offset"));
if let Some(offset) = offset {
let seconds = offset.as_i64().unwrap_or_else(|| { 0 });
let seconds = offset.as_i64().unwrap_or_else(|| 0);
let offset = Duration::seconds(seconds);
now = now + offset;
}

View File

@ -17,9 +17,9 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::extension::ExtensionResult;
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use crate::extension::ExtensionResult;
pub struct DummyExtension {
name: String,
@ -38,11 +38,18 @@ impl super::Extension for DummyExtension {
self.name.clone()
}
fn calculate(&self, params: &Mapping, _: &Vec<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
_: &Vec<String>,
_: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let echo = params.get(&Value::from("echo"));
if let Some(echo) = echo {
Some(ExtensionResult::Single(echo.as_str().unwrap_or_default().to_owned()))
Some(ExtensionResult::Single(
echo.as_str().unwrap_or_default().to_owned(),
))
} else {
None
}

View File

@ -17,10 +17,10 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::{config::Configs, extension::ExtensionResult, ui::modulo::ModuloManager};
use log::{error, warn};
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use crate::{ui::modulo::ModuloManager, extension::ExtensionResult, config::Configs};
use log::{error, warn};
pub struct FormExtension {
manager: ModuloManager,
@ -29,9 +29,7 @@ pub struct FormExtension {
impl FormExtension {
pub fn new(config: &Configs) -> FormExtension {
let manager = ModuloManager::new(config);
FormExtension {
manager,
}
FormExtension { manager }
}
}
@ -40,7 +38,12 @@ impl super::Extension for FormExtension {
"form".to_owned()
}
fn calculate(&self, params: &Mapping, _: &Vec<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
_: &Vec<String>,
_: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let layout = params.get(&Value::from("layout"));
let layout = if let Some(value) = layout {
value.as_str().unwrap_or_default().to_string()
@ -48,21 +51,24 @@ impl super::Extension for FormExtension {
error!("invoking form extension without specifying a layout");
return None;
};
let mut form_config = Mapping::new();
form_config.insert(Value::from("layout"), Value::from(layout));
if let Some(fields) = params.get(&Value::from("fields")) {
form_config.insert(Value::from("fields"), fields.clone());
}
let serialized_config: String = serde_yaml::to_string(&form_config).expect("unable to serialize form config");
let output = self.manager.invoke(&["form", "-i", "-"], &serialized_config);
if let Some(fields) = params.get(&Value::from("fields")) {
form_config.insert(Value::from("fields"), fields.clone());
}
let serialized_config: String =
serde_yaml::to_string(&form_config).expect("unable to serialize form config");
let output = self
.manager
.invoke(&["form", "-i", "-"], &serialized_config);
// On macOS, after the form closes we have to wait until the user releases the modifier keys
on_form_close();
if let Some(output) = output {
let json: Result<HashMap<String, String>, _> = serde_json::from_str(&output);
match json {
@ -77,7 +83,7 @@ impl super::Extension for FormExtension {
} else {
error!("modulo form didn't return any output");
return None;
}
}
}
}
@ -92,4 +98,4 @@ fn on_form_close() {
if !released {
warn!("Wait for modifiers release timed out! Please after closing the form, release your modifiers keys (CTRL, CMD, ALT, SHIFT)");
}
}
}

View File

@ -17,20 +17,20 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::{config::Configs, clipboard::ClipboardManager};
use crate::{clipboard::ClipboardManager, config::Configs};
use serde_yaml::Mapping;
use std::collections::HashMap;
mod clipboard;
mod date;
pub mod dummy;
mod form;
pub mod multiecho;
mod random;
mod script;
mod shell;
pub mod multiecho;
pub mod vardummy;
mod utils;
mod form;
pub mod vardummy;
#[derive(Clone, Debug, PartialEq)]
pub enum ExtensionResult {
@ -40,10 +40,18 @@ pub enum ExtensionResult {
pub trait Extension {
fn name(&self) -> String;
fn calculate(&self, params: &Mapping, args: &Vec<String>, current_vars: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult>;
fn calculate(
&self,
params: &Mapping,
args: &Vec<String>,
current_vars: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult>;
}
pub fn get_extensions(config: &Configs, clipboard_manager: Box<dyn ClipboardManager>) -> Vec<Box<dyn Extension>> {
pub fn get_extensions(
config: &Configs,
clipboard_manager: Box<dyn ClipboardManager>,
) -> Vec<Box<dyn Extension>> {
vec![
Box::new(date::DateExtension::new()),
Box::new(shell::ShellExtension::new()),

View File

@ -17,9 +17,9 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::extension::ExtensionResult;
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use crate::extension::ExtensionResult;
pub struct MultiEchoExtension {}
@ -34,7 +34,12 @@ impl super::Extension for MultiEchoExtension {
"multiecho".to_owned()
}
fn calculate(&self, params: &Mapping, _: &Vec<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
_: &Vec<String>,
_: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let mut output: HashMap<String, String> = HashMap::new();
for (key, value) in params.iter() {
if let Some(key) = key.as_str() {

View File

@ -17,11 +17,11 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::extension::ExtensionResult;
use log::{error, warn};
use rand::seq::SliceRandom;
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use crate::extension::ExtensionResult;
pub struct RandomExtension {}
@ -36,7 +36,12 @@ impl super::Extension for RandomExtension {
String::from("random")
}
fn calculate(&self, params: &Mapping, args: &Vec<String>, _: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
args: &Vec<String>,
_: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let choices = params.get(&Value::from("choices"));
if choices.is_none() {
warn!("No 'choices' parameter specified for random variable");
@ -89,7 +94,9 @@ mod tests {
let output = output.unwrap();
assert!(choices.into_iter().any(|x| ExtensionResult::Single(x.to_owned()) == output));
assert!(choices
.into_iter()
.any(|x| ExtensionResult::Single(x.to_owned()) == output));
}
#[test]
@ -107,6 +114,8 @@ mod tests {
let rendered_choices = vec!["first test", "second test", "test third"];
assert!(rendered_choices.into_iter().any(|x| ExtensionResult::Single(x.to_owned()) == output));
assert!(rendered_choices
.into_iter()
.any(|x| ExtensionResult::Single(x.to_owned()) == output));
}
}

View File

@ -17,12 +17,12 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::extension::ExtensionResult;
use log::{error, warn};
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
use std::collections::HashMap;
use crate::extension::ExtensionResult;
pub struct ScriptExtension {}
@ -37,7 +37,12 @@ impl super::Extension for ScriptExtension {
String::from("script")
}
fn calculate(&self, params: &Mapping, user_args: &Vec<String>, vars: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
user_args: &Vec<String>,
vars: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let args = params.get(&Value::from("args"));
if args.is_none() {
warn!("No 'args' parameter specified for script variable");
@ -69,10 +74,20 @@ impl super::Extension for ScriptExtension {
*arg = arg.replace("%HOME%", &home_dir.to_string_lossy().to_string());
}
if arg.contains("%CONFIG%") {
*arg = arg.replace("%CONFIG%", &crate::context::get_config_dir().to_string_lossy().to_string());
*arg = arg.replace(
"%CONFIG%",
&crate::context::get_config_dir()
.to_string_lossy()
.to_string(),
);
}
if arg.contains("%PACKAGES%") {
*arg = arg.replace("%PACKAGES%", &crate::context::get_package_dir().to_string_lossy().to_string());
*arg = arg.replace(
"%PACKAGES%",
&crate::context::get_package_dir()
.to_string_lossy()
.to_string(),
);
}
// On Windows, correct paths separators
@ -162,7 +177,10 @@ mod tests {
let output = extension.calculate(&params, &vec![], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world".to_owned())
);
}
#[test]
@ -179,7 +197,10 @@ mod tests {
let output = extension.calculate(&params, &vec![], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world\n".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world\n".to_owned())
);
}
#[test]
@ -195,7 +216,10 @@ mod tests {
let output = extension.calculate(&params, &vec!["jon".to_owned()], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world".to_owned())
);
}
#[test]
@ -212,7 +236,10 @@ mod tests {
let output = extension.calculate(&params, &vec!["jon".to_owned()], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world jon".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world jon".to_owned())
);
}
#[test]
@ -228,12 +255,18 @@ mod tests {
let mut subvars = HashMap::new();
subvars.insert("name".to_owned(), "John".to_owned());
vars.insert("form1".to_owned(), ExtensionResult::Multiple(subvars));
vars.insert("var1".to_owned(), ExtensionResult::Single("hello".to_owned()));
vars.insert(
"var1".to_owned(),
ExtensionResult::Single("hello".to_owned()),
);
let extension = ScriptExtension::new();
let output = extension.calculate(&params, &vec![], &vars);
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello John".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello John".to_owned())
);
}
}

View File

@ -17,12 +17,12 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::extension::ExtensionResult;
use log::{error, info, warn};
use regex::{Captures, Regex};
use serde_yaml::{Mapping, Value};
use std::process::{Command, Output};
use std::collections::HashMap;
use crate::extension::ExtensionResult;
use std::process::{Command, Output};
lazy_static! {
static ref POS_ARG_REGEX: Regex = if cfg!(target_os = "windows") {
@ -150,7 +150,12 @@ impl super::Extension for ShellExtension {
String::from("shell")
}
fn calculate(&self, params: &Mapping, args: &Vec<String>, vars: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
args: &Vec<String>,
vars: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let cmd = params.get(&Value::from("cmd"));
if cmd.is_none() {
warn!("No 'cmd' parameter specified for shell variable");
@ -260,9 +265,15 @@ mod tests {
assert!(output.is_some());
if cfg!(target_os = "windows") {
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world\r\n".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world\r\n".to_owned())
);
} else {
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world\n".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world\n".to_owned())
);
}
}
@ -275,7 +286,10 @@ mod tests {
let output = extension.calculate(&params, &vec![], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world".to_owned())
);
}
#[test]
@ -290,7 +304,10 @@ mod tests {
let output = extension.calculate(&params, &vec![], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world".to_owned())
);
}
#[test]
@ -303,7 +320,10 @@ mod tests {
let output = extension.calculate(&params, &vec![], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world".to_owned())
);
}
#[test]
@ -317,7 +337,10 @@ mod tests {
let output = extension.calculate(&params, &vec![], &HashMap::new());
assert!(output.is_some());
assert_eq!(output.unwrap(), ExtensionResult::Single("hello world".to_owned()));
assert_eq!(
output.unwrap(),
ExtensionResult::Single("hello world".to_owned())
);
}
#[test]
@ -354,13 +377,16 @@ mod tests {
if cfg!(target_os = "windows") {
params.insert(Value::from("cmd"), Value::from("echo %ESPANSO_VAR1%"));
params.insert(Value::from("shell"), Value::from("cmd"));
}else{
} else {
params.insert(Value::from("cmd"), Value::from("echo $ESPANSO_VAR1"));
}
let extension = ShellExtension::new();
let mut vars: HashMap<String, ExtensionResult> = HashMap::new();
vars.insert("var1".to_owned(), ExtensionResult::Single("hello".to_owned()));
vars.insert(
"var1".to_owned(),
ExtensionResult::Single("hello".to_owned()),
);
let output = extension.calculate(&params, &vec![], &vars);
assert!(output.is_some());
@ -373,7 +399,7 @@ mod tests {
if cfg!(target_os = "windows") {
params.insert(Value::from("cmd"), Value::from("echo %ESPANSO_FORM1_NAME%"));
params.insert(Value::from("shell"), Value::from("cmd"));
}else{
} else {
params.insert(Value::from("cmd"), Value::from("echo $ESPANSO_FORM1_NAME"));
}

View File

@ -1,8 +1,10 @@
use crate::extension::ExtensionResult;
use std::collections::HashMap;
use std::process::Command;
use crate::extension::ExtensionResult;
pub fn convert_to_env_variables(original_vars: &HashMap<String, ExtensionResult>) -> HashMap<String, String> {
pub fn convert_to_env_variables(
original_vars: &HashMap<String, ExtensionResult>,
) -> HashMap<String, String> {
let mut output = HashMap::new();
for (key, result) in original_vars.iter() {
@ -10,13 +12,13 @@ pub fn convert_to_env_variables(original_vars: &HashMap<String, ExtensionResult>
ExtensionResult::Single(value) => {
let name = format!("ESPANSO_{}", key.to_uppercase());
output.insert(name, value.clone());
},
}
ExtensionResult::Multiple(values) => {
for (sub_key, sub_value) in values.iter() {
let name = format!("ESPANSO_{}_{}", key.to_uppercase(), sub_key.to_uppercase());
output.insert(name, sub_value.clone());
}
},
}
}
}
@ -36,7 +38,6 @@ pub fn set_command_flags(command: &mut Command) {
// NOOP on Linux and macOS
}
#[cfg(test)]
mod tests {
use super::*;
@ -49,11 +50,14 @@ mod tests {
subvars.insert("name".to_owned(), "John".to_owned());
subvars.insert("lastname".to_owned(), "Snow".to_owned());
vars.insert("form1".to_owned(), ExtensionResult::Multiple(subvars));
vars.insert("var1".to_owned(), ExtensionResult::Single("test".to_owned()));
vars.insert(
"var1".to_owned(),
ExtensionResult::Single("test".to_owned()),
);
let output = convert_to_env_variables(&vars);
assert_eq!(output.get("ESPANSO_FORM1_NAME").unwrap(), "John");
assert_eq!(output.get("ESPANSO_FORM1_LASTNAME").unwrap(), "Snow");
assert_eq!(output.get("ESPANSO_VAR1").unwrap(), "test");
}
}
}

View File

@ -17,9 +17,9 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
use crate::extension::ExtensionResult;
use serde_yaml::{Mapping, Value};
use std::collections::HashMap;
use crate::extension::ExtensionResult;
pub struct VarDummyExtension {}
@ -34,7 +34,12 @@ impl super::Extension for VarDummyExtension {
"vardummy".to_owned()
}
fn calculate(&self, params: &Mapping, _: &Vec<String>, vars: &HashMap<String, ExtensionResult>) -> Option<ExtensionResult> {
fn calculate(
&self,
params: &Mapping,
_: &Vec<String>,
vars: &HashMap<String, ExtensionResult>,
) -> Option<ExtensionResult> {
let target = params.get(&Value::from("target"));
if let Some(target) = target {

View File

@ -20,7 +20,7 @@
use super::PasteShortcut;
use crate::bridge::macos::*;
use crate::config::Configs;
use log::{error};
use log::error;
use std::ffi::CString;
pub struct MacKeyboardManager {}
@ -78,12 +78,12 @@ impl super::KeyboardManager for MacKeyboardManager {
pub fn wait_for_modifiers_release() -> bool {
let start = std::time::SystemTime::now();
while start.elapsed().unwrap_or_default().as_millis() < 3000 {
while start.elapsed().unwrap_or_default().as_millis() < 3000 {
let pressed = unsafe { crate::bridge::macos::are_modifiers_pressed() };
if pressed == 0 {
return true
return true;
}
std::thread::sleep(std::time::Duration::from_millis(100));
}
false
}
}

View File

@ -17,7 +17,7 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/
#![cfg_attr(not(test), windows_subsystem = "windows")]
#![cfg_attr(not(test), windows_subsystem = "windows")]
#[macro_use]
extern crate lazy_static;
@ -352,7 +352,7 @@ fn main() {
fn attach_console() {
// When using the windows subsystem we loose the terminal output.
// Therefore we try to attach to the current console if available.
unsafe {winapi::um::wincon::AttachConsole(0xFFFFFFFF)};
unsafe { winapi::um::wincon::AttachConsole(0xFFFFFFFF) };
}
#[cfg(not(target_os = "windows"))]
@ -582,8 +582,13 @@ fn watcher_background(sender: Sender<Event>) {
};
if let Some(path) = path {
if path.extension().unwrap_or_default() == "yml" &&
!path.file_name().unwrap_or_default().to_string_lossy().starts_with("."){
if path.extension().unwrap_or_default() == "yml"
&& !path
.file_name()
.unwrap_or_default()
.to_string_lossy()
.starts_with(".")
{
// Only load non-hidden yml files
true
} else {
@ -688,7 +693,10 @@ fn worker_background(
let keyboard_manager = keyboard::get_manager();
let extensions = extension::get_extensions(config_manager.default_config(), Box::new(clipboard::get_manager()));
let extensions = extension::get_extensions(
config_manager.default_config(),
Box::new(clipboard::get_manager()),
);
let renderer =
render::default::DefaultRenderer::new(extensions, config_manager.default_config().clone());

View File

@ -75,7 +75,8 @@ impl<'de> serde::Deserialize<'de> for Match {
impl<'a> From<&'a AutoMatch> for Match {
fn from(other: &'a AutoMatch) -> Self {
lazy_static! {
static ref VAR_REGEX: Regex = Regex::new("\\{\\{\\s*(\\w+)(\\.\\w+)?\\s*\\}\\}").unwrap();
static ref VAR_REGEX: Regex =
Regex::new("\\{\\{\\s*(\\w+)(\\.\\w+)?\\s*\\}\\}").unwrap();
};
let mut triggers = if !other.triggers.is_empty() {
@ -145,14 +146,15 @@ impl<'a> From<&'a AutoMatch> for Match {
};
MatchContentType::Text(content)
} else if let Some(form) = &other.form { // Form shorthand
} else if let Some(form) = &other.form {
// Form shorthand
// Replace all the form fields with actual variables
let new_replace = VAR_REGEX.replace_all(&form, |caps: &Captures| {
let var_name = caps.get(1).unwrap().as_str();
format!("{{{{form1.{}}}}}", var_name)
});
let new_replace = new_replace.to_string();
// Convert the form data to valid variables
let mut params = Mapping::new();
if let Some(fields) = &other.form_fields {
@ -163,14 +165,12 @@ impl<'a> From<&'a AutoMatch> for Match {
params.insert(Value::from("fields"), Value::from(mapping_fields));
}
params.insert(Value::from("layout"), Value::from(form.to_owned()));
let vars = vec![
MatchVariable {
name: "form1".to_owned(),
var_type: "form".to_owned(),
params,
}
];
let vars = vec![MatchVariable {
name: "form1".to_owned(),
var_type: "form".to_owned(),
params,
}];
let content = TextContent {
replace: new_replace,
@ -241,7 +241,7 @@ struct AutoMatch {
#[serde(default = "default_form")]
pub form: Option<String>,
#[serde(default = "default_form_fields")]
pub form_fields: Option<HashMap<String, Value>>,
@ -603,20 +603,24 @@ mod tests {
match _match.content {
MatchContentType::Text(content) => {
let mut mapping = Mapping::new();
mapping.insert(Value::from("layout"), Value::from("Hey {{name}}, how are you? {{greet}}"));
assert_eq!(content, TextContent {
replace: "Hey {{form1.name}}, how are you? {{form1.greet}}".to_owned(),
_has_vars: true,
vars: vec![
MatchVariable {
mapping.insert(
Value::from("layout"),
Value::from("Hey {{name}}, how are you? {{greet}}"),
);
assert_eq!(
content,
TextContent {
replace: "Hey {{form1.name}}, how are you? {{form1.greet}}".to_owned(),
_has_vars: true,
vars: vec![MatchVariable {
name: "form1".to_owned(),
var_type: "form".to_owned(),
params: mapping,
}
]
});
},
_ => panic!("wrong content")
}]
}
);
}
_ => panic!("wrong content"),
}
}
@ -639,20 +643,24 @@ mod tests {
submapping.insert(Value::from("name"), Value::from(name_mapping));
let mut mapping = Mapping::new();
mapping.insert(Value::from("fields"), Value::from(submapping));
mapping.insert(Value::from("layout"), Value::from("Hey {{name}}, how are you? {{greet}}"));
assert_eq!(content, TextContent {
replace: "Hey {{form1.name}}, how are you? {{form1.greet}}".to_owned(),
_has_vars: true,
vars: vec![
MatchVariable {
mapping.insert(
Value::from("layout"),
Value::from("Hey {{name}}, how are you? {{greet}}"),
);
assert_eq!(
content,
TextContent {
replace: "Hey {{form1.name}}, how are you? {{form1.greet}}".to_owned(),
_has_vars: true,
vars: vec![MatchVariable {
name: "form1".to_owned(),
var_type: "form".to_owned(),
params: mapping,
}
]
});
},
_ => panic!("wrong content")
}]
}
);
}
_ => panic!("wrong content"),
}
}
}

View File

@ -106,7 +106,7 @@ impl<'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMat
.word_separators
.contains(&c.chars().nth(0).unwrap_or_default());
let mut was_previous_char_a_match = self.was_previous_char_a_match.borrow_mut();
let mut was_previous_char_a_match = self.was_previous_char_a_match.borrow_mut();
(*was_previous_char_a_match) = false;
let mut was_previous_word_separator = self.was_previous_char_word_separator.borrow_mut();
@ -212,8 +212,7 @@ impl<'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMat
self.receiver
.on_match(mtc, trailing_separator, entry.trigger_offset);
(*was_previous_char_a_match) = true;
}
}
@ -221,7 +220,7 @@ impl<'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMat
fn handle_modifier(&self, m: KeyModifier) {
let config = self.config_manager.default_config();
let mut was_previous_char_a_match = self.was_previous_char_a_match.borrow_mut();
let mut was_previous_char_a_match = self.was_previous_char_a_match.borrow_mut();
// TODO: at the moment, activating the passive key triggers the toggle key
// study a mechanism to avoid this problem
@ -280,7 +279,7 @@ impl<'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMat
*was_previous_char_word_separator = true;
// Disable the "backspace undo" feature
let mut was_previous_char_a_match = self.was_previous_char_a_match.borrow_mut();
let mut was_previous_char_a_match = self.was_previous_char_a_match.borrow_mut();
(*was_previous_char_a_match) = false;
}
}

View File

@ -27,7 +27,8 @@ use serde_yaml::Value;
use std::collections::{HashMap, HashSet};
lazy_static! {
static ref VAR_REGEX: Regex = Regex::new(r"\{\{\s*((?P<name>\w+)(\.(?P<subname>(\w+)))?)\s*\}\}").unwrap();
static ref VAR_REGEX: Regex =
Regex::new(r"\{\{\s*((?P<name>\w+)(\.(?P<subname>(\w+)))?)\s*\}\}").unwrap();
static ref UNKNOWN_VARIABLE: String = "".to_string();
}
@ -95,9 +96,8 @@ impl super::Renderer for DefaultRenderer {
target_vars.insert(var_name.to_owned());
}
let match_variables: HashSet<&String> = content.vars.iter().map(|var| {
&var.name
}).collect();
let match_variables: HashSet<&String> =
content.vars.iter().map(|var| &var.name).collect();
// Find the global variables that are not specified in the var list
let mut missing_globals = Vec::new();
@ -106,7 +106,7 @@ impl super::Renderer for DefaultRenderer {
if target_vars.contains(&global_var.name) {
if match_variables.contains(&global_var.name) {
specified_globals.insert(global_var.name.clone(), &global_var);
}else {
} else {
missing_globals.push(global_var);
}
}
@ -120,14 +120,18 @@ impl super::Renderer for DefaultRenderer {
variables.extend(&content.vars);
// Replace variable type "global" with the actual reference
let variables: Vec<&MatchVariable> = variables.into_iter().map(|variable| {
if variable.var_type == "global" {
if let Some(actual_variable) = specified_globals.get(&variable.name) {
return actual_variable.clone();
let variables: Vec<&MatchVariable> = variables
.into_iter()
.map(|variable| {
if variable.var_type == "global" {
if let Some(actual_variable) = specified_globals.get(&variable.name)
{
return actual_variable.clone();
}
}
}
variable
}).collect();
variable
})
.collect();
let mut output_map: HashMap<String, ExtensionResult> = HashMap::new();
@ -178,11 +182,15 @@ impl super::Renderer for DefaultRenderer {
// Normal extension variables
let extension = self.extension_map.get(&variable.var_type);
if let Some(extension) = extension {
let ext_out = extension.calculate(&variable.params, &args, &output_map);
let ext_out =
extension.calculate(&variable.params, &args, &output_map);
if let Some(output) = ext_out {
output_map.insert(variable.name.clone(), output);
} else {
output_map.insert(variable.name.clone(), ExtensionResult::Single("".to_owned()));
output_map.insert(
variable.name.clone(),
ExtensionResult::Single("".to_owned()),
);
warn!(
"Could not generate output for variable: {}",
variable.name
@ -202,28 +210,23 @@ impl super::Renderer for DefaultRenderer {
let var_name = caps.name("name").unwrap().as_str();
let var_subname = caps.name("subname");
match output_map.get(var_name) {
Some(result) => {
match result {
ExtensionResult::Single(output) => {
output
},
ExtensionResult::Multiple(results) => {
match var_subname {
Some(var_subname) => {
let var_subname = var_subname.as_str();
results.get(var_subname).unwrap_or(&UNKNOWN_VARIABLE)
},
None => {
error!("nested name missing from multi-value variable: {}", var_name);
&UNKNOWN_VARIABLE
},
}
},
}
},
None => {
&UNKNOWN_VARIABLE
Some(result) => match result {
ExtensionResult::Single(output) => output,
ExtensionResult::Multiple(results) => match var_subname {
Some(var_subname) => {
let var_subname = var_subname.as_str();
results.get(var_subname).unwrap_or(&UNKNOWN_VARIABLE)
}
None => {
error!(
"nested name missing from multi-value variable: {}",
var_name
);
&UNKNOWN_VARIABLE
}
},
},
None => &UNKNOWN_VARIABLE,
}
});
@ -793,8 +796,6 @@ mod tests {
verify_render(rendered, "RESULT");
}
#[test]
fn test_render_variable_order() {
let config = get_config_for(

View File

@ -0,0 +1 @@

View File

@ -1,7 +1,7 @@
use crate::config::Configs;
use std::process::{Command, Child, Output};
use log::{error, info};
use std::io::{Error, Write};
use std::process::{Child, Command, Output};
pub mod form;
@ -15,9 +15,10 @@ impl ModuloManager {
// Check if the `MODULO_PATH` env variable is configured
if let Some(_modulo_path) = std::env::var_os("MODULO_PATH") {
modulo_path = Some(_modulo_path.to_string_lossy().to_string())
} else if let Some(ref _modulo_path) = config.modulo_path { // Check the configs
} else if let Some(ref _modulo_path) = config.modulo_path {
// Check the configs
modulo_path = Some(_modulo_path.to_owned());
}else{
} else {
// Check in the same directory of espanso
if let Ok(exe_path) = std::env::current_exe() {
if let Some(parent) = exe_path.parent() {
@ -46,9 +47,7 @@ impl ModuloManager {
info!("Using modulo at {:?}", modulo_path);
}
Self {
modulo_path,
}
Self { modulo_path }
}
pub fn is_valid(&self) -> bool {
@ -97,26 +96,26 @@ impl ModuloManager {
}
return Some(output.to_string());
},
}
Err(error) => {
error!("error while getting output from modulo: {}", error);
},
}
}
},
}
Err(error) => {
error!("error while sending body to modulo");
},
}
}
}else{
} else {
error!("unable to open stdin to modulo");
}
},
}
Err(error) => {
error!("error reported when invoking modulo: {}", error);
},
}
}
}
None
}
}
}