Initial draft of config parsing
This commit is contained in:
parent
79a1b85769
commit
e26a04de67
52
Cargo.lock
generated
52
Cargo.lock
generated
|
@ -190,6 +190,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dtoa"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.6.1"
|
version = "1.6.1"
|
||||||
|
@ -212,6 +218,7 @@ dependencies = [
|
||||||
name = "espanso"
|
name = "espanso"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"espanso-config",
|
||||||
"espanso-detect",
|
"espanso-detect",
|
||||||
"espanso-inject",
|
"espanso-inject",
|
||||||
"espanso-ui",
|
"espanso-ui",
|
||||||
|
@ -219,6 +226,18 @@ dependencies = [
|
||||||
"simplelog",
|
"simplelog",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "espanso-config"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"glob",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_yaml",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "espanso-detect"
|
name = "espanso-detect"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -292,6 +311,12 @@ dependencies = [
|
||||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -343,6 +368,12 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked-hash-map"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
@ -588,6 +619,18 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_yaml"
|
||||||
|
version = "0.8.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23"
|
||||||
|
dependencies = [
|
||||||
|
"dtoa",
|
||||||
|
"linked-hash-map",
|
||||||
|
"serde",
|
||||||
|
"yaml-rust",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simplelog"
|
name = "simplelog"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -792,3 +835,12 @@ checksum = "e1945e12e16b951721d7976520b0832496ef79c31602c7a29d950de79ba74621"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yaml-rust"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||||
|
dependencies = [
|
||||||
|
"linked-hash-map",
|
||||||
|
]
|
||||||
|
|
|
@ -6,4 +6,5 @@ members = [
|
||||||
"espanso-ui",
|
"espanso-ui",
|
||||||
"espanso-inject",
|
"espanso-inject",
|
||||||
"espanso-ipc",
|
"espanso-ipc",
|
||||||
|
"espanso-config",
|
||||||
]
|
]
|
13
espanso-config/Cargo.toml
Normal file
13
espanso-config/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "espanso-config"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Federico Terzi <federico-terzi@users.noreply.github.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
log = "0.4.14"
|
||||||
|
anyhow = "1.0.38"
|
||||||
|
thiserror = "1.0.23"
|
||||||
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
|
serde_yaml = "0.8.17"
|
||||||
|
glob = "0.3.0"
|
15
espanso-config/src/config/mod.rs
Normal file
15
espanso-config/src/config/mod.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
|
||||||
|
mod yaml;
|
||||||
|
mod path;
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub label: Option<String>,
|
||||||
|
//pub backend:
|
||||||
|
pub match_files: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
}
|
34
espanso-config/src/config/path.rs
Normal file
34
espanso-config/src/config/path.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use glob::glob;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
// TODO: test
|
||||||
|
pub fn calculate_paths<'a>(glob_patterns: impl Iterator<Item = &'a String>) -> HashSet<String> {
|
||||||
|
let mut path_set = HashSet::new();
|
||||||
|
for glob_pattern in glob_patterns {
|
||||||
|
let entries = glob(glob_pattern);
|
||||||
|
match entries {
|
||||||
|
Ok(paths) => {
|
||||||
|
for path in paths {
|
||||||
|
match path {
|
||||||
|
Ok(path) => {
|
||||||
|
path_set.insert(path.to_string_lossy().to_string());
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!("glob error when processing pattern: {}, with error: {}", glob_pattern, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
error!(
|
||||||
|
"unable to calculate glob from pattern: {}, with error: {}",
|
||||||
|
glob_pattern, err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path_set
|
||||||
|
}
|
89
espanso-config/src/config/yaml.rs
Normal file
89
espanso-config/src/config/yaml.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
use super::path::calculate_paths;
|
||||||
|
|
||||||
|
const STANDARD_INCLUDES: &[&str] = &["match/**/*.yml"];
|
||||||
|
const STANDARD_EXCLUDES: &[&str] = &["match/**/_*.yml"];
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct YAMLConfig {
|
||||||
|
pub label: Option<String>,
|
||||||
|
|
||||||
|
pub includes: Option<Vec<String>>,
|
||||||
|
|
||||||
|
pub excludes: Option<Vec<String>>,
|
||||||
|
|
||||||
|
pub extra_includes: Option<Vec<String>>,
|
||||||
|
|
||||||
|
pub extra_excludes: Option<Vec<String>>,
|
||||||
|
|
||||||
|
pub use_standard_includes: bool,
|
||||||
|
|
||||||
|
// Filters
|
||||||
|
|
||||||
|
pub filter_title: Option<String>,
|
||||||
|
pub filter_class: Option<String>,
|
||||||
|
pub filter_exec: Option<String>,
|
||||||
|
pub filter_os: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl YAMLConfig {
|
||||||
|
// TODO test
|
||||||
|
pub fn aggregate_includes(&self) -> HashSet<String> {
|
||||||
|
let mut includes = HashSet::new();
|
||||||
|
|
||||||
|
if self.use_standard_includes {
|
||||||
|
STANDARD_INCLUDES.iter().for_each(|include| { includes.insert(include.to_string()); })
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(yaml_includes) = self.includes.as_ref() {
|
||||||
|
yaml_includes.iter().for_each(|include| { includes.insert(include.to_string()); })
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(extra_includes) = self.extra_includes.as_ref() {
|
||||||
|
extra_includes.iter().for_each(|include| { includes.insert(include.to_string()); })
|
||||||
|
}
|
||||||
|
|
||||||
|
includes
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO test
|
||||||
|
pub fn aggregate_excludes(&self) -> HashSet<String> {
|
||||||
|
let mut excludes = HashSet::new();
|
||||||
|
|
||||||
|
if self.use_standard_includes {
|
||||||
|
STANDARD_EXCLUDES.iter().for_each(|exclude| { excludes.insert(exclude.to_string()); })
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(yaml_excludes) = self.excludes.as_ref() {
|
||||||
|
yaml_excludes.iter().for_each(|exclude| { excludes.insert(exclude.to_string()); })
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(extra_excludes) = self.extra_excludes.as_ref() {
|
||||||
|
extra_excludes.iter().for_each(|exclude| { excludes.insert(exclude.to_string()); })
|
||||||
|
}
|
||||||
|
|
||||||
|
excludes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: convert to TryFrom (check the matches section for an example)
|
||||||
|
impl From<YAMLConfig> for super::Config {
|
||||||
|
// TODO: test
|
||||||
|
fn from(yaml_config: YAMLConfig) -> Self {
|
||||||
|
let includes = yaml_config.aggregate_includes();
|
||||||
|
let excludes = yaml_config.aggregate_excludes();
|
||||||
|
|
||||||
|
// Extract the paths
|
||||||
|
let exclude_paths = calculate_paths(excludes.iter());
|
||||||
|
let include_paths = calculate_paths(includes.iter());
|
||||||
|
|
||||||
|
let match_files: Vec<String> = Vec::from_iter(include_paths.difference(&exclude_paths).cloned());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
label: yaml_config.label,
|
||||||
|
match_files,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
espanso-config/src/lib.rs
Normal file
58
espanso-config/src/lib.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
mod matches;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
|
use thiserror::Error;
|
||||||
|
use config::Config;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct ConfigSet {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigSet {
|
||||||
|
//fn active(&self, app: AppProperties) -> &'a Config {
|
||||||
|
// TODO: using the app properties, check if any of the sub configs match or not. If not, return the default
|
||||||
|
// Here a RegexSet might be very useful to efficiently match them.
|
||||||
|
//}
|
||||||
|
|
||||||
|
//fn default(&self) -> &'a Config {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AppProperties<'a> {
|
||||||
|
pub title: Option<&'a str>,
|
||||||
|
pub class: Option<&'a str>,
|
||||||
|
pub exec: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn todo() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
85
espanso-config/src/matches/mod.rs
Normal file
85
espanso-config/src/matches/mod.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
use serde_yaml::Mapping;
|
||||||
|
|
||||||
|
mod yaml;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Match {
|
||||||
|
cause: MatchCause,
|
||||||
|
effect: MatchEffect,
|
||||||
|
|
||||||
|
// Metadata
|
||||||
|
label: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Match {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
cause: MatchCause::None,
|
||||||
|
effect: MatchEffect::None,
|
||||||
|
label: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Causes
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum MatchCause {
|
||||||
|
None,
|
||||||
|
Trigger(TriggerCause),
|
||||||
|
// TODO: regex
|
||||||
|
// TODO: shortcut
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct TriggerCause {
|
||||||
|
pub triggers: Vec<String>,
|
||||||
|
|
||||||
|
pub left_word: bool,
|
||||||
|
pub right_word: bool,
|
||||||
|
|
||||||
|
pub propagate_case: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TriggerCause {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
triggers: Vec::new(),
|
||||||
|
left_word: false,
|
||||||
|
right_word: false,
|
||||||
|
propagate_case: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Effects
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum MatchEffect {
|
||||||
|
None,
|
||||||
|
Text(TextEffect),
|
||||||
|
// TODO: image
|
||||||
|
// TODO: rich text
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct TextEffect {
|
||||||
|
pub replace: String,
|
||||||
|
pub vars: Vec<Variable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TextEffect {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
replace: String::new(),
|
||||||
|
vars: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct Variable {
|
||||||
|
pub name: String,
|
||||||
|
pub var_type: String,
|
||||||
|
pub params: Mapping,
|
||||||
|
}
|
384
espanso-config/src/matches/yaml.rs
Normal file
384
espanso-config/src/matches/yaml.rs
Normal file
|
@ -0,0 +1,384 @@
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
convert::{TryFrom, TryInto},
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_yaml::{Mapping, Value};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use super::{MatchCause, MatchEffect, TextEffect, TriggerCause, Variable};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
struct YAMLMatch {
|
||||||
|
#[serde(default)]
|
||||||
|
pub trigger: Option<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub triggers: Option<Vec<String>>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub replace: Option<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub image_path: Option<String>, // TODO: map
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub form: Option<String>, // TODO: map
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub form_fields: Option<HashMap<String, Value>>, // TODO: map
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub vars: Option<Vec<YAMLVariable>>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub word: Option<bool>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub left_word: Option<bool>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub right_word: Option<bool>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub propagate_case: Option<bool>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub force_clipboard: Option<bool>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub markdown: Option<String>, // TODO: map
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub paragraph: Option<bool>, // TODO: map
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub html: Option<String>, // TODO: map
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
|
pub struct YAMLVariable {
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub var_type: String,
|
||||||
|
|
||||||
|
#[serde(default = "default_params")]
|
||||||
|
pub params: Mapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_params() -> Mapping {
|
||||||
|
Mapping::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<YAMLMatch> for super::Match {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
// TODO: test
|
||||||
|
fn try_from(yaml_match: YAMLMatch) -> Result<Self, Self::Error> {
|
||||||
|
let triggers = if let Some(trigger) = yaml_match.trigger {
|
||||||
|
Some(vec![trigger])
|
||||||
|
} else if let Some(triggers) = yaml_match.triggers {
|
||||||
|
Some(triggers)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let cause = if let Some(triggers) = triggers {
|
||||||
|
MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers,
|
||||||
|
left_word: yaml_match
|
||||||
|
.left_word
|
||||||
|
.or(yaml_match.word)
|
||||||
|
.unwrap_or(TriggerCause::default().left_word),
|
||||||
|
right_word: yaml_match
|
||||||
|
.right_word
|
||||||
|
.or(yaml_match.word)
|
||||||
|
.unwrap_or(TriggerCause::default().right_word),
|
||||||
|
propagate_case: yaml_match
|
||||||
|
.propagate_case
|
||||||
|
.unwrap_or(TriggerCause::default().propagate_case),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
MatchCause::None
|
||||||
|
};
|
||||||
|
|
||||||
|
let effect = if let Some(replace) = yaml_match.replace {
|
||||||
|
let vars: Result<Vec<Variable>> = yaml_match
|
||||||
|
.vars
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.map(|var| var.try_into())
|
||||||
|
.collect();
|
||||||
|
MatchEffect::Text(TextEffect {
|
||||||
|
replace,
|
||||||
|
vars: vars?,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
MatchEffect::None
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: log none match effect
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
cause,
|
||||||
|
effect,
|
||||||
|
label: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<YAMLVariable> for super::Variable {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
// TODO: test
|
||||||
|
fn try_from(yaml_var: YAMLVariable) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
name: yaml_var.name,
|
||||||
|
var_type: yaml_var.var_type,
|
||||||
|
params: yaml_var.params,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum YAMLConversionError {
|
||||||
|
// TODO
|
||||||
|
//#[error("unknown data store error")]
|
||||||
|
//Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::matches::Match;
|
||||||
|
|
||||||
|
fn create_match(yaml: &str) -> Result<Match> {
|
||||||
|
let yaml_match: YAMLMatch = serde_yaml::from_str(yaml)?;
|
||||||
|
let m: Match = yaml_match.try_into()?;
|
||||||
|
Ok(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_match_maps_correctly() {
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple_triggers_maps_correctly() {
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
triggers: ["Hello", "john"]
|
||||||
|
replace: "world"
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string(), "john".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn word_maps_correctly() {
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
word: true
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
left_word: true,
|
||||||
|
right_word: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn left_word_maps_correctly() {
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
left_word: true
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
left_word: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn right_word_maps_correctly() {
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
right_word: true
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
right_word: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn propagate_case_maps_correctly() {
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
propagate_case: true
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
propagate_case: true,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vars_maps_correctly() {
|
||||||
|
let mut params = Mapping::new();
|
||||||
|
params.insert(Value::String("param1".to_string()), Value::Bool(true));
|
||||||
|
let vars = vec![Variable {
|
||||||
|
name: "var1".to_string(),
|
||||||
|
var_type: "test".to_string(),
|
||||||
|
params,
|
||||||
|
}];
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
vars:
|
||||||
|
- name: var1
|
||||||
|
type: test
|
||||||
|
params:
|
||||||
|
param1: true
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
vars,
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vars_no_params_maps_correctly() {
|
||||||
|
let vars = vec![Variable {
|
||||||
|
name: "var1".to_string(),
|
||||||
|
var_type: "test".to_string(),
|
||||||
|
params: Mapping::new(),
|
||||||
|
}];
|
||||||
|
assert_eq!(
|
||||||
|
create_match(
|
||||||
|
r#"
|
||||||
|
trigger: "Hello"
|
||||||
|
replace: "world"
|
||||||
|
vars:
|
||||||
|
- name: var1
|
||||||
|
type: test
|
||||||
|
"#
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Match {
|
||||||
|
cause: MatchCause::Trigger(TriggerCause {
|
||||||
|
triggers: vec!["Hello".to_string()],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
effect: MatchEffect::Text(TextEffect {
|
||||||
|
replace: "world".to_string(),
|
||||||
|
vars,
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -91,7 +91,10 @@ mod tests {
|
||||||
server.accept_one().unwrap();
|
server.accept_one().unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
if cfg!(target_os = "windows") {
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
|
||||||
let client = client::<Event>("testespansoipc", &std::env::temp_dir()).unwrap();
|
let client = client::<Event>("testespansoipc", &std::env::temp_dir()).unwrap();
|
||||||
client.send(Event::Foo("hello".to_string())).unwrap();
|
client.send(Event::Foo("hello".to_string())).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -17,5 +17,6 @@ wayland = ["espanso-detect/wayland", "espanso-inject/wayland"]
|
||||||
espanso-detect = { path = "../espanso-detect" }
|
espanso-detect = { path = "../espanso-detect" }
|
||||||
espanso-ui = { path = "../espanso-ui" }
|
espanso-ui = { path = "../espanso-ui" }
|
||||||
espanso-inject = { path = "../espanso-inject" }
|
espanso-inject = { path = "../espanso-inject" }
|
||||||
|
espanso-config = { path = "../espanso-config" }
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
simplelog = "0.9.0"
|
simplelog = "0.9.0"
|
Loading…
Reference in New Issue
Block a user