diff --git a/clafrica/data/data_sample.toml b/clafrica/data/data_sample.toml index 03c60be..0e13d42 100644 --- a/clafrica/data/data_sample.toml +++ b/clafrica/data/data_sample.toml @@ -9,6 +9,9 @@ authors = [ website = "sample@example.com" description = "Sample code for testing purpose." +[core] +auto_capitalize = true + [data] 2a_ = "á̠" 2af_ = "ɑ̠́" @@ -19,4 +22,6 @@ description = "Sample code for testing purpose." 2ua = "úá" 2uaf = "úɑ́" 2uuaf = "ʉ́ɑ́" +u2 = "ú" +a2 = "á" sample2 = { path = "./data_sample2.toml" } diff --git a/clafrica/data/data_sample2.toml b/clafrica/data/data_sample2.toml index 78669b6..e827111 100644 --- a/clafrica/data/data_sample2.toml +++ b/clafrica/data/data_sample2.toml @@ -6,6 +6,9 @@ authors = ["Foo Bar "] website = "sample@example.com" description = "Sample code for testing purpose." +[core] +auto_capitalize = false + [data] 2aa = { value = "áá", alias = ["a22"]} 2ee = { value = "éé", alias = ["e22"]} diff --git a/clafrica/src/config.rs b/clafrica/src/config.rs index 0a98230..dadd480 100644 --- a/clafrica/src/config.rs +++ b/clafrica/src/config.rs @@ -13,10 +13,10 @@ pub struct Config { #[derive(Deserialize, Debug, Clone)] pub struct CoreConfig { - pub buffer_size: usize, - pub auto_capitalize: bool, - pub page_size: usize, - pub auto_commit: bool, + pub buffer_size: Option, + pub auto_capitalize: Option, + pub page_size: Option, + pub auto_commit: Option, } #[derive(Deserialize, Debug, Clone)] @@ -38,6 +38,18 @@ struct DetailedData { alias: Vec, } +macro_rules! insert_with_auto_capitalize { + ( $data: expr, $auto_capitalize: expr, $key: expr, $value: expr ) => { + $data.insert($key.to_owned(), Data::Simple($value.to_owned())); + + if $auto_capitalize && !$key.is_empty() && $key.chars().next().unwrap().is_lowercase() { + $data + .entry($key[0..1].to_uppercase() + &$key[1..]) + .or_insert(Data::Simple($value.to_uppercase())); + } + }; +} + impl Config { pub fn from_file(filepath: &Path) -> Result> { let content = fs::read_to_string(filepath) @@ -45,8 +57,12 @@ impl Config { let mut config: Self = toml::from_str(&content).map_err(|err| { format!("Failed to parse configuration file `{filepath:?}`.\nCaused by:\n\t{err}") })?; - let config_path = filepath.parent().unwrap(); + let auto_capitalize = config + .core + .as_ref() + .map(|c| c.auto_capitalize.unwrap_or(true)) + .unwrap_or(true); // Data let mut data = HashMap::new(); @@ -59,12 +75,12 @@ impl Config { let conf = Config::from_file(&filepath)?; data.extend(conf.data.unwrap_or_default()); } - Data::Simple(_) => { - data.insert(key.to_owned(), value.clone()); + Data::Simple(value) => { + insert_with_auto_capitalize!(data, auto_capitalize, key, value); } Data::Detailed(DetailedData { value, alias }) => { - alias.iter().chain([key.to_owned()].iter()).for_each(|e| { - data.insert(e.to_owned(), Data::Simple(value.to_owned())); + alias.iter().chain([key.to_owned()].iter()).for_each(|key| { + insert_with_auto_capitalize!(data, auto_capitalize, key, value); }); } }; @@ -126,8 +142,8 @@ impl Config { pub fn extract_data(&self) -> HashMap { let empty = HashMap::default(); - let data = self - .data + + self.data .as_ref() .unwrap_or(&empty) .iter() @@ -137,27 +153,8 @@ impl Config { _ => None, }; v.map(|v| (k.to_owned(), v.to_owned())) - }); - - if self - .core - .as_ref() - .map(|c| c.auto_capitalize) - .unwrap_or(true) - { - data.clone() - .chain(data.clone().filter_map(|(k, v)| { - k.chars() - .next()? - .is_lowercase() - .then(|| (k[0..1].to_uppercase() + &k[1..], v.to_uppercase())) - })) - // We overwrite the auto capitalization - .chain(data.filter_map(|(k, v)| k.chars().next()?.is_uppercase().then_some((k, v)))) - .collect() - } else { - data.collect() - } + }) + .collect() } pub fn extract_translators(&self) -> Result, Box> { @@ -219,13 +216,20 @@ mod tests { use std::path::Path; let conf = Config::from_file(Path::new("./data/config_sample.toml")).unwrap(); - assert_eq!(conf.core.as_ref().unwrap().buffer_size, 12); - assert!(!conf.core.as_ref().unwrap().auto_capitalize); - assert!(!conf.core.as_ref().unwrap().auto_commit); - assert_eq!(conf.core.as_ref().unwrap().page_size, 10); + + assert_eq!( + conf.core.as_ref().map(|core| { + assert_eq!(core.buffer_size.unwrap(), 12); + assert!(!core.auto_capitalize.unwrap()); + assert!(!core.auto_commit.unwrap()); + assert_eq!(core.page_size.unwrap(), 10); + true + }), + Some(true) + ); let data = conf.extract_data(); - assert_eq!(data.keys().len(), 19); + assert_eq!(data.keys().len(), 23); // parsing error let conf = Config::from_file(Path::new("./data/invalid.toml")); diff --git a/clafrica/src/lib.rs b/clafrica/src/lib.rs index d56a451..45439e5 100644 --- a/clafrica/src/lib.rs +++ b/clafrica/src/lib.rs @@ -25,18 +25,26 @@ pub fn run( .map(|(k, v)| [k.as_str(), v.as_str()]) .collect(), ); - let mut processor = Processor::new( - map, - config.core.as_ref().map(|e| e.buffer_size).unwrap_or(8), - ); + let (buffer_size, auto_commit, page_size) = config + .core + .as_ref() + .map(|core| { + ( + core.buffer_size.unwrap_or(32), + core.auto_commit.unwrap_or(false), + core.page_size.unwrap_or(10), + ) + }) + .unwrap_or((32, false, 10)); + let mut processor = Processor::new(map, buffer_size); let translator = Translator::new( config.extract_translation(), config.extract_translators()?, - config.core.as_ref().map(|e| e.auto_commit).unwrap_or(false), + auto_commit, ); let mut is_special_pressed = false; - frontend.set_page_size(config.core.as_ref().map(|e| e.page_size).unwrap_or(10)); + frontend.set_page_size(page_size); frontend.update_screen(rdev::display_size().unwrap()); let (tx, rx) = mpsc::channel();