parent
7a679c6395
commit
b40778cc84
|
@ -29,6 +29,7 @@ fn default_log_level() -> i32 { 0 }
|
||||||
fn default_config_caching_interval() -> i32 { 800 }
|
fn default_config_caching_interval() -> i32 { 800 }
|
||||||
fn default_toggle_interval() -> u32 { 230 }
|
fn default_toggle_interval() -> u32 { 230 }
|
||||||
fn default_backspace_limit() -> i32 { 3 }
|
fn default_backspace_limit() -> i32 { 3 }
|
||||||
|
fn default_exclude_parent_matches() -> bool {false}
|
||||||
fn default_matches() -> Vec<Match> { Vec::new() }
|
fn default_matches() -> Vec<Match> { Vec::new() }
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
@ -66,6 +67,9 @@ pub struct Configs {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub backend: BackendType,
|
pub backend: BackendType,
|
||||||
|
|
||||||
|
#[serde(default = "default_exclude_parent_matches")]
|
||||||
|
pub exclude_parent_matches: bool,
|
||||||
|
|
||||||
#[serde(default = "default_matches")]
|
#[serde(default = "default_matches")]
|
||||||
pub matches: Vec<Match>
|
pub matches: Vec<Match>
|
||||||
}
|
}
|
||||||
|
@ -176,7 +180,7 @@ impl ConfigSet {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let config = Configs::load_config(path.as_path())?;
|
let mut config = Configs::load_config(path.as_path())?;
|
||||||
|
|
||||||
if !config.validate_specific_config() {
|
if !config.validate_specific_config() {
|
||||||
return Err(ConfigLoadError::InvalidParameter(path.to_owned()))
|
return Err(ConfigLoadError::InvalidParameter(path.to_owned()))
|
||||||
|
@ -190,6 +194,23 @@ impl ConfigSet {
|
||||||
return Err(ConfigLoadError::NameDuplicate(path.to_owned()));
|
return Err(ConfigLoadError::NameDuplicate(path.to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute new match set, merging the parent's matches.
|
||||||
|
// Note: if an app-specific redefines a trigger already present in the
|
||||||
|
// default config, the latter gets overwritten.
|
||||||
|
if !config.exclude_parent_matches {
|
||||||
|
let mut merged_matches = config.matches.clone();
|
||||||
|
let mut trigger_set = HashSet::new();
|
||||||
|
merged_matches.iter().for_each(|m| {
|
||||||
|
trigger_set.insert(m.trigger.clone());
|
||||||
|
});
|
||||||
|
let parent_matches : Vec<Match> = default.matches.iter().filter(|&m| {
|
||||||
|
!trigger_set.contains(&m.trigger)
|
||||||
|
}).map(|m| m.clone()).collect();
|
||||||
|
|
||||||
|
merged_matches.extend(parent_matches);
|
||||||
|
config.matches = merged_matches;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check if it contains at least a filter, and warn the user about the problem
|
// TODO: check if it contains at least a filter, and warn the user about the problem
|
||||||
|
|
||||||
name_set.insert(config.name.clone());
|
name_set.insert(config.name.clone());
|
||||||
|
@ -521,4 +542,96 @@ mod tests {
|
||||||
assert!(config_set.is_err());
|
assert!(config_set.is_err());
|
||||||
assert!(variant_eq(&config_set.unwrap_err(), &ConfigLoadError::NameDuplicate(PathBuf::new())))
|
assert!(variant_eq(&config_set.unwrap_err(), &ConfigLoadError::NameDuplicate(PathBuf::new())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_specific_config_set_merge_with_parent_matches() {
|
||||||
|
let tmp_dir = TempDir::new().expect("unable to create temp directory");
|
||||||
|
let default_path = tmp_dir.path().join(DEFAULT_CONFIG_FILE_NAME);
|
||||||
|
fs::write(default_path, r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ":lol"
|
||||||
|
replace: "LOL"
|
||||||
|
- trigger: ":yess"
|
||||||
|
replace: "Bob"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let specific_path = tmp_dir.path().join("specific.yaml");
|
||||||
|
let specific_path_copy = specific_path.clone();
|
||||||
|
fs::write(specific_path, r###"
|
||||||
|
name: specific1
|
||||||
|
|
||||||
|
matches:
|
||||||
|
- trigger: "hello"
|
||||||
|
replace: "newstring"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let config_set = ConfigSet::load(tmp_dir.path()).unwrap();
|
||||||
|
assert_eq!(config_set.default.matches.len(), 2);
|
||||||
|
assert_eq!(config_set.specific[0].matches.len(), 3);
|
||||||
|
|
||||||
|
assert!(config_set.specific[0].matches.iter().find(|x| x.trigger == "hello").is_some());
|
||||||
|
assert!(config_set.specific[0].matches.iter().find(|x| x.trigger == ":lol").is_some());
|
||||||
|
assert!(config_set.specific[0].matches.iter().find(|x| x.trigger == ":yess").is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_specific_config_set_merge_with_parent_matches_child_priority() {
|
||||||
|
let tmp_dir = TempDir::new().expect("unable to create temp directory");
|
||||||
|
let default_path = tmp_dir.path().join(DEFAULT_CONFIG_FILE_NAME);
|
||||||
|
fs::write(default_path, r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ":lol"
|
||||||
|
replace: "LOL"
|
||||||
|
- trigger: ":yess"
|
||||||
|
replace: "Bob"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let specific_path = tmp_dir.path().join("specific.yaml");
|
||||||
|
let specific_path_copy = specific_path.clone();
|
||||||
|
fs::write(specific_path, r###"
|
||||||
|
name: specific1
|
||||||
|
|
||||||
|
matches:
|
||||||
|
- trigger: ":lol"
|
||||||
|
replace: "newstring"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let config_set = ConfigSet::load(tmp_dir.path()).unwrap();
|
||||||
|
assert_eq!(config_set.default.matches.len(), 2);
|
||||||
|
assert_eq!(config_set.specific[0].matches.len(), 2);
|
||||||
|
|
||||||
|
assert!(config_set.specific[0].matches.iter().find(|x| x.trigger == ":lol" && x.replace == "newstring").is_some());
|
||||||
|
assert!(config_set.specific[0].matches.iter().find(|x| x.trigger == ":yess").is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_specific_config_set_exclude_merge_with_parent_matches() {
|
||||||
|
let tmp_dir = TempDir::new().expect("unable to create temp directory");
|
||||||
|
let default_path = tmp_dir.path().join(DEFAULT_CONFIG_FILE_NAME);
|
||||||
|
fs::write(default_path, r###"
|
||||||
|
matches:
|
||||||
|
- trigger: ":lol"
|
||||||
|
replace: "LOL"
|
||||||
|
- trigger: ":yess"
|
||||||
|
replace: "Bob"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let specific_path = tmp_dir.path().join("specific.yaml");
|
||||||
|
let specific_path_copy = specific_path.clone();
|
||||||
|
fs::write(specific_path, r###"
|
||||||
|
name: specific1
|
||||||
|
|
||||||
|
exclude_parent_matches: true
|
||||||
|
|
||||||
|
matches:
|
||||||
|
- trigger: "hello"
|
||||||
|
replace: "newstring"
|
||||||
|
"###);
|
||||||
|
|
||||||
|
let config_set = ConfigSet::load(tmp_dir.path()).unwrap();
|
||||||
|
assert_eq!(config_set.default.matches.len(), 2);
|
||||||
|
assert_eq!(config_set.specific[0].matches.len(), 1);
|
||||||
|
|
||||||
|
assert!(config_set.specific[0].matches.iter().find(|x| x.trigger == "hello" && x.replace == "newstring").is_some());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,8 @@ use crate::matcher::Match;
|
||||||
|
|
||||||
pub struct RuntimeConfigManager<'a, S: SystemManager> {
|
pub struct RuntimeConfigManager<'a, S: SystemManager> {
|
||||||
set: ConfigSet,
|
set: ConfigSet,
|
||||||
|
|
||||||
|
// Filter regexps
|
||||||
title_regexps: Vec<Option<Regex>>,
|
title_regexps: Vec<Option<Regex>>,
|
||||||
class_regexps: Vec<Option<Regex>>,
|
class_regexps: Vec<Option<Regex>>,
|
||||||
exec_regexps: Vec<Option<Regex>>,
|
exec_regexps: Vec<Option<Regex>>,
|
||||||
|
@ -178,6 +180,7 @@ impl <'a, S: SystemManager> super::ConfigManager<'a> for RuntimeConfigManager<'a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TESTS
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user