From 5dc329686fd0c63a0d21d098499fbead53e17600 Mon Sep 17 00:00:00 2001 From: rszyma Date: Wed, 23 Aug 2023 05:32:12 +0200 Subject: [PATCH] refactor: parse all deflocalkeys variants regardless of target os (#540) Parse all `deflocalkeys` variants for errors regardless of target OS, but apply only the one based on target OS. This PR fixes https://github.com/rszyma/vscode-kanata/issues/1 ## Checklist - Add documentation to docs/config.adoc - [x] N/A - Add example to cfg_samples/kanata.kbd - [x] N/A - Update error messages - [x] Yes - Added tests, or did manual testing - [x] Yes (manual testing) --- parser/src/cfg/mod.rs | 86 ++++++++++++++++++++++++++---------------- parser/src/keys/mod.rs | 2 + 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/parser/src/cfg/mod.rs b/parser/src/cfg/mod.rs index 9083273d9..33f3f7718 100644 --- a/parser/src/cfg/mod.rs +++ b/parser/src/cfg/mod.rs @@ -404,22 +404,37 @@ pub fn parse_cfg_raw_string( ) } - if let Some(result) = root_exprs - .iter() - .find(gen_first_atom_filter(DEF_LOCAL_KEYS)) - .map(|custom_keys| parse_deflocalkeys(custom_keys)) - { - result?; + let mut local_keys: Option> = None; + clear_custom_str_oscode_mapping(); + for def_local_keys_variant in [ + "deflocalkeys-win", + "deflocalkeys-wintercept", + "deflocalkeys-linux", + ] { + if let Some(result) = root_exprs + .iter() + .find(gen_first_atom_filter(def_local_keys_variant)) + .map(|custom_keys| parse_deflocalkeys(def_local_keys_variant, custom_keys)) + { + let mapping = result?; + if def_local_keys_variant == DEF_LOCAL_KEYS { + local_keys = Some(mapping); + } + } + + if let Some(spanned) = spanned_root_exprs + .iter() + .filter(gen_first_atom_filter_spanned(def_local_keys_variant)) + .nth(1) + { + bail_span!( + spanned, + "Only one {def_local_keys_variant} is allowed, found more. Delete the extras." + ) + } } - if let Some(spanned) = spanned_root_exprs - .iter() - .filter(gen_first_atom_filter_spanned(DEF_LOCAL_KEYS)) - .nth(1) - { - bail_span!( - spanned, - "Only one {DEF_LOCAL_KEYS} is allowed, found more. Delete the extras." - ) + if let Some(mapping) = local_keys { + replace_custom_str_oscode_mapping(&mapping); } let src_expr = root_exprs @@ -782,44 +797,49 @@ fn parse_defcfg(expr: &[SExpr]) -> Result> { } } -/// Parse custom keys from an expression starting with deflocalkeys. Statefully updates the `keys` -/// module using the custom keys parsed. -fn parse_deflocalkeys(expr: &[SExpr]) -> Result<()> { +/// Parse custom keys from an expression starting with deflocalkeys. +fn parse_deflocalkeys( + def_local_keys_variant: &str, + expr: &[SExpr], +) -> Result> { let mut cfg = HashMap::default(); - let mut exprs = check_first_expr(expr.iter(), DEF_LOCAL_KEYS)?; - clear_custom_str_oscode_mapping(); + let mut exprs = check_first_expr(expr.iter(), def_local_keys_variant)?; // Read k-v pairs from the configuration while let Some(key_expr) = exprs.next() { - let key = key_expr - .atom(None) - .ok_or_else(|| anyhow_expr!(key_expr, "No lists are allowed in {DEF_LOCAL_KEYS}"))?; + let key = key_expr.atom(None).ok_or_else(|| { + anyhow_expr!(key_expr, "No lists are allowed in {def_local_keys_variant}") + })?; if str_to_oscode(key).is_some() { bail_expr!( key_expr, - "Cannot use {key} in {DEF_LOCAL_KEYS} because it is a default key name" + "Cannot use {key} in {def_local_keys_variant} because it is a default key name" ); } else if cfg.contains_key(key) { - bail_expr!(key_expr, "Duplicate {key} found in {DEF_LOCAL_KEYS}"); + bail_expr!( + key_expr, + "Duplicate {key} found in {def_local_keys_variant}" + ); } let osc = match exprs.next() { Some(v) => v .atom(None) - .ok_or_else(|| anyhow_expr!(v, "No lists are allowed in {DEF_LOCAL_KEYS}")) + .ok_or_else(|| anyhow_expr!(v, "No lists are allowed in {def_local_keys_variant}")) .and_then(|osc| { - osc.parse::() - .map_err(|_| anyhow_expr!(v, "Unknown number in {DEF_LOCAL_KEYS}: {osc}")) + osc.parse::().map_err(|_| { + anyhow_expr!(v, "Unknown number in {def_local_keys_variant}: {osc}") + }) }) .and_then(|osc| { - OsCode::from_u16(osc) - .ok_or_else(|| anyhow_expr!(v, "Unknown number in {DEF_LOCAL_KEYS}: {osc}")) + OsCode::from_u16(osc).ok_or_else(|| { + anyhow_expr!(v, "Unknown number in {def_local_keys_variant}: {osc}") + }) })?, - None => bail_expr!(key_expr, "Key without a number in {DEF_LOCAL_KEYS}"), + None => bail_expr!(key_expr, "Key without a number in {def_local_keys_variant}"), }; log::debug!("custom mapping: {key} {}", osc.as_u16()); cfg.insert(key.to_owned(), osc); } - replace_custom_str_oscode_mapping(&cfg); - Ok(()) + Ok(cfg) } /// Parse mapped keys from an expression starting with defsrc. Returns the key mapping as well as diff --git a/parser/src/keys/mod.rs b/parser/src/keys/mod.rs index 0b49e541f..9e86fbb46 100644 --- a/parser/src/keys/mod.rs +++ b/parser/src/keys/mod.rs @@ -45,6 +45,8 @@ pub fn replace_custom_str_oscode_mapping(mapping: &HashMap) { pub fn clear_custom_str_oscode_mapping() { let mut local_mapping = CUSTOM_STRS_TO_OSCODES.lock(); local_mapping.clear(); + add_default_str_osc_mappings(&mut local_mapping); + local_mapping.shrink_to_fit(); } /// Used for backwards compatibility. If there is hardcoded key name in `str_to_oscode` that would