feat(config): implement legacy loader
This commit is contained in:
		
							parent
							
								
									1e015eb891
								
							
						
					
					
						commit
						9098d5ac2a
					
				| 
						 | 
				
			
			@ -24,8 +24,8 @@ use thiserror::Error;
 | 
			
		|||
mod parse;
 | 
			
		||||
mod path;
 | 
			
		||||
mod resolve;
 | 
			
		||||
mod store;
 | 
			
		||||
mod util;
 | 
			
		||||
pub(crate) mod store;
 | 
			
		||||
 | 
			
		||||
pub trait Config {
 | 
			
		||||
  fn label(&self) -> &str;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,6 +106,13 @@ impl DefaultConfigStore {
 | 
			
		|||
      customs,
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pub fn from_configs(default: Box<dyn Config>, customs: Vec<Box<dyn Config>>) -> Result<Self> {
 | 
			
		||||
    Ok(Self {
 | 
			
		||||
      default,
 | 
			
		||||
      customs,
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,13 +153,12 @@ fn default_modulo_path() -> Option<String> {
 | 
			
		|||
fn default_post_inject_delay() -> u64 {
 | 
			
		||||
  100
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn default_wait_for_modifiers_release() -> bool {
 | 
			
		||||
  false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, Serialize, Deserialize)]
 | 
			
		||||
pub struct Configs {
 | 
			
		||||
pub struct LegacyConfig {
 | 
			
		||||
  #[serde(default = "default_name")]
 | 
			
		||||
  pub name: String,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +301,7 @@ macro_rules! validate_field {
 | 
			
		|||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Configs {
 | 
			
		||||
impl LegacyConfig {
 | 
			
		||||
  /*
 | 
			
		||||
   * Validate the Config instance.
 | 
			
		||||
   * It makes sure that user defined config instances do not define
 | 
			
		||||
| 
						 | 
				
			
			@ -412,8 +411,8 @@ impl Default for BackendType {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Configs {
 | 
			
		||||
  fn load_config(path: &Path) -> Result<Configs, ConfigLoadError> {
 | 
			
		||||
impl LegacyConfig {
 | 
			
		||||
  fn load_config(path: &Path) -> Result<LegacyConfig, ConfigLoadError> {
 | 
			
		||||
    let file_res = File::open(path);
 | 
			
		||||
    if let Ok(mut file) = file_res {
 | 
			
		||||
      let mut contents = String::new();
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +434,7 @@ impl Configs {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn merge_overwrite(&mut self, new_config: Configs) {
 | 
			
		||||
  fn merge_overwrite(&mut self, new_config: LegacyConfig) {
 | 
			
		||||
    // Merge matches
 | 
			
		||||
    let mut merged_matches = new_config.matches;
 | 
			
		||||
    let mut match_trigger_set = HashSet::new();
 | 
			
		||||
| 
						 | 
				
			
			@ -473,7 +472,7 @@ impl Configs {
 | 
			
		|||
    self.global_vars = merged_global_vars;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn merge_no_overwrite(&mut self, default: &Configs) {
 | 
			
		||||
  fn merge_no_overwrite(&mut self, default: &LegacyConfig) {
 | 
			
		||||
    // Merge matches
 | 
			
		||||
    let mut match_trigger_set = HashSet::new();
 | 
			
		||||
    self.matches.iter().for_each(|m| {
 | 
			
		||||
| 
						 | 
				
			
			@ -527,20 +526,20 @@ fn name_for_global_var(v: &Value) -> String {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug, Serialize, Deserialize)]
 | 
			
		||||
pub struct ConfigSet {
 | 
			
		||||
  pub default: Configs,
 | 
			
		||||
  pub specific: Vec<Configs>,
 | 
			
		||||
pub struct LegacyConfigSet {
 | 
			
		||||
  pub default: LegacyConfig,
 | 
			
		||||
  pub specific: Vec<LegacyConfig>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ConfigSet {
 | 
			
		||||
  pub fn load(config_dir: &Path, package_dir: &Path) -> Result<ConfigSet, ConfigLoadError> {
 | 
			
		||||
impl LegacyConfigSet {
 | 
			
		||||
  pub fn load(config_dir: &Path, package_dir: &Path) -> Result<LegacyConfigSet, ConfigLoadError> {
 | 
			
		||||
    if !config_dir.is_dir() {
 | 
			
		||||
      return Err(ConfigLoadError::InvalidConfigDirectory);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Load default configuration
 | 
			
		||||
    let default_file = config_dir.join(DEFAULT_CONFIG_FILE_NAME);
 | 
			
		||||
    let default = Configs::load_config(default_file.as_path())?;
 | 
			
		||||
    let default = LegacyConfig::load_config(default_file.as_path())?;
 | 
			
		||||
 | 
			
		||||
    // Check that a compatible backend is used, otherwise warn the user
 | 
			
		||||
    if cfg!(not(target_os = "linux")) && default.backend == BackendType::Auto {
 | 
			
		||||
| 
						 | 
				
			
			@ -569,13 +568,13 @@ impl ConfigSet {
 | 
			
		|||
    // Load the user defined config files
 | 
			
		||||
 | 
			
		||||
    let mut name_set = HashSet::new();
 | 
			
		||||
    let mut children_map: HashMap<String, Vec<Configs>> = HashMap::new();
 | 
			
		||||
    let mut package_map: HashMap<String, Vec<Configs>> = HashMap::new();
 | 
			
		||||
    let mut children_map: HashMap<String, Vec<LegacyConfig>> = HashMap::new();
 | 
			
		||||
    let mut package_map: HashMap<String, Vec<LegacyConfig>> = HashMap::new();
 | 
			
		||||
    let mut root_configs = Vec::new();
 | 
			
		||||
    root_configs.push(default);
 | 
			
		||||
 | 
			
		||||
    let mut file_loader = |entry: walkdir::Result<DirEntry>,
 | 
			
		||||
                           dest_map: &mut HashMap<String, Vec<Configs>>|
 | 
			
		||||
                           dest_map: &mut HashMap<String, Vec<LegacyConfig>>|
 | 
			
		||||
     -> Result<(), ConfigLoadError> {
 | 
			
		||||
      match entry {
 | 
			
		||||
        Ok(entry) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -598,12 +597,12 @@ impl ConfigSet {
 | 
			
		|||
            .unwrap_or_default()
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .unwrap_or_default()
 | 
			
		||||
            .starts_with(".")
 | 
			
		||||
            .starts_with('.')
 | 
			
		||||
          {
 | 
			
		||||
            return Ok(());
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          let mut config = Configs::load_config(&path)?;
 | 
			
		||||
          let mut config = LegacyConfig::load_config(&path)?;
 | 
			
		||||
 | 
			
		||||
          // Make sure the config does not contain reserved fields
 | 
			
		||||
          if !config.validate_user_defined_config() {
 | 
			
		||||
| 
						 | 
				
			
			@ -651,7 +650,7 @@ impl ConfigSet {
 | 
			
		|||
    // Merge the children config files
 | 
			
		||||
    let mut configs_without_packages = Vec::new();
 | 
			
		||||
    for root_config in root_configs {
 | 
			
		||||
      let config = ConfigSet::reduce_configs(root_config, &children_map, true);
 | 
			
		||||
      let config = LegacyConfigSet::reduce_configs(root_config, &children_map, true);
 | 
			
		||||
      configs_without_packages.push(config);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -660,13 +659,13 @@ impl ConfigSet {
 | 
			
		|||
    //       than configs.
 | 
			
		||||
    let mut configs = Vec::new();
 | 
			
		||||
    for root_config in configs_without_packages {
 | 
			
		||||
      let config = ConfigSet::reduce_configs(root_config, &package_map, false);
 | 
			
		||||
      let config = LegacyConfigSet::reduce_configs(root_config, &package_map, false);
 | 
			
		||||
      configs.push(config);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Separate default from specific
 | 
			
		||||
    let default = configs.get(0).unwrap().clone();
 | 
			
		||||
    let mut specific = (&configs[1..]).to_vec().clone();
 | 
			
		||||
    let mut specific = (&configs[1..]).to_vec();
 | 
			
		||||
 | 
			
		||||
    // Add default entries to specific configs when needed
 | 
			
		||||
    for config in specific.iter_mut() {
 | 
			
		||||
| 
						 | 
				
			
			@ -685,14 +684,14 @@ impl ConfigSet {
 | 
			
		|||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(ConfigSet { default, specific })
 | 
			
		||||
    Ok(LegacyConfigSet { default, specific })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn reduce_configs(
 | 
			
		||||
    target: Configs,
 | 
			
		||||
    children_map: &HashMap<String, Vec<Configs>>,
 | 
			
		||||
    target: LegacyConfig,
 | 
			
		||||
    children_map: &HashMap<String, Vec<LegacyConfig>>,
 | 
			
		||||
    higher_priority: bool,
 | 
			
		||||
  ) -> Configs {
 | 
			
		||||
  ) -> LegacyConfig {
 | 
			
		||||
    if children_map.contains_key(&target.name) {
 | 
			
		||||
      let mut target = target;
 | 
			
		||||
      for children in children_map.get(&target.name).unwrap() {
 | 
			
		||||
| 
						 | 
				
			
			@ -709,7 +708,7 @@ impl ConfigSet {
 | 
			
		|||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn has_conflicts(default: &Configs, specific: &Vec<Configs>) -> bool {
 | 
			
		||||
  fn has_conflicts(default: &LegacyConfig, specific: &[LegacyConfig]) -> bool {
 | 
			
		||||
    let mut sorted_triggers: Vec<String> = default
 | 
			
		||||
      .matches
 | 
			
		||||
      .iter()
 | 
			
		||||
| 
						 | 
				
			
			@ -729,7 +728,7 @@ impl ConfigSet {
 | 
			
		|||
    has_conflicts
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn list_has_conflicts(sorted_list: &Vec<String>) -> bool {
 | 
			
		||||
  fn list_has_conflicts(sorted_list: &[String]) -> bool {
 | 
			
		||||
    if sorted_list.len() <= 1 {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -817,7 +816,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
  #[test]
 | 
			
		||||
  fn test_config_file_not_found() {
 | 
			
		||||
    let config = Configs::load_config(Path::new("invalid/path"));
 | 
			
		||||
    let config = LegacyConfig::load_config(Path::new("invalid/path"));
 | 
			
		||||
    assert_eq!(config.is_err(), true);
 | 
			
		||||
    assert_eq!(config.unwrap_err(), ConfigLoadError::FileNotFound);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -825,15 +824,14 @@ mod tests {
 | 
			
		|||
  #[test]
 | 
			
		||||
  fn test_config_file_with_bad_yaml_syntax() {
 | 
			
		||||
    let broken_config_file = create_tmp_file(TEST_CONFIG_FILE_WITH_BAD_YAML);
 | 
			
		||||
    let config = Configs::load_config(broken_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(broken_config_file.path());
 | 
			
		||||
    match config {
 | 
			
		||||
      Ok(_) => assert!(false),
 | 
			
		||||
      Ok(_) => unreachable!(),
 | 
			
		||||
      Err(e) => {
 | 
			
		||||
        match e {
 | 
			
		||||
          ConfigLoadError::InvalidYAML(p, _) => assert_eq!(p, broken_config_file.path().to_owned()),
 | 
			
		||||
          _ => assert!(false),
 | 
			
		||||
          _ => unreachable!(),
 | 
			
		||||
        }
 | 
			
		||||
        assert!(true);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -861,7 +859,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let config = Configs::load_config(working_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(working_config_file.path());
 | 
			
		||||
    assert_eq!(config.unwrap().validate_user_defined_config(), true);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -875,7 +873,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let config = Configs::load_config(working_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(working_config_file.path());
 | 
			
		||||
    assert_eq!(config.unwrap().validate_user_defined_config(), false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -889,7 +887,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let config = Configs::load_config(working_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(working_config_file.path());
 | 
			
		||||
    assert_eq!(config.unwrap().validate_user_defined_config(), false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -903,7 +901,7 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let config = Configs::load_config(working_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(working_config_file.path());
 | 
			
		||||
    assert_eq!(config.unwrap().validate_user_defined_config(), false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -917,14 +915,14 @@ mod tests {
 | 
			
		|||
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let config = Configs::load_config(working_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(working_config_file.path());
 | 
			
		||||
    assert_eq!(config.unwrap().validate_user_defined_config(), false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
  fn test_config_loaded_correctly() {
 | 
			
		||||
    let working_config_file = create_tmp_file(TEST_WORKING_CONFIG_FILE);
 | 
			
		||||
    let config = Configs::load_config(working_config_file.path());
 | 
			
		||||
    let config = LegacyConfig::load_config(working_config_file.path());
 | 
			
		||||
    assert_eq!(config.is_ok(), true);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -981,13 +979,13 @@ mod tests {
 | 
			
		|||
  fn test_config_set_default_content_should_work_correctly() {
 | 
			
		||||
    let (data_dir, package_dir) = create_temp_espanso_directories();
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    assert!(config_set.is_ok());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
  fn test_config_set_load_fail_bad_directory() {
 | 
			
		||||
    let config_set = ConfigSet::load(Path::new("invalid/path"), Path::new("invalid/path"));
 | 
			
		||||
    let config_set = LegacyConfigSet::load(Path::new("invalid/path"), Path::new("invalid/path"));
 | 
			
		||||
    assert_eq!(config_set.is_err(), true);
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      config_set.unwrap_err(),
 | 
			
		||||
| 
						 | 
				
			
			@ -1000,7 +998,7 @@ mod tests {
 | 
			
		|||
    let data_dir = TempDir::new().expect("unable to create temp directory");
 | 
			
		||||
    let package_dir = TempDir::new().expect("unable to create package directory");
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    assert_eq!(config_set.is_err(), true);
 | 
			
		||||
    assert_eq!(config_set.unwrap_err(), ConfigLoadError::FileNotFound);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1011,15 +1009,14 @@ mod tests {
 | 
			
		|||
      create_temp_espanso_directories_with_default_content(TEST_CONFIG_FILE_WITH_BAD_YAML);
 | 
			
		||||
    let default_path = data_dir.path().join(DEFAULT_CONFIG_FILE_NAME);
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    match config_set {
 | 
			
		||||
      Ok(_) => assert!(false),
 | 
			
		||||
      Ok(_) => unreachable!(),
 | 
			
		||||
      Err(e) => {
 | 
			
		||||
        match e {
 | 
			
		||||
          ConfigLoadError::InvalidYAML(p, _) => assert_eq!(p, default_path),
 | 
			
		||||
          _ => assert!(false),
 | 
			
		||||
          _ => unreachable!(),
 | 
			
		||||
        }
 | 
			
		||||
        assert!(true);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1035,13 +1032,11 @@ mod tests {
 | 
			
		|||
        config_caching_interval: 10000
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let user_defined_path_copy = user_defined_path.clone();
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    assert!(config_set.is_err());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      config_set.unwrap_err(),
 | 
			
		||||
      ConfigLoadError::InvalidParameter(user_defined_path_copy)
 | 
			
		||||
      ConfigLoadError::InvalidParameter(user_defined_path)
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1056,13 +1051,12 @@ mod tests {
 | 
			
		|||
        backend: Clipboard
 | 
			
		||||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
    let user_defined_path_copy = user_defined_path.clone();
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    assert!(config_set.is_ok());
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      config_set.unwrap().specific[0].name,
 | 
			
		||||
      user_defined_path_copy.to_str().unwrap_or_default()
 | 
			
		||||
      user_defined_path.to_str().unwrap_or_default()
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1086,7 +1080,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path());
 | 
			
		||||
    assert!(config_set.is_err());
 | 
			
		||||
    assert!(matches!(
 | 
			
		||||
      &config_set.unwrap_err(),
 | 
			
		||||
| 
						 | 
				
			
			@ -1118,25 +1112,22 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_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| triggers_for_match(x)[0] == "hello")
 | 
			
		||||
      .is_some());
 | 
			
		||||
      .any(|x| triggers_for_match(x)[0] == "hello"));
 | 
			
		||||
    assert!(config_set.specific[0]
 | 
			
		||||
      .matches
 | 
			
		||||
      .iter()
 | 
			
		||||
      .find(|x| triggers_for_match(x)[0] == ":lol")
 | 
			
		||||
      .is_some());
 | 
			
		||||
      .any(|x| triggers_for_match(x)[0] == ":lol"));
 | 
			
		||||
    assert!(config_set.specific[0]
 | 
			
		||||
      .matches
 | 
			
		||||
      .iter()
 | 
			
		||||
      .find(|x| triggers_for_match(x)[0] == ":yess")
 | 
			
		||||
      .is_some());
 | 
			
		||||
      .any(|x| triggers_for_match(x)[0] == ":yess"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
| 
						 | 
				
			
			@ -1163,22 +1154,20 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_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| {
 | 
			
		||||
      .any(|x| {
 | 
			
		||||
        triggers_for_match(x)[0] == ":lol" && replace_for_match(x) == "newstring"
 | 
			
		||||
      })
 | 
			
		||||
      .is_some());
 | 
			
		||||
      }));
 | 
			
		||||
    assert!(config_set.specific[0]
 | 
			
		||||
      .matches
 | 
			
		||||
      .iter()
 | 
			
		||||
      .find(|x| triggers_for_match(x)[0] == ":yess")
 | 
			
		||||
      .is_some());
 | 
			
		||||
      .any(|x| triggers_for_match(x)[0] == ":yess"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
| 
						 | 
				
			
			@ -1207,17 +1196,16 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_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| {
 | 
			
		||||
      .any(|x| {
 | 
			
		||||
        triggers_for_match(x)[0] == "hello" && replace_for_match(x) == "newstring"
 | 
			
		||||
      })
 | 
			
		||||
      .is_some());
 | 
			
		||||
      }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
| 
						 | 
				
			
			@ -1246,7 +1234,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1276,7 +1264,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1300,7 +1288,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1326,7 +1314,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 2);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1361,7 +1349,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 1);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1415,7 +1403,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 3);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1457,7 +1445,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 1);
 | 
			
		||||
    assert!(config_set.default.matches.iter().any(|m| {
 | 
			
		||||
| 
						 | 
				
			
			@ -1488,7 +1476,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 2);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1526,7 +1514,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 1);
 | 
			
		||||
    assert_eq!(triggers_for_match(&config_set.default.matches[0])[0], "hasta");
 | 
			
		||||
| 
						 | 
				
			
			@ -1554,7 +1542,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 1);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1604,7 +1592,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.default.matches.len(), 1);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1625,7 +1613,7 @@ mod tests {
 | 
			
		|||
  #[test]
 | 
			
		||||
  fn test_list_has_conflict_no_conflict() {
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      ConfigSet::list_has_conflicts(&vec!(":ab".to_owned(), ":bc".to_owned())),
 | 
			
		||||
      LegacyConfigSet::list_has_conflicts(&[":ab".to_owned(), ":bc".to_owned()]),
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1634,7 +1622,7 @@ mod tests {
 | 
			
		|||
  fn test_list_has_conflict_conflict() {
 | 
			
		||||
    let mut list = vec!["ac".to_owned(), "ab".to_owned(), "abc".to_owned()];
 | 
			
		||||
    list.sort();
 | 
			
		||||
    assert_eq!(ConfigSet::list_has_conflicts(&list), true);
 | 
			
		||||
    assert_eq!(LegacyConfigSet::list_has_conflicts(&list), true);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
| 
						 | 
				
			
			@ -1661,9 +1649,9 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      ConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      LegacyConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1694,9 +1682,9 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      ConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      LegacyConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      true
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1725,9 +1713,9 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      ConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      LegacyConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      true
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1767,9 +1755,9 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
      ConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      LegacyConfigSet::has_conflicts(&config_set.default, &config_set.specific),
 | 
			
		||||
      false
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -1798,7 +1786,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.default.global_vars.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.specific[0].global_vars.len(), 2);
 | 
			
		||||
| 
						 | 
				
			
			@ -1837,7 +1825,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 0);
 | 
			
		||||
    assert_eq!(config_set.default.global_vars.len(), 2);
 | 
			
		||||
    assert!(config_set
 | 
			
		||||
| 
						 | 
				
			
			@ -1878,7 +1866,7 @@ mod tests {
 | 
			
		|||
        "###,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let config_set = ConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    let config_set = LegacyConfigSet::load(data_dir.path(), package_dir.path()).unwrap();
 | 
			
		||||
    assert_eq!(config_set.specific.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.default.global_vars.len(), 1);
 | 
			
		||||
    assert_eq!(config_set.specific[0].global_vars.len(), 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
/*
 | 
			
		||||
 * This file is part of espanso.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2019-2021 Federico Terzi
 | 
			
		||||
 * C title: (), class: (), exec: ()opyright (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
 | 
			
		||||
| 
						 | 
				
			
			@ -17,16 +17,313 @@
 | 
			
		|||
 * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use regex::Regex;
 | 
			
		||||
use std::{collections::HashMap, path::Path};
 | 
			
		||||
 | 
			
		||||
use crate::{config::ConfigStore, matches::store::MatchStore};
 | 
			
		||||
use self::config::LegacyConfig;
 | 
			
		||||
use crate::config::store::DefaultConfigStore;
 | 
			
		||||
use crate::matches::group::loader::yaml::parse::{YAMLMatch, YAMLVariable};
 | 
			
		||||
use crate::{
 | 
			
		||||
  config::Config,
 | 
			
		||||
  config::{AppProperties, ConfigStore},
 | 
			
		||||
  matches::{
 | 
			
		||||
    store::{MatchSet, MatchStore},
 | 
			
		||||
    Match, Variable,
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
use std::convert::TryInto;
 | 
			
		||||
 | 
			
		||||
mod config;
 | 
			
		||||
mod model;
 | 
			
		||||
 | 
			
		||||
pub fn load(base_dir: &Path) -> Result<(Box<dyn ConfigStore>, Box<dyn MatchStore>)> {
 | 
			
		||||
  // TODO: load legacy config set and then convert it to the new format 
 | 
			
		||||
pub fn load(
 | 
			
		||||
  base_dir: &Path,
 | 
			
		||||
  package_dir: &Path,
 | 
			
		||||
) -> Result<(Box<dyn ConfigStore>, Box<dyn MatchStore>)> {
 | 
			
		||||
  let config_set = config::LegacyConfigSet::load(base_dir, package_dir)?;
 | 
			
		||||
 | 
			
		||||
  todo!()
 | 
			
		||||
}
 | 
			
		||||
  let (default_config, default_match_group) = split_config(config_set.default);
 | 
			
		||||
  let mut match_groups = HashMap::new();
 | 
			
		||||
  match_groups.insert("default".to_string(), default_match_group);
 | 
			
		||||
 | 
			
		||||
  let mut custom_configs: Vec<Box<dyn Config>> = Vec::new();
 | 
			
		||||
  for custom in config_set.specific {
 | 
			
		||||
    let (custom_config, custom_match_group) = split_config(custom);
 | 
			
		||||
    match_groups.insert(custom_config.name.clone(), custom_match_group);
 | 
			
		||||
    custom_configs.push(Box::new(custom_config));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let config_store = DefaultConfigStore::from_configs(Box::new(default_config), custom_configs)?;
 | 
			
		||||
  let match_store = LegacyMatchStore::new(match_groups);
 | 
			
		||||
 | 
			
		||||
  Ok((Box::new(config_store), Box::new(match_store)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn split_config(config: LegacyConfig) -> (LegacyInteropConfig, LegacyMatchGroup) {
 | 
			
		||||
  let global_vars = config
 | 
			
		||||
    .global_vars
 | 
			
		||||
    .iter()
 | 
			
		||||
    .filter_map(|var| {
 | 
			
		||||
      let var: YAMLVariable = serde_yaml::from_value(var.clone()).ok()?;
 | 
			
		||||
      let var: Variable = var.try_into().ok()?;
 | 
			
		||||
      Some(var)
 | 
			
		||||
    })
 | 
			
		||||
    .collect();
 | 
			
		||||
 | 
			
		||||
  let matches = config
 | 
			
		||||
    .matches
 | 
			
		||||
    .iter()
 | 
			
		||||
    .filter_map(|var| {
 | 
			
		||||
      let m: YAMLMatch = serde_yaml::from_value(var.clone()).ok()?;
 | 
			
		||||
      let m: Match = m.try_into().ok()?;
 | 
			
		||||
      Some(m)
 | 
			
		||||
    })
 | 
			
		||||
    .collect();
 | 
			
		||||
 | 
			
		||||
  let match_group = LegacyMatchGroup {
 | 
			
		||||
    global_vars,
 | 
			
		||||
    matches,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let config: LegacyInteropConfig = config.into();
 | 
			
		||||
  (config, match_group)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct LegacyInteropConfig {
 | 
			
		||||
  pub name: String,
 | 
			
		||||
 | 
			
		||||
  match_paths: Vec<String>,
 | 
			
		||||
 | 
			
		||||
  filter_title: Option<Regex>,
 | 
			
		||||
  filter_class: Option<Regex>,
 | 
			
		||||
  filter_exec: Option<Regex>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<config::LegacyConfig> for LegacyInteropConfig {
 | 
			
		||||
  fn from(config: config::LegacyConfig) -> Self {
 | 
			
		||||
    Self {
 | 
			
		||||
      name: config.name.clone(),
 | 
			
		||||
      match_paths: vec![config.name],
 | 
			
		||||
      filter_title: if !config.filter_title.is_empty() {
 | 
			
		||||
        Regex::new(&config.filter_title).ok()
 | 
			
		||||
      } else {
 | 
			
		||||
        None
 | 
			
		||||
      },
 | 
			
		||||
      filter_class: if !config.filter_class.is_empty() {
 | 
			
		||||
        Regex::new(&config.filter_class).ok()
 | 
			
		||||
      } else {
 | 
			
		||||
        None
 | 
			
		||||
      },
 | 
			
		||||
      filter_exec: if !config.filter_exec.is_empty() {
 | 
			
		||||
        Regex::new(&config.filter_exec).ok()
 | 
			
		||||
      } else {
 | 
			
		||||
        None
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Config for LegacyInteropConfig {
 | 
			
		||||
  fn label(&self) -> &str {
 | 
			
		||||
    &self.name
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn match_paths(&self) -> &[String] {
 | 
			
		||||
    &self.match_paths
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fn is_match(&self, app: &AppProperties) -> bool {
 | 
			
		||||
    if self.filter_title.is_none() && self.filter_exec.is_none() && self.filter_class.is_none() {
 | 
			
		||||
      return 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 {
 | 
			
		||||
        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
 | 
			
		||||
      }
 | 
			
		||||
    } 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
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      true
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // All the filters that have been specified must be true to define a match
 | 
			
		||||
    is_exec_match && is_title_match && is_class_match
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct LegacyMatchGroup {
 | 
			
		||||
  matches: Vec<Match>,
 | 
			
		||||
  global_vars: Vec<Variable>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct LegacyMatchStore {
 | 
			
		||||
  groups: HashMap<String, LegacyMatchGroup>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl LegacyMatchStore {
 | 
			
		||||
  pub fn new(groups: HashMap<String, LegacyMatchGroup>) -> Self {
 | 
			
		||||
    Self { groups }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MatchStore for LegacyMatchStore {
 | 
			
		||||
  fn query(&self, paths: &[String]) -> MatchSet {
 | 
			
		||||
    let group = if !paths.is_empty() {
 | 
			
		||||
      if let Some(group) = self.groups.get(&paths[0]) {
 | 
			
		||||
        Some(group)
 | 
			
		||||
      } else {
 | 
			
		||||
        None
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      None
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if let Some(group) = group {
 | 
			
		||||
      MatchSet {
 | 
			
		||||
        matches: group.matches.iter().collect(),
 | 
			
		||||
        global_vars: group.global_vars.iter().collect(),
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      MatchSet {
 | 
			
		||||
        matches: Vec::new(),
 | 
			
		||||
        global_vars: Vec::new(),
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
  use super::*;
 | 
			
		||||
  use std::{fs::create_dir_all, path::Path};
 | 
			
		||||
  use tempdir::TempDir;
 | 
			
		||||
 | 
			
		||||
  pub fn use_test_directory(callback: impl FnOnce(&Path, &Path, &Path)) {
 | 
			
		||||
    let dir = TempDir::new("tempconfig").unwrap();
 | 
			
		||||
    let user_dir = dir.path().join("user");
 | 
			
		||||
    create_dir_all(&user_dir).unwrap();
 | 
			
		||||
 | 
			
		||||
    let package_dir = TempDir::new("tempconfig").unwrap();
 | 
			
		||||
 | 
			
		||||
    callback(
 | 
			
		||||
      &dunce::canonicalize(&dir.path()).unwrap(),
 | 
			
		||||
      &dunce::canonicalize(&user_dir).unwrap(),
 | 
			
		||||
      &dunce::canonicalize(&package_dir.path()).unwrap(),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
  fn load_legacy_works_correctly() {
 | 
			
		||||
    use_test_directory(|base, user, packages| {
 | 
			
		||||
      std::fs::write(base.join("default.yml"), r#"
 | 
			
		||||
      backend: Clipboard
 | 
			
		||||
 | 
			
		||||
      global_vars:
 | 
			
		||||
        - name: var1
 | 
			
		||||
          type: test
 | 
			
		||||
 | 
			
		||||
      matches:
 | 
			
		||||
        - trigger: "hello"
 | 
			
		||||
          replace: "world"
 | 
			
		||||
      "#).unwrap();
 | 
			
		||||
 | 
			
		||||
      std::fs::write(user.join("specific.yml"), r#"
 | 
			
		||||
      name: specific
 | 
			
		||||
      parent: default
 | 
			
		||||
 | 
			
		||||
      matches:
 | 
			
		||||
        - trigger: "foo"
 | 
			
		||||
          replace: "bar"
 | 
			
		||||
      "#).unwrap();
 | 
			
		||||
 | 
			
		||||
      std::fs::write(user.join("separate.yml"), r#"
 | 
			
		||||
      name: separate
 | 
			
		||||
      filter_title: "Google"
 | 
			
		||||
 | 
			
		||||
      matches:
 | 
			
		||||
        - trigger: "eren"
 | 
			
		||||
          replace: "mikasa"
 | 
			
		||||
      "#).unwrap();
 | 
			
		||||
 | 
			
		||||
      let (config_store, match_store) = load(base, packages).unwrap();
 | 
			
		||||
 | 
			
		||||
      let default_config = config_store.default();
 | 
			
		||||
      assert_eq!(default_config.match_paths().len(), 1);
 | 
			
		||||
 | 
			
		||||
      let active_config = config_store.active(&AppProperties {
 | 
			
		||||
        title: Some("Google"),
 | 
			
		||||
        class: None,
 | 
			
		||||
        exec: None,
 | 
			
		||||
      });
 | 
			
		||||
      assert_eq!(active_config.match_paths().len(), 1);
 | 
			
		||||
 | 
			
		||||
      let default_fallback = config_store.active(&AppProperties {
 | 
			
		||||
        title: Some("Yahoo"),
 | 
			
		||||
        class: None,
 | 
			
		||||
        exec: None,
 | 
			
		||||
      });
 | 
			
		||||
      assert_eq!(default_fallback.match_paths().len(), 1);
 | 
			
		||||
 | 
			
		||||
      assert_eq!(match_store.query(default_config.match_paths()).matches.len(), 2); 
 | 
			
		||||
      assert_eq!(match_store.query(default_config.match_paths()).global_vars.len(), 1); 
 | 
			
		||||
      
 | 
			
		||||
      assert_eq!(match_store.query(active_config.match_paths()).matches.len(), 3); 
 | 
			
		||||
      assert_eq!(match_store.query(active_config.match_paths()).global_vars.len(), 1); 
 | 
			
		||||
 | 
			
		||||
      assert_eq!(match_store.query(default_fallback.match_paths()).matches.len(), 2); 
 | 
			
		||||
      assert_eq!(match_store.query(default_fallback.match_paths()).global_vars.len(), 1); 
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #[test]
 | 
			
		||||
  fn load_legacy_with_packages() {
 | 
			
		||||
    use_test_directory(|base, user, packages| {
 | 
			
		||||
      std::fs::write(base.join("default.yml"), r#"
 | 
			
		||||
      backend: Clipboard
 | 
			
		||||
 | 
			
		||||
      matches:
 | 
			
		||||
        - trigger: "hello"
 | 
			
		||||
          replace: "world"
 | 
			
		||||
      "#).unwrap();
 | 
			
		||||
 | 
			
		||||
      create_dir_all(packages.join("test-package")).unwrap();
 | 
			
		||||
      std::fs::write(packages.join("test-package").join("package.yml"), r#"
 | 
			
		||||
      name: test-package 
 | 
			
		||||
      parent: default
 | 
			
		||||
 | 
			
		||||
      matches:
 | 
			
		||||
        - trigger: "foo"
 | 
			
		||||
          replace: "bar"
 | 
			
		||||
      "#).unwrap();
 | 
			
		||||
 | 
			
		||||
      let (config_store, match_store) = load(base, packages).unwrap();
 | 
			
		||||
 | 
			
		||||
      let default_config = config_store.default();
 | 
			
		||||
      assert_eq!(default_config.match_paths().len(), 1);
 | 
			
		||||
 | 
			
		||||
      assert_eq!(match_store.query(default_config.match_paths()).matches.len(), 2); 
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@ use self::yaml::YAMLImporter;
 | 
			
		|||
 | 
			
		||||
use super::MatchGroup;
 | 
			
		||||
 | 
			
		||||
mod yaml;
 | 
			
		||||
pub(crate) mod yaml;
 | 
			
		||||
 | 
			
		||||
trait Importer {
 | 
			
		||||
  fn is_supported(&self, extension: &str) -> bool;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ use crate::matches::{MatchCause, MatchEffect, TextEffect, TriggerCause};
 | 
			
		|||
 | 
			
		||||
use super::Importer;
 | 
			
		||||
 | 
			
		||||
mod parse;
 | 
			
		||||
pub(crate) mod parse;
 | 
			
		||||
 | 
			
		||||
pub(crate) struct YAMLImporter {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,7 +22,7 @@ use std::path::Path;
 | 
			
		|||
 | 
			
		||||
use super::{Match, Variable};
 | 
			
		||||
 | 
			
		||||
mod loader;
 | 
			
		||||
pub(crate) mod loader;
 | 
			
		||||
mod path;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ use serde_yaml::Mapping;
 | 
			
		|||
 | 
			
		||||
use crate::counter::{next_id, StructId};
 | 
			
		||||
 | 
			
		||||
mod group;
 | 
			
		||||
pub(crate) mod group;
 | 
			
		||||
pub mod store;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user