|
2 | 2 | import sys |
3 | 3 | from dataclasses import dataclass |
4 | 4 | from pathlib import Path |
5 | | -from typing import Dict, List, Optional, Set, Type, TypeVar |
| 5 | +from typing import Dict, List, Optional, Set, Type, TypeVar, Union |
6 | 6 |
|
7 | 7 | import click |
8 | 8 | import tomli |
@@ -199,8 +199,47 @@ def __init__( |
199 | 199 | self.layers[Layer.ALTGR]["spce"] = spc["altgr"] |
200 | 200 | self.layers[Layer.ALTGR_SHIFT]["spce"] = spc["altgr_shift"] |
201 | 201 |
|
| 202 | + # Extra mapping |
| 203 | + if mapping := layout_data.get("mapping"): |
| 204 | + self._parse_extra_mapping(mapping) |
| 205 | + |
202 | 206 | self._parse_dead_keys(spc) |
203 | 207 |
|
| 208 | + @staticmethod |
| 209 | + def _parse_key_ref(raw: str) -> Optional[str]: |
| 210 | + """Parse a key reference (e.g. to clone)""" |
| 211 | + if raw.startswith("(") and raw.endswith(")"): |
| 212 | + if (clone := raw[1:-1]) and clone in KEYS: |
| 213 | + return clone |
| 214 | + return None |
| 215 | + |
| 216 | + def _parse_extra_mapping(self, mapping: Dict[str, Union[str, Dict[str, str]]]): |
| 217 | + """Parse a layout dict""" |
| 218 | + layer: Optional[Layer] |
| 219 | + for raw_key, levels in mapping.items(): |
| 220 | + # TODO: parse key in various ways (XKB, Linux keycode) |
| 221 | + if raw_key not in KEYS: |
| 222 | + raise ValueError(f"Unknown key: “{raw_key}”") |
| 223 | + key = raw_key |
| 224 | + # Check for key clone |
| 225 | + if isinstance(levels, str): |
| 226 | + # Check for clone |
| 227 | + if clone := self._parse_key_ref(levels): |
| 228 | + for layer, keys in self.layers.items(): |
| 229 | + if value := keys.get(clone): |
| 230 | + self.layers[layer][key] = value |
| 231 | + continue |
| 232 | + raise ValueError(f"Unsupported key mapping: {raw_key}: {levels}") |
| 233 | + for raw_layer, raw_value in levels.items(): |
| 234 | + if (layer := Layer.parse(raw_layer)) is None: |
| 235 | + raise ValueError(f"Cannot parse layer: “{raw_layer}”") |
| 236 | + if clone := self._parse_key_ref(raw_value): |
| 237 | + if (value := self.layers[layer].get(clone)) is None: |
| 238 | + continue |
| 239 | + else: |
| 240 | + value = raw_value |
| 241 | + self.layers[layer][key] = value |
| 242 | + |
204 | 243 | def _parse_dead_keys(self, spc: Dict[str, str]) -> None: |
205 | 244 | """Build a deadkey dict.""" |
206 | 245 |
|
|
0 commit comments