Skip to content

Commit

Permalink
refactor: parse all deflocalkeys variants regardless of target os (#540)
Browse files Browse the repository at this point in the history
Parse all `deflocalkeys` variants for errors regardless of target OS,
but apply only the one based on target OS.

This PR fixes rszyma/vscode-kanata#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)
  • Loading branch information
rszyma committed Aug 23, 2023
1 parent da05276 commit 5dc3296
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 33 deletions.
86 changes: 53 additions & 33 deletions parser/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<HashMap<String, OsCode>> = 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
Expand Down Expand Up @@ -782,44 +797,49 @@ fn parse_defcfg(expr: &[SExpr]) -> Result<HashMap<String, String>> {
}
}

/// 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<HashMap<String, OsCode>> {
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::<u16>()
.map_err(|_| anyhow_expr!(v, "Unknown number in {DEF_LOCAL_KEYS}: {osc}"))
osc.parse::<u16>().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
Expand Down
2 changes: 2 additions & 0 deletions parser/src/keys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub fn replace_custom_str_oscode_mapping(mapping: &HashMap<String, OsCode>) {
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
Expand Down

0 comments on commit 5dc3296

Please sign in to comment.