From e8881d0faf4957fe51eaf5108852f5b3b56f5720 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Tue, 9 Mar 2021 16:06:50 +0100 Subject: [PATCH] Add license header and formatting --- espanso-config/src/config/mod.rs | 27 +++++- espanso-config/src/config/parse/mod.rs | 31 +++++-- espanso-config/src/config/parse/yaml.rs | 19 ++++ espanso-config/src/config/path.rs | 29 ++++-- espanso-config/src/config/resolve.rs | 81 ++++++++++------- espanso-config/src/config/store.rs | 32 ++++++- espanso-config/src/config/util.rs | 24 ++++- espanso-config/src/counter.rs | 21 ++++- espanso-config/src/lib.rs | 90 +++++++++++++------ .../src/matches/group/loader/mod.rs | 73 ++++++++++++--- .../src/matches/group/loader/yaml/mod.rs | 63 ++++++++----- .../src/matches/group/loader/yaml/parse.rs | 21 ++++- espanso-config/src/matches/group/mod.rs | 23 ++++- espanso-config/src/matches/group/path.rs | 19 ++++ espanso-config/src/matches/mod.rs | 19 ++++ espanso-config/src/matches/store/default.rs | 21 ++++- espanso-config/src/matches/store/mod.rs | 21 ++++- espanso-config/src/util.rs | 23 ++++- espanso-detect/src/evdev/keymap.rs | 38 +++++--- espanso-detect/src/evdev/mod.rs | 9 +- espanso-detect/src/lib.rs | 3 +- espanso-detect/src/mac/mod.rs | 6 +- espanso-detect/src/win32/mod.rs | 6 +- espanso-detect/src/x11/mod.rs | 4 +- espanso-inject/src/evdev/ffi.rs | 2 +- espanso-inject/src/evdev/keymap.rs | 30 ++++--- espanso-inject/src/evdev/mod.rs | 12 ++- espanso-inject/src/evdev/state.rs | 8 +- espanso-inject/src/keys.rs | 2 +- espanso-inject/src/lib.rs | 3 +- espanso-inject/src/linux/mod.rs | 2 +- espanso-inject/src/linux/raw_keys.rs | 2 +- espanso-inject/src/mac/mod.rs | 14 ++- espanso-inject/src/win32/mod.rs | 23 +++-- espanso-inject/src/x11/mod.rs | 15 ++-- espanso-ipc/src/lib.rs | 24 +++-- espanso-ipc/src/windows.rs | 10 +-- espanso-ui/src/lib.rs | 15 ++-- espanso-ui/src/linux/mod.rs | 2 +- espanso-ui/src/mac/mod.rs | 16 ++-- espanso-ui/src/win32/mod.rs | 47 +++++++--- espanso/src/main.rs | 44 +++++---- 42 files changed, 711 insertions(+), 263 deletions(-) diff --git a/espanso-config/src/config/mod.rs b/espanso-config/src/config/mod.rs index 1dee966..8458eef 100644 --- a/espanso-config/src/config/mod.rs +++ b/espanso-config/src/config/mod.rs @@ -1,12 +1,31 @@ +/* + * 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 std::{collections::HashSet, path::Path}; use thiserror::Error; -use anyhow::Result; -mod path; mod parse; -mod util; +mod path; mod resolve; mod store; +mod util; pub trait Config { fn label(&self) -> &str; @@ -42,4 +61,4 @@ pub enum ConfigStoreError { #[error("io error")] IOError(#[from] std::io::Error), -} \ No newline at end of file +} diff --git a/espanso-config/src/config/parse/mod.rs b/espanso-config/src/config/parse/mod.rs index b8b0c08..5815c4e 100644 --- a/espanso-config/src/config/parse/mod.rs +++ b/espanso-config/src/config/parse/mod.rs @@ -1,6 +1,25 @@ +/* + * 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 thiserror::Error; use std::{convert::TryInto, path::Path}; +use thiserror::Error; mod yaml; @@ -26,12 +45,8 @@ impl ParsedConfig { pub fn load(path: &Path) -> Result { let content = std::fs::read_to_string(path)?; match yaml::YAMLConfig::parse_from_str(&content) { - Ok(config) => { - Ok(config.try_into()?) - } - Err(err) => { - Err(ParsedConfigError::LoadFailed(err).into()) - } + Ok(config) => Ok(config.try_into()?), + Err(err) => Err(ParsedConfigError::LoadFailed(err).into()), } } } @@ -40,4 +55,4 @@ impl ParsedConfig { pub enum ParsedConfigError { #[error("can't load config `{0}`")] LoadFailed(#[from] anyhow::Error), -} \ No newline at end of file +} diff --git a/espanso-config/src/config/parse/yaml.rs b/espanso-config/src/config/parse/yaml.rs index 62e8ddf..ff8085f 100644 --- a/espanso-config/src/config/parse/yaml.rs +++ b/espanso-config/src/config/parse/yaml.rs @@ -1,3 +1,22 @@ +/* + * 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 serde::{Deserialize, Serialize}; use std::convert::TryFrom; diff --git a/espanso-config/src/config/path.rs b/espanso-config/src/config/path.rs index 8162cdc..f40befc 100644 --- a/espanso-config/src/config/path.rs +++ b/espanso-config/src/config/path.rs @@ -1,7 +1,23 @@ -use std::{ - collections::HashSet, - path::{Path}, -}; +/* + * 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 std::{collections::HashSet, path::Path}; use glob::glob; use log::error; @@ -36,7 +52,10 @@ pub fn calculate_paths<'a>( path_set.insert(canonical_path.to_string_lossy().to_string()); } Err(err) => { - error!("unable to canonicalize path from glob: {:?}, with error: {}", path, err); + error!( + "unable to canonicalize path from glob: {:?}, with error: {}", + path, err + ); } } } diff --git a/espanso-config/src/config/resolve.rs b/espanso-config/src/config/resolve.rs index 54d6a99..25127be 100644 --- a/espanso-config/src/config/resolve.rs +++ b/espanso-config/src/config/resolve.rs @@ -1,3 +1,22 @@ +/* + * 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 super::{parse::ParsedConfig, path::calculate_paths, util::os_matches, AppProperties, Config}; use crate::merge; use anyhow::Result; @@ -14,7 +33,6 @@ pub(crate) struct ResolvedConfig { parsed: ParsedConfig, // Generated properties - match_paths: Vec, filter_title: Option, @@ -58,38 +76,35 @@ impl Config for ResolvedConfig { true }; - let is_title_match = - if let Some(title_regex) = self.filter_title.as_ref() { - if let Some(title) = app.title { - title_regex.is_match(title) - } else { - false - } + let is_title_match = if let Some(title_regex) = self.filter_title.as_ref() { + if let Some(title) = app.title { + title_regex.is_match(title) } else { - true - }; + false + } + } else { + true + }; - let is_exec_match = - if let Some(exec_regex) = self.filter_exec.as_ref() { - if let Some(exec) = app.exec { - exec_regex.is_match(exec) - } else { - false - } + let is_exec_match = if let Some(exec_regex) = self.filter_exec.as_ref() { + if let Some(exec) = app.exec { + exec_regex.is_match(exec) } else { - true - }; + false + } + } else { + true + }; - let is_class_match = - if let Some(class_regex) = self.filter_class.as_ref() { - if let Some(class) = app.class { - class_regex.is_match(class) - } else { - false - } + let is_class_match = if let Some(class_regex) = self.filter_class.as_ref() { + if let Some(class) = app.class { + class_regex.is_match(class) } else { - true - }; + false + } + } else { + true + }; // All the filters that have been specified must be true to define a match is_os_match && is_exec_match && is_title_match && is_class_match @@ -110,7 +125,9 @@ impl ResolvedConfig { .parent() .ok_or_else(ResolveError::ParentResolveFailed)?; - let match_paths = Self::generate_match_paths(&config, base_dir).into_iter().collect(); + let match_paths = Self::generate_match_paths(&config, base_dir) + .into_iter() + .collect(); let filter_title = if let Some(filter_title) = config.filter_title.as_deref() { Some(Regex::new(filter_title)?) @@ -431,7 +448,7 @@ mod tests { sub_file.to_string_lossy().to_string(), ]; expected.sort(); - + let mut result = config.match_paths().to_vec(); result.sort(); @@ -491,9 +508,7 @@ mod tests { result.sort(); assert_eq!(result, expected.as_slice()); - let expected = vec![ - base_file.to_string_lossy().to_string() - ]; + let expected = vec![base_file.to_string_lossy().to_string()]; assert_eq!(parent.match_paths(), expected.as_slice()); }); diff --git a/espanso-config/src/config/store.rs b/espanso-config/src/config/store.rs index c943a93..13c2b02 100644 --- a/espanso-config/src/config/store.rs +++ b/espanso-config/src/config/store.rs @@ -1,4 +1,23 @@ -use super::{Config, ConfigStore, ConfigStoreError, resolve::ResolvedConfig}; +/* + * 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 super::{resolve::ResolvedConfig, Config, ConfigStore, ConfigStoreError}; use anyhow::Result; use log::{debug, error}; use std::{collections::HashSet, path::Path}; @@ -56,7 +75,11 @@ impl DefaultConfigStore { for entry in std::fs::read_dir(config_dir).map_err(ConfigStoreError::IOError)? { let entry = entry?; let config_file = entry.path(); - let extension = config_file.extension().unwrap_or_default().to_string_lossy().to_lowercase(); + let extension = config_file + .extension() + .unwrap_or_default() + .to_string_lossy() + .to_lowercase(); // Additional config files are loaded best-effort if config_file.is_file() @@ -69,7 +92,10 @@ impl DefaultConfigStore { debug!("loaded config at path: {:?}", config_file); } Err(err) => { - error!("unable to load config at path: {:?}, with error: {}", config_file, err); + error!( + "unable to load config at path: {:?}, with error: {}", + config_file, err + ); } } } diff --git a/espanso-config/src/config/util.rs b/espanso-config/src/config/util.rs index 3ef29fe..0492d72 100644 --- a/espanso-config/src/config/util.rs +++ b/espanso-config/src/config/util.rs @@ -1,3 +1,22 @@ +/* + * 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 . + */ + #[macro_export] macro_rules! merge { ( $t:ident, $child:expr, $parent:expr, $( $x:ident ),* ) => { @@ -7,7 +26,7 @@ macro_rules! merge { $child.$x = $parent.$x.clone(); } )* - + // Build a temporary object to verify that all fields // are being used at compile time $t { @@ -41,7 +60,6 @@ mod tests { assert!(!os_matches("invalid")); } - #[test] #[cfg(target_os = "macos")] fn os_matches_macos() { @@ -59,4 +77,4 @@ mod tests { assert!(!os_matches("linux")); assert!(!os_matches("invalid")); } -} \ No newline at end of file +} diff --git a/espanso-config/src/counter.rs b/espanso-config/src/counter.rs index 7e9338c..80400fb 100644 --- a/espanso-config/src/counter.rs +++ b/espanso-config/src/counter.rs @@ -1,3 +1,22 @@ +/* + * 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 std::sync::atomic::{AtomicUsize, Ordering}; static STRUCT_COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -10,4 +29,4 @@ pub type StructId = usize; /// that is incremented for each struct. pub fn next_id() -> StructId { STRUCT_COUNTER.fetch_add(1, Ordering::SeqCst) -} \ No newline at end of file +} diff --git a/espanso-config/src/lib.rs b/espanso-config/src/lib.rs index b09a2ea..33e19de 100644 --- a/espanso-config/src/lib.rs +++ b/espanso-config/src/lib.rs @@ -17,24 +17,24 @@ * along with espanso. If not, see . */ -use std::path::Path; +use anyhow::Result; use config::ConfigStore; use matches::store::MatchStore; -use anyhow::Result; +use std::path::Path; use thiserror::Error; #[macro_use] extern crate lazy_static; -mod util; -mod counter; pub mod config; +mod counter; pub mod matches; +mod util; pub fn load(base_path: &Path) -> Result<(impl ConfigStore, impl MatchStore)> { let config_dir = base_path.join("config"); if !config_dir.exists() || !config_dir.is_dir() { - return Err(ConfigError::MissingConfigDir().into()) + return Err(ConfigError::MissingConfigDir().into()); } let config_store = config::load_store(&config_dir)?; @@ -55,62 +55,100 @@ pub enum ConfigError { #[cfg(test)] mod tests { use super::*; - use config::{AppProperties, ConfigStore}; use crate::util::tests::use_test_directory; + use config::{AppProperties, ConfigStore}; #[test] fn load_works_correctly() { use_test_directory(|base, match_dir, config_dir| { let base_file = match_dir.join("base.yml"); - std::fs::write(&base_file, r#" + std::fs::write( + &base_file, + r#" matches: - trigger: "hello" replace: "world" - "#).unwrap(); + "#, + ) + .unwrap(); let another_file = match_dir.join("another.yml"); - std::fs::write(&another_file, r#" + std::fs::write( + &another_file, + r#" imports: - "_sub.yml" matches: - trigger: "hello2" replace: "world2" - "#).unwrap(); - + "#, + ) + .unwrap(); + let under_file = match_dir.join("_sub.yml"); - std::fs::write(&under_file, r#" + std::fs::write( + &under_file, + r#" matches: - trigger: "hello3" replace: "world3" - "#).unwrap(); + "#, + ) + .unwrap(); let config_file = config_dir.join("default.yml"); std::fs::write(&config_file, "").unwrap(); let custom_config_file = config_dir.join("custom.yml"); - std::fs::write(&custom_config_file, r#" + std::fs::write( + &custom_config_file, + r#" filter_title: "Chrome" use_standard_includes: false includes: ["../match/another.yml"] - "#).unwrap(); + "#, + ) + .unwrap(); let (config_store, match_store) = load(&base).unwrap(); assert_eq!(config_store.default().match_paths().len(), 2); - assert_eq!(config_store.active(&AppProperties { - title: Some("Google Chrome"), - class: None, - exec: None, - }).match_paths().len(), 1); + assert_eq!( + config_store + .active(&AppProperties { + title: Some("Google Chrome"), + class: None, + exec: None, + }) + .match_paths() + .len(), + 1 + ); - assert_eq!(match_store.query(config_store.default().match_paths()).matches.len(), 3); - assert_eq!(match_store.query(config_store.active(&AppProperties { - title: Some("Chrome"), - class: None, - exec: None, - }).match_paths()).matches.len(), 2); + assert_eq!( + match_store + .query(config_store.default().match_paths()) + .matches + .len(), + 3 + ); + assert_eq!( + match_store + .query( + config_store + .active(&AppProperties { + title: Some("Chrome"), + class: None, + exec: None, + }) + .match_paths() + ) + .matches + .len(), + 2 + ); }); } diff --git a/espanso-config/src/matches/group/loader/mod.rs b/espanso-config/src/matches/group/loader/mod.rs index 81ae143..7e931ee 100644 --- a/espanso-config/src/matches/group/loader/mod.rs +++ b/espanso-config/src/matches/group/loader/mod.rs @@ -1,3 +1,22 @@ +/* + * 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 std::path::Path; use thiserror::Error; @@ -14,9 +33,7 @@ trait Importer { } lazy_static! { - static ref IMPORTERS: Vec> = vec![ - Box::new(YAMLImporter::new()), - ]; + static ref IMPORTERS: Vec> = vec![Box::new(YAMLImporter::new()),]; } pub(crate) fn load_match_group(path: &Path) -> Result { @@ -26,7 +43,7 @@ pub(crate) fn load_match_group(path: &Path) -> Result { let importer = IMPORTERS .iter() .find(|importer| importer.is_supported(&extension)); - + match importer { Some(importer) => match importer.load_group(path) { Ok(group) => Ok(group), @@ -62,7 +79,13 @@ mod tests { let file = match_dir.join("base.invalid"); std::fs::write(&file, "test").unwrap(); - assert!(matches!(load_match_group(&file).unwrap_err().downcast::().unwrap(), LoadError::InvalidFormat())); + assert!(matches!( + load_match_group(&file) + .unwrap_err() + .downcast::() + .unwrap(), + LoadError::InvalidFormat() + )); }); } @@ -72,7 +95,13 @@ mod tests { let file = match_dir.join("base"); std::fs::write(&file, "test").unwrap(); - assert!(matches!(load_match_group(&file).unwrap_err().downcast::().unwrap(), LoadError::MissingExtension())); + assert!(matches!( + load_match_group(&file) + .unwrap_err() + .downcast::() + .unwrap(), + LoadError::MissingExtension() + )); }); } @@ -82,7 +111,13 @@ mod tests { let file = match_dir.join("base.yml"); std::fs::write(&file, "test").unwrap(); - assert!(matches!(load_match_group(&file).unwrap_err().downcast::().unwrap(), LoadError::ParsingError(_))); + assert!(matches!( + load_match_group(&file) + .unwrap_err() + .downcast::() + .unwrap(), + LoadError::ParsingError(_) + )); }); } @@ -90,11 +125,15 @@ mod tests { fn load_group_yaml_format() { use_test_directory(|_, match_dir, _| { let file = match_dir.join("base.yml"); - std::fs::write(&file, r#" + std::fs::write( + &file, + r#" matches: - trigger: "hello" replace: "world" - "#).unwrap(); + "#, + ) + .unwrap(); assert_eq!(load_match_group(&file).unwrap().matches.len(), 1); }); @@ -104,11 +143,15 @@ mod tests { fn load_group_yaml_format_2() { use_test_directory(|_, match_dir, _| { let file = match_dir.join("base.yaml"); - std::fs::write(&file, r#" + std::fs::write( + &file, + r#" matches: - trigger: "hello" replace: "world" - "#).unwrap(); + "#, + ) + .unwrap(); assert_eq!(load_match_group(&file).unwrap().matches.len(), 1); }); @@ -118,11 +161,15 @@ mod tests { fn load_group_yaml_format_casing() { use_test_directory(|_, match_dir, _| { let file = match_dir.join("base.YML"); - std::fs::write(&file, r#" + std::fs::write( + &file, + r#" matches: - trigger: "hello" replace: "world" - "#).unwrap(); + "#, + ) + .unwrap(); assert_eq!(load_match_group(&file).unwrap().matches.len(), 1); }); diff --git a/espanso-config/src/matches/group/loader/yaml/mod.rs b/espanso-config/src/matches/group/loader/yaml/mod.rs index cc3edd9..74e699d 100644 --- a/espanso-config/src/matches/group/loader/yaml/mod.rs +++ b/espanso-config/src/matches/group/loader/yaml/mod.rs @@ -1,3 +1,22 @@ +/* + * 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 crate::matches::{ group::{path::resolve_imports, MatchGroup}, Match, Variable, @@ -140,9 +159,9 @@ impl TryFrom for Variable { #[cfg(test)] mod tests { use super::*; - use std::fs::create_dir_all; - use serde_yaml::{Mapping, Value}; use crate::{matches::Match, util::tests::use_test_directory}; + use serde_yaml::{Mapping, Value}; + use std::fs::create_dir_all; fn create_match(yaml: &str) -> Result { let yaml_match: YAMLMatch = serde_yaml::from_str(yaml)?; @@ -388,7 +407,9 @@ mod tests { create_dir_all(&sub_dir).unwrap(); let base_file = match_dir.join("base.yml"); - std::fs::write(&base_file, r#" + std::fs::write( + &base_file, + r#" imports: - "sub/sub.yml" - "invalid/import.yml" # This should be discarded @@ -400,14 +421,16 @@ mod tests { matches: - trigger: "hello" replace: "world" - "#).unwrap(); + "#, + ) + .unwrap(); let sub_file = sub_dir.join("sub.yml"); - std::fs::write(&sub_file, "").unwrap(); - + std::fs::write(&sub_file, "").unwrap(); + let importer = YAMLImporter::new(); let group = importer.load_group(&base_file).unwrap(); - + let vars = vec![Variable { name: "var1".to_string(), var_type: "test".to_string(), @@ -418,23 +441,19 @@ mod tests { assert_eq!( group, MatchGroup { - imports: vec![ - sub_file.to_string_lossy().to_string(), - ], + imports: vec![sub_file.to_string_lossy().to_string(),], global_vars: vars, - matches: vec![ - Match { - cause: MatchCause::Trigger(TriggerCause { - triggers: vec!["hello".to_string()], - ..Default::default() - }), - effect: MatchEffect::Text(TextEffect { - replace: "world".to_string(), - ..Default::default() - }), + matches: vec![Match { + cause: MatchCause::Trigger(TriggerCause { + triggers: vec!["hello".to_string()], ..Default::default() - } - ], + }), + effect: MatchEffect::Text(TextEffect { + replace: "world".to_string(), + ..Default::default() + }), + ..Default::default() + }], } ) }); diff --git a/espanso-config/src/matches/group/loader/yaml/parse.rs b/espanso-config/src/matches/group/loader/yaml/parse.rs index 248fcfb..8d41ab2 100644 --- a/espanso-config/src/matches/group/loader/yaml/parse.rs +++ b/espanso-config/src/matches/group/loader/yaml/parse.rs @@ -1,3 +1,22 @@ +/* + * 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 std::{collections::HashMap, path::Path}; use anyhow::Result; @@ -98,4 +117,4 @@ pub struct YAMLVariable { fn default_params() -> Mapping { Mapping::new() -} \ No newline at end of file +} diff --git a/espanso-config/src/matches/group/mod.rs b/espanso-config/src/matches/group/mod.rs index 05be22d..5943a35 100644 --- a/espanso-config/src/matches/group/mod.rs +++ b/espanso-config/src/matches/group/mod.rs @@ -1,7 +1,24 @@ +/* + * 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 std::{ - path::{Path}, -}; +use std::path::Path; use super::{Match, Variable}; diff --git a/espanso-config/src/matches/group/path.rs b/espanso-config/src/matches/group/path.rs index 8143ec9..35fd40f 100644 --- a/espanso-config/src/matches/group/path.rs +++ b/espanso-config/src/matches/group/path.rs @@ -1,3 +1,22 @@ +/* + * 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 log::error; use std::path::{Path, PathBuf}; diff --git a/espanso-config/src/matches/mod.rs b/espanso-config/src/matches/mod.rs index 7fa4c7e..a4b4a42 100644 --- a/espanso-config/src/matches/mod.rs +++ b/espanso-config/src/matches/mod.rs @@ -1,3 +1,22 @@ +/* + * 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 serde_yaml::Mapping; use crate::counter::{next_id, StructId}; diff --git a/espanso-config/src/matches/store/default.rs b/espanso-config/src/matches/store/default.rs index 305d9ff..2be0eb1 100644 --- a/espanso-config/src/matches/store/default.rs +++ b/espanso-config/src/matches/store/default.rs @@ -1,3 +1,22 @@ +/* + * 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 log::error; use std::{ collections::{HashMap, HashSet}, @@ -629,7 +648,7 @@ mod tests { .cloned() .collect::>(), create_matches(&[ - ("hello", "world3"), // This appears only once, though it appears 2 times + ("hello", "world3"), // This appears only once, though it appears 2 times ("hello", "world2"), ("foo", "bar"), ("hello", "world"), diff --git a/espanso-config/src/matches/store/mod.rs b/espanso-config/src/matches/store/mod.rs index 2feb44c..2872160 100644 --- a/espanso-config/src/matches/store/mod.rs +++ b/espanso-config/src/matches/store/mod.rs @@ -1,3 +1,22 @@ +/* + * 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 super::{Match, Variable}; mod default; @@ -17,4 +36,4 @@ pub fn new() -> impl MatchStore { // TODO: here we can replace the DefaultMatchStore with a caching wrapper // that returns the same response for the given "paths" query default::DefaultMatchStore::new() -} \ No newline at end of file +} diff --git a/espanso-config/src/util.rs b/espanso-config/src/util.rs index 1ef0aa3..f283da8 100644 --- a/espanso-config/src/util.rs +++ b/espanso-config/src/util.rs @@ -1,3 +1,22 @@ +/* + * 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 . + */ + /// Check if the given string represents an empty YAML. /// In other words, it checks if the document is only composed /// of spaces and/or comments @@ -5,7 +24,7 @@ pub fn is_yaml_empty(yaml: &str) -> bool { for line in yaml.lines() { let trimmed_line = line.trim(); if !trimmed_line.starts_with("#") && !trimmed_line.is_empty() { - return false + return false; } } @@ -48,4 +67,4 @@ pub mod tests { fn is_yaml_empty_document_with_content() { assert_eq!(is_yaml_empty("\nfield: true\n"), false); } -} \ No newline at end of file +} diff --git a/espanso-detect/src/evdev/keymap.rs b/espanso-detect/src/evdev/keymap.rs index 8fc5ddb..bb2f266 100644 --- a/espanso-detect/src/evdev/keymap.rs +++ b/espanso-detect/src/evdev/keymap.rs @@ -10,7 +10,13 @@ use thiserror::Error; use crate::KeyboardConfig; -use super::{context::Context, ffi::{XKB_KEYMAP_COMPILE_NO_FLAGS, xkb_keymap, xkb_keymap_new_from_names, xkb_keymap_unref, xkb_rule_names}}; +use super::{ + context::Context, + ffi::{ + xkb_keymap, xkb_keymap_new_from_names, xkb_keymap_unref, xkb_rule_names, + XKB_KEYMAP_COMPILE_NO_FLAGS, + }, +}; pub struct Keymap { keymap: *mut xkb_keymap, @@ -18,17 +24,11 @@ pub struct Keymap { impl Keymap { pub fn new(context: &Context, rmlvo: Option) -> Result { - let names = rmlvo.map(|rmlvo| { - Self::generate_names(rmlvo) - }); + let names = rmlvo.map(|rmlvo| Self::generate_names(rmlvo)); let names_ptr = names.map_or(std::ptr::null(), |names| &names); let raw_keymap = unsafe { - xkb_keymap_new_from_names( - context.get_handle(), - names_ptr, - XKB_KEYMAP_COMPILE_NO_FLAGS, - ) + xkb_keymap_new_from_names(context.get_handle(), names_ptr, XKB_KEYMAP_COMPILE_NO_FLAGS) }; let keymap = scopeguard::guard(raw_keymap, |raw_keymap| unsafe { xkb_keymap_unref(raw_keymap); @@ -48,11 +48,21 @@ impl Keymap { } fn generate_names(rmlvo: KeyboardConfig) -> xkb_rule_names { - let rules = rmlvo.rules.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let model = rmlvo.model.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let layout = rmlvo.layout.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let variant = rmlvo.variant.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let options = rmlvo.options.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + let rules = rmlvo + .rules + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let model = rmlvo + .model + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let layout = rmlvo + .layout + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let variant = rmlvo + .variant + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let options = rmlvo + .options + .map(|s| CString::new(s).expect("unable to create CString for keymap")); xkb_rule_names { rules: rules.map_or(std::ptr::null(), |s| s.as_ptr()), diff --git a/espanso-detect/src/evdev/mod.rs b/espanso-detect/src/evdev/mod.rs index e87c87f..54814f8 100644 --- a/espanso-detect/src/evdev/mod.rs +++ b/espanso-detect/src/evdev/mod.rs @@ -36,10 +36,10 @@ use libc::{ use log::{error, trace}; use thiserror::Error; -use crate::{KeyboardConfig, Source, SourceCallback, SourceCreationOptions, event::Status::*}; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{Key::*, MouseButton, MouseEvent}; +use crate::{event::Status::*, KeyboardConfig, Source, SourceCallback, SourceCreationOptions}; use self::device::{DeviceError, RawInputEvent}; @@ -72,7 +72,8 @@ impl EVDEVSource { impl Source for EVDEVSource { fn initialize(&mut self) -> Result<()> { let context = Context::new().expect("unable to obtain xkb context"); - let keymap = Keymap::new(&context, self._keyboard_rmlvo.clone()).expect("unable to create xkb keymap"); + let keymap = + Keymap::new(&context, self._keyboard_rmlvo.clone()).expect("unable to create xkb keymap"); match get_devices(&keymap) { Ok(devices) => self.devices = devices, @@ -140,9 +141,7 @@ impl Source for EVDEVSource { if unsafe { *errno_ptr } == EINTR { continue; } else { - error!("Could not poll for events, {}", unsafe { - *errno_ptr - }); + error!("Could not poll for events, {}", unsafe { *errno_ptr }); return Err(EVDEVSourceError::Internal().into()); } } diff --git a/espanso-detect/src/lib.rs b/espanso-detect/src/lib.rs index 11e0927..0143cee 100644 --- a/espanso-detect/src/lib.rs +++ b/espanso-detect/src/lib.rs @@ -50,7 +50,7 @@ pub trait Source { pub struct SourceCreationOptions { // Only relevant in X11 Linux systems, use the EVDEV backend instead of X11. use_evdev: bool, - + // Can be used to overwrite the keymap configuration // used by espanso to inject key presses. evdev_keyboard_rmlvo: Option, @@ -107,4 +107,3 @@ pub fn get_source(options: SourceCreationOptions) -> Result> { info!("using EVDEVSource"); Ok(Box::new(evdev::EVDEVSource::new(options))) } - diff --git a/espanso-detect/src/mac/mod.rs b/espanso-detect/src/mac/mod.rs index 55e7f78..e5e5f50 100644 --- a/espanso-detect/src/mac/mod.rs +++ b/espanso-detect/src/mac/mod.rs @@ -31,10 +31,10 @@ use log::{error, trace, warn}; use anyhow::Result; use thiserror::Error; -use crate::{Source, SourceCallback, event::Status::*}; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{Key::*, MouseButton, MouseEvent}; +use crate::{event::Status::*, Source, SourceCallback}; const INPUT_EVENT_TYPE_KEYBOARD: i32 = 1; const INPUT_EVENT_TYPE_MOUSE: i32 = 2; @@ -97,8 +97,6 @@ impl CocoaSource { receiver: LazyCell::new(), } } - - } impl Source for CocoaSource { @@ -139,7 +137,7 @@ impl Source for CocoaSource { } } else { error!("Unable to start event loop if CocoaSource receiver is null"); - return Err(CocoaSourceError::Unknown().into()) + return Err(CocoaSourceError::Unknown().into()); } Ok(()) diff --git a/espanso-detect/src/win32/mod.rs b/espanso-detect/src/win32/mod.rs index 48ddd18..3378940 100644 --- a/espanso-detect/src/win32/mod.rs +++ b/espanso-detect/src/win32/mod.rs @@ -26,10 +26,10 @@ use widestring::U16CStr; use anyhow::Result; use thiserror::Error; -use crate::{Source, SourceCallback, event::Status::*}; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{Key::*, MouseButton, MouseEvent}; +use crate::{event::Status::*, Source, SourceCallback}; const INPUT_LEFT_VARIANT: i32 = 1; const INPUT_RIGHT_VARIANT: i32 = 2; @@ -116,7 +116,7 @@ impl Source for Win32Source { if self.callback.fill(event_callback).is_err() { error!("Unable to set Win32Source event callback"); - return Err(Win32SourceError::Unknown().into()) + return Err(Win32SourceError::Unknown().into()); } extern "C" fn callback(_self: *mut Win32Source, event: RawInputEvent) { @@ -134,7 +134,7 @@ impl Source for Win32Source { if error_code <= 0 { error!("Win32Source eventloop returned a negative error code"); - return Err(Win32SourceError::Unknown().into()) + return Err(Win32SourceError::Unknown().into()); } Ok(()) diff --git a/espanso-detect/src/x11/mod.rs b/espanso-detect/src/x11/mod.rs index b753b31..6648eb5 100644 --- a/espanso-detect/src/x11/mod.rs +++ b/espanso-detect/src/x11/mod.rs @@ -25,10 +25,10 @@ use log::{error, trace, warn}; use anyhow::Result; use thiserror::Error; -use crate::{Source, SourceCallback, event::Status::*}; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{Key::*, MouseButton, MouseEvent}; +use crate::{event::Status::*, Source, SourceCallback}; const INPUT_EVENT_TYPE_KEYBOARD: i32 = 1; const INPUT_EVENT_TYPE_MOUSE: i32 = 2; @@ -87,8 +87,6 @@ impl X11Source { pub fn is_compatible() -> bool { unsafe { detect_check_x11() != 0 } } - - } impl Source for X11Source { diff --git a/espanso-inject/src/evdev/ffi.rs b/espanso-inject/src/evdev/ffi.rs index 8391306..2fbdbfc 100644 --- a/espanso-inject/src/evdev/ffi.rs +++ b/espanso-inject/src/evdev/ffi.rs @@ -81,4 +81,4 @@ extern "C" { pub fn setup_uinput_device(fd: c_int) -> c_int; pub fn uinput_emit(fd: c_int, code: c_uint, pressed: c_int); -} \ No newline at end of file +} diff --git a/espanso-inject/src/evdev/keymap.rs b/espanso-inject/src/evdev/keymap.rs index b652bdd..437b9bc 100644 --- a/espanso-inject/src/evdev/keymap.rs +++ b/espanso-inject/src/evdev/keymap.rs @@ -24,18 +24,12 @@ pub struct Keymap { impl Keymap { pub fn new(context: &Context, rmlvo: Option) -> Result { - let names = rmlvo.map(|rmlvo| { - Self::generate_names(rmlvo) - }); + let names = rmlvo.map(|rmlvo| Self::generate_names(rmlvo)); let names_ptr = names.map_or(std::ptr::null(), |names| &names); let raw_keymap = unsafe { - xkb_keymap_new_from_names( - context.get_handle(), - names_ptr, - XKB_KEYMAP_COMPILE_NO_FLAGS, - ) + xkb_keymap_new_from_names(context.get_handle(), names_ptr, XKB_KEYMAP_COMPILE_NO_FLAGS) }; let keymap = scopeguard::guard(raw_keymap, |raw_keymap| unsafe { xkb_keymap_unref(raw_keymap); @@ -55,11 +49,21 @@ impl Keymap { } fn generate_names(rmlvo: KeyboardConfig) -> xkb_rule_names { - let rules = rmlvo.rules.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let model = rmlvo.model.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let layout = rmlvo.layout.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let variant = rmlvo.variant.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); - let options = rmlvo.options.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + let rules = rmlvo + .rules + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let model = rmlvo + .model + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let layout = rmlvo + .layout + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let variant = rmlvo + .variant + .map(|s| CString::new(s).expect("unable to create CString for keymap")); + let options = rmlvo + .options + .map(|s| CString::new(s).expect("unable to create CString for keymap")); xkb_rule_names { rules: rules.map_or(std::ptr::null(), |s| s.as_ptr()), diff --git a/espanso-inject/src/evdev/mod.rs b/espanso-inject/src/evdev/mod.rs index d66fb18..0164294 100644 --- a/espanso-inject/src/evdev/mod.rs +++ b/espanso-inject/src/evdev/mod.rs @@ -25,7 +25,7 @@ mod uinput; use std::{ collections::{HashMap, HashSet}, - ffi::{CString}, + ffi::CString, }; use context::Context; @@ -34,10 +34,7 @@ use log::error; use std::iter::FromIterator; use uinput::UInputDevice; -use crate::{ - linux::raw_keys::{convert_to_sym_array}, - InjectorCreationOptions, -}; +use crate::{linux::raw_keys::convert_to_sym_array, InjectorCreationOptions}; use anyhow::Result; use itertools::Itertools; use thiserror::Error; @@ -120,7 +117,8 @@ impl EVDEVInjector { } let context = Context::new().expect("unable to obtain xkb context"); - let keymap = Keymap::new(&context, options.evdev_keyboard_rmlvo).expect("unable to create xkb keymap"); + let keymap = + Keymap::new(&context, options.evdev_keyboard_rmlvo).expect("unable to create xkb keymap"); let (char_map, sym_map) = Self::generate_maps(&modifiers, max_modifier_combination_len, &keymap)?; @@ -294,7 +292,7 @@ impl Injector for EVDEVInjector { // Compute all the key record sequence first to make sure a mapping is available let syms = convert_to_sym_array(keys)?; let records = self.convert_to_record_array(&syms)?; - + let delay_us = options.delay as u32 * 1000; // Convert to micro seconds // First press the keys diff --git a/espanso-inject/src/evdev/state.rs b/espanso-inject/src/evdev/state.rs index 0eee303..5a962b1 100644 --- a/espanso-inject/src/evdev/state.rs +++ b/espanso-inject/src/evdev/state.rs @@ -8,7 +8,13 @@ use scopeguard::ScopeGuard; use anyhow::Result; use thiserror::Error; -use super::{ffi::{xkb_state, xkb_state_key_get_one_sym, xkb_state_key_get_utf8, xkb_state_new, xkb_state_unref, xkb_state_update_key}, keymap::Keymap}; +use super::{ + ffi::{ + xkb_state, xkb_state_key_get_one_sym, xkb_state_key_get_utf8, xkb_state_new, xkb_state_unref, + xkb_state_update_key, + }, + keymap::Keymap, +}; pub struct State { state: *mut xkb_state, diff --git a/espanso-inject/src/keys.rs b/espanso-inject/src/keys.rs index 987f6e5..97355b5 100644 --- a/espanso-inject/src/keys.rs +++ b/espanso-inject/src/keys.rs @@ -356,4 +356,4 @@ mod tests { assert!(Key::parse("INVALID").is_none()); assert!(Key::parse("RAW(a)").is_none()); } -} \ No newline at end of file +} diff --git a/espanso-inject/src/lib.rs b/espanso-inject/src/lib.rs index 508e12e..e1fa991 100644 --- a/espanso-inject/src/lib.rs +++ b/espanso-inject/src/lib.rs @@ -86,7 +86,7 @@ pub struct InjectorCreationOptions { // Only relevant in X11 Linux systems, use the EVDEV backend instead of X11. use_evdev: bool, - // Overwrite the list of modifiers to be scanned when + // Overwrite the list of modifiers to be scanned when // populating the evdev injector lookup maps evdev_modifiers: Option>, @@ -151,4 +151,3 @@ pub fn get_injector(options: InjectorCreationOptions) -> Result. */ -pub mod raw_keys; \ No newline at end of file +pub mod raw_keys; diff --git a/espanso-inject/src/linux/raw_keys.rs b/espanso-inject/src/linux/raw_keys.rs index 26db27d..e586527 100644 --- a/espanso-inject/src/linux/raw_keys.rs +++ b/espanso-inject/src/linux/raw_keys.rs @@ -143,4 +143,4 @@ pub fn convert_to_sym_array(keys: &[Key]) -> Result> { pub enum LinuxRawKeyError { #[error("missing mapping for key `{0}`")] MappingFailure(Key), -} \ No newline at end of file +} diff --git a/espanso-inject/src/mac/mod.rs b/espanso-inject/src/mac/mod.rs index d4776f7..2bb12d7 100644 --- a/espanso-inject/src/mac/mod.rs +++ b/espanso-inject/src/mac/mod.rs @@ -27,7 +27,7 @@ use raw_keys::convert_key_to_vkey; use anyhow::Result; use thiserror::Error; -use crate::{InjectionOptions, Injector, keys}; +use crate::{keys, InjectionOptions, Injector}; #[allow(improper_ctypes)] #[link(name = "espansoinject", kind = "static")] @@ -72,7 +72,11 @@ impl Injector for MacInjector { let virtual_keys = Self::convert_to_vk_array(keys)?; unsafe { - inject_separate_vkeys(virtual_keys.as_ptr(), virtual_keys.len() as i32, options.delay); + inject_separate_vkeys( + virtual_keys.as_ptr(), + virtual_keys.len() as i32, + options.delay, + ); } Ok(()) @@ -82,7 +86,11 @@ impl Injector for MacInjector { let virtual_keys = Self::convert_to_vk_array(keys)?; unsafe { - inject_vkeys_combination(virtual_keys.as_ptr(), virtual_keys.len() as i32, options.delay); + inject_vkeys_combination( + virtual_keys.as_ptr(), + virtual_keys.len() as i32, + options.delay, + ); } Ok(()) diff --git a/espanso-inject/src/win32/mod.rs b/espanso-inject/src/win32/mod.rs index d6b0772..45c7d03 100644 --- a/espanso-inject/src/win32/mod.rs +++ b/espanso-inject/src/win32/mod.rs @@ -19,13 +19,13 @@ mod raw_keys; -use log::{error}; +use log::error; use raw_keys::convert_key_to_vkey; use anyhow::Result; use thiserror::Error; -use crate::{InjectionOptions, Injector, keys}; +use crate::{keys, InjectionOptions, Injector}; #[allow(improper_ctypes)] #[link(name = "espansoinject", kind = "static")] @@ -77,7 +77,11 @@ impl Injector for Win32Injector { } } else { unsafe { - inject_separate_vkeys_with_delay(virtual_keys.as_ptr(), virtual_keys.len() as i32, options.delay); + inject_separate_vkeys_with_delay( + virtual_keys.as_ptr(), + virtual_keys.len() as i32, + options.delay, + ); } } @@ -93,7 +97,11 @@ impl Injector for Win32Injector { } } else { unsafe { - inject_vkeys_combination_with_delay(virtual_keys.as_ptr(), virtual_keys.len() as i32, options.delay); + inject_vkeys_combination_with_delay( + virtual_keys.as_ptr(), + virtual_keys.len() as i32, + options.delay, + ); } } @@ -113,6 +121,9 @@ mod tests { #[test] fn convert_raw_to_virtual_key_array() { - assert_eq!(Win32Injector::convert_to_vk_array(&[keys::Key::Alt, keys::Key::V]).unwrap(), vec![0x12, 0x56]); + assert_eq!( + Win32Injector::convert_to_vk_array(&[keys::Key::Alt, keys::Key::V]).unwrap(), + vec![0x12, 0x56] + ); } -} \ No newline at end of file +} diff --git a/espanso-inject/src/x11/mod.rs b/espanso-inject/src/x11/mod.rs index 6f53f15..0d8ba82 100644 --- a/espanso-inject/src/x11/mod.rs +++ b/espanso-inject/src/x11/mod.rs @@ -26,11 +26,15 @@ use std::{ slice, }; -use ffi::{Display, KeyCode, KeyPress, KeyRelease, KeySym, Window, XCloseDisplay, XDefaultRootWindow, XFlush, XFreeModifiermap, XGetInputFocus, XGetModifierMapping, XKeyEvent, XLookupString, XQueryKeymap, XSendEvent, XSync, XTestFakeKeyEvent}; +use ffi::{ + Display, KeyCode, KeyPress, KeyRelease, KeySym, Window, XCloseDisplay, XDefaultRootWindow, + XFlush, XFreeModifiermap, XGetInputFocus, XGetModifierMapping, XKeyEvent, XLookupString, + XQueryKeymap, XSendEvent, XSync, XTestFakeKeyEvent, +}; use log::error; +use crate::linux::raw_keys::convert_to_sym_array; use anyhow::Result; -use crate::linux::raw_keys::{convert_to_sym_array}; use thiserror::Error; use crate::{keys, InjectionOptions, Injector}; @@ -174,7 +178,6 @@ impl X11Injector { modifiers.modifiermap, (8 * modifiers.max_keypermod) as usize, ) - }; let keycode = modifier_map[(mod_index * modifiers.max_keypermod + mod_key) as usize]; if keycode != 0 { @@ -355,7 +358,7 @@ impl Injector for X11Injector { fn send_keys(&self, keys: &[keys::Key], options: InjectionOptions) -> Result<()> { let focused_window = self.get_focused_window(); - + // Compute all the key record sequence first to make sure a mapping is available let syms = convert_to_sym_array(keys)?; let records = self.convert_to_record_array(&syms)?; @@ -385,7 +388,7 @@ impl Injector for X11Injector { // Compute all the key record sequence first to make sure a mapping is available let syms = convert_to_sym_array(keys)?; let records = self.convert_to_record_array(&syms)?; - + // Render the correct modifier mask for the given sequence let records = self.render_key_combination(&records); @@ -427,4 +430,4 @@ pub enum X11InjectorError { #[error("missing record mapping for sym `{0}`")] SymMappingFailure(u64), -} \ No newline at end of file +} diff --git a/espanso-ipc/src/lib.rs b/espanso-ipc/src/lib.rs index 4fed83d..6a322e4 100644 --- a/espanso-ipc/src/lib.rs +++ b/espanso-ipc/src/lib.rs @@ -17,11 +17,11 @@ * along with espanso. If not, see . */ -use std::path::Path; use anyhow::Result; -use serde::{Serialize, de::DeserializeOwned}; +use crossbeam::channel::{unbounded, Receiver}; +use serde::{de::DeserializeOwned, Serialize}; +use std::path::Path; use thiserror::Error; -use crossbeam::channel::{Receiver, unbounded}; #[cfg(target_os = "windows")] pub mod windows; @@ -39,7 +39,10 @@ pub trait IPCClient { } #[cfg(not(target_os = "windows"))] -pub fn server(id: &str, parent_dir: &Path) -> Result<(impl IPCServer, Receiver)> { +pub fn server( + id: &str, + parent_dir: &Path, +) -> Result<(impl IPCServer, Receiver)> { let (sender, receiver) = unbounded(); let server = unix::UnixIPCServer::new(id, parent_dir, sender)?; Ok((server, receiver)) @@ -52,7 +55,10 @@ pub fn client(id: &str, parent_dir: &Path) -> Result(id: &str, _: &Path) -> Result<(impl IPCServer, Receiver)> { +pub fn server( + id: &str, + _: &Path, +) -> Result<(impl IPCServer, Receiver)> { let (sender, receiver) = unbounded(); let server = windows::WinIPCServer::new(id, sender)?; Ok((server, receiver)) @@ -76,7 +82,7 @@ pub enum IPCServerError { #[cfg(test)] mod tests { use super::*; - use serde::{Serialize, Deserialize}; + use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] enum Event { @@ -93,10 +99,10 @@ mod tests { // TODO: avoid delay and change the IPC code so that we can wait for the IPC //std::thread::sleep(std::time::Duration::from_secs(1)); - + let client = client::("testespansoipc", &std::env::temp_dir()).unwrap(); client.send(Event::Foo("hello".to_string())).unwrap(); - + let event = receiver.recv().unwrap(); assert!(matches!(event, Event::Foo(x) if x == "hello")); @@ -108,4 +114,4 @@ mod tests { let client = client::("testespansoipc", &std::env::temp_dir()).unwrap(); assert!(client.send(Event::Foo("hello".to_string())).is_err()); } -} \ No newline at end of file +} diff --git a/espanso-ipc/src/windows.rs b/espanso-ipc/src/windows.rs index 78bb699..6670743 100644 --- a/espanso-ipc/src/windows.rs +++ b/espanso-ipc/src/windows.rs @@ -22,9 +22,7 @@ use crossbeam::channel::Sender; use log::{error, info}; use named_pipe::{PipeClient, PipeOptions}; use serde::{de::DeserializeOwned, Serialize}; -use std::{ - io::{BufReader, Read, Write}, -}; +use std::io::{BufReader, Read, Write}; use crate::{IPCClient, IPCServer, IPCServerError}; @@ -41,10 +39,7 @@ impl WinIPCServer { let options = PipeOptions::new(&pipe_name); - info!( - "binded to named pipe: {}", - pipe_name - ); + info!("binded to named pipe: {}", pipe_name); Ok(Self { options, sender }) } @@ -116,4 +111,3 @@ impl IPCClient for WinIPCClient { Ok(()) } } - diff --git a/espanso-ui/src/lib.rs b/espanso-ui/src/lib.rs index 197d9eb..9a9babb 100644 --- a/espanso-ui/src/lib.rs +++ b/espanso-ui/src/lib.rs @@ -1,5 +1,5 @@ -use icons::TrayIcon; use anyhow::Result; +use icons::TrayIcon; use thiserror::Error; pub mod event; @@ -48,14 +48,15 @@ pub fn create_ui(options: UIOptions) -> Result<(Box, Box Result<(Box, Box)> { +pub fn create_ui(options: UIOptions) -> Result<(Box, Box)> { let (remote, eventloop) = mac::create(mac::MacUIOptions { show_icon: options.show_icon, icon_paths: &options.icon_paths, @@ -66,7 +67,9 @@ pub fn create_ui(options: UIOptions) -> Result<(Box, Box Result<(Box, Box)> { let (remote, eventloop) = linux::create(linux::LinuxUIOptions { - notification_icon_path: options.notification_icon_path.ok_or_else(|| UIError::MissingOption("notification icon".to_string()))?, + notification_icon_path: options + .notification_icon_path + .ok_or_else(|| UIError::MissingOption("notification icon".to_string()))?, }); Ok((Box::new(remote), Box::new(eventloop))) } @@ -75,4 +78,4 @@ pub fn create_ui(options: UIOptions) -> Result<(Box, Box) -> Self { Self { icon_indexes } - } + } } impl UIRemote for MacRemote { @@ -242,4 +240,4 @@ impl From for Option { pub enum MacUIError { #[error("internal error")] InternalError(), -} \ No newline at end of file +} diff --git a/espanso-ui/src/win32/mod.rs b/espanso-ui/src/win32/mod.rs index d802427..ddc3c22 100644 --- a/espanso-ui/src/win32/mod.rs +++ b/espanso-ui/src/win32/mod.rs @@ -29,13 +29,13 @@ use std::{ thread::ThreadId, }; +use anyhow::Result; use lazycell::LazyCell; use log::{error, trace}; -use widestring::WideCString; -use anyhow::Result; use thiserror::Error; +use widestring::WideCString; -use crate::{UIEventCallback, UIEventLoop, UIRemote, event::UIEvent, icons::TrayIcon, menu::Menu}; +use crate::{event::UIEvent, icons::TrayIcon, menu::Menu, UIEventCallback, UIEventLoop, UIRemote}; // IMPORTANT: if you change these, also edit the native.h file. const MAX_FILE_PATH: usize = 260; @@ -154,8 +154,7 @@ impl UIEventLoop for Win32EventLoop { let mut icon_paths: [[u16; MAX_FILE_PATH]; MAX_ICON_COUNT] = [[0; MAX_FILE_PATH]; MAX_ICON_COUNT]; for (i, icon_path) in icon_paths.iter_mut().enumerate().take(self.icons.len()) { - let wide_path = - WideCString::from_str(&self.icons[i])?; + let wide_path = WideCString::from_str(&self.icons[i])?; let len = min(wide_path.len(), MAX_FILE_PATH - 1); icon_path[0..len].clone_from_slice(&wide_path.as_slice()[..len]); } @@ -178,11 +177,31 @@ impl UIEventLoop for Win32EventLoop { if handle.is_null() { return match error_code { - -1 => Err(Win32UIError::EventLoopInitError("Unable to initialize Win32EventLoop, error registering window class".to_string()).into()), - -2 => Err(Win32UIError::EventLoopInitError("Unable to initialize Win32EventLoop, error creating window".to_string()).into()), - -3 => Err(Win32UIError::EventLoopInitError("Unable to initialize Win32EventLoop, initializing notifications".to_string()).into()), - _ => Err(Win32UIError::EventLoopInitError("Unable to initialize Win32EventLoop, unknown error".to_string()).into()), - } + -1 => Err( + Win32UIError::EventLoopInitError( + "Unable to initialize Win32EventLoop, error registering window class".to_string(), + ) + .into(), + ), + -2 => Err( + Win32UIError::EventLoopInitError( + "Unable to initialize Win32EventLoop, error creating window".to_string(), + ) + .into(), + ), + -3 => Err( + Win32UIError::EventLoopInitError( + "Unable to initialize Win32EventLoop, initializing notifications".to_string(), + ) + .into(), + ), + _ => Err( + Win32UIError::EventLoopInitError( + "Unable to initialize Win32EventLoop, unknown error".to_string(), + ) + .into(), + ), + }; } self.handle.store(handle, Ordering::Release); @@ -192,7 +211,7 @@ impl UIEventLoop for Win32EventLoop { ._init_thread_id .fill(std::thread::current().id()) .expect("Unable to set initialization thread id"); - + Ok(()) } @@ -207,12 +226,12 @@ impl UIEventLoop for Win32EventLoop { let window_handle = self.handle.load(Ordering::Acquire); if window_handle.is_null() { error!("Attempt to run Win32EventLoop on a null window handle"); - return Err(Win32UIError::InvalidHandle().into()) + return Err(Win32UIError::InvalidHandle().into()); } if self._event_callback.fill(event_callback).is_err() { error!("Unable to set Win32EventLoop callback"); - return Err(Win32UIError::InternalError().into()) + return Err(Win32UIError::InternalError().into()); } extern "C" fn callback(_self: *mut Win32EventLoop, event: RawUIEvent) { @@ -230,7 +249,7 @@ impl UIEventLoop for Win32EventLoop { if error_code <= 0 { error!("Win32EventLoop exited with <= 0 code"); - return Err(Win32UIError::InternalError().into()) + return Err(Win32UIError::InternalError().into()); } Ok(()) diff --git a/espanso/src/main.rs b/espanso/src/main.rs index 37157bf..232ea62 100644 --- a/espanso/src/main.rs +++ b/espanso/src/main.rs @@ -1,7 +1,10 @@ use std::time::Duration; -use espanso_detect::{event::{InputEvent, Status}, get_source}; -use espanso_inject::{get_injector, Injector, keys}; +use espanso_detect::{ + event::{InputEvent, Status}, + get_source, +}; +use espanso_inject::{get_injector, keys, Injector}; use espanso_ui::{event::UIEvent::*, icons::TrayIcon, menu::*}; use simplelog::{CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode}; @@ -49,9 +52,12 @@ fn main() { // icon_paths: &icon_paths, // }); let (remote, mut eventloop) = espanso_ui::create_ui(espanso_ui::UIOptions { - notification_icon_path: Some(r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png".to_string()), + notification_icon_path: Some( + r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png".to_string(), + ), ..Default::default() - }).unwrap(); + }) + .unwrap(); eventloop.initialize().unwrap(); @@ -59,21 +65,25 @@ fn main() { let injector = get_injector(Default::default()).unwrap(); let mut source = get_source(Default::default()).unwrap(); source.initialize().unwrap(); - source.eventloop(Box::new(move |event: InputEvent| { - println!("ev {:?}", event); - match event { - InputEvent::Mouse(_) => {} - InputEvent::Keyboard(evt) => { - if evt.key == espanso_detect::event::Key::Escape && evt.status == Status::Released { - //remote.update_tray_icon(espanso_ui::icons::TrayIcon::Disabled); - //remote.show_notification("Espanso is running!"); - injector.send_string("Hey guys! @", Default::default()).expect("error"); - //std::thread::sleep(std::time::Duration::from_secs(2)); - //injector.send_key_combination(&[keys::Key::Control, keys::Key::V], Default::default()).unwrap(); + source + .eventloop(Box::new(move |event: InputEvent| { + println!("ev {:?}", event); + match event { + InputEvent::Mouse(_) => {} + InputEvent::Keyboard(evt) => { + if evt.key == espanso_detect::event::Key::Escape && evt.status == Status::Released { + //remote.update_tray_icon(espanso_ui::icons::TrayIcon::Disabled); + //remote.show_notification("Espanso is running!"); + injector + .send_string("Hey guys! @", Default::default()) + .expect("error"); + //std::thread::sleep(std::time::Duration::from_secs(2)); + //injector.send_key_combination(&[keys::Key::Control, keys::Key::V], Default::default()).unwrap(); + } } } - } - })).unwrap(); + })) + .unwrap(); }); eventloop.run(Box::new(move |event| {