diff --git a/boards/klardotsh/threethree_matrix_pyboard.py b/boards/klardotsh/threethree_matrix_pyboard.py index 8eea9aa..b66befc 100644 --- a/boards/klardotsh/threethree_matrix_pyboard.py +++ b/boards/klardotsh/threethree_matrix_pyboard.py @@ -2,7 +2,7 @@ from logging import DEBUG import machine -from kmk.common.consts import DiodeOrientation +from kmk.common.consts import KC, DiodeOrientation from kmk.firmware import Firmware @@ -15,9 +15,9 @@ def main(): diode_orientation = DiodeOrientation.COLUMNS keymap = [ - ['A', 'B', 'C'], - ['D', 'E', 'F'], - ['G', 'H', 'I'], + [KC.ESC, KC.H, KC.BACKSPACE], + [KC.TAB, KC.I, KC.ENTER], + [KC.CTRL, KC.SPACE, KC.SHIFT], ] firmware = Firmware( diff --git a/kmk/common/consts.py b/kmk/common/consts.py index 0dbe5b9..f7776cb 100644 --- a/kmk/common/consts.py +++ b/kmk/common/consts.py @@ -1,3 +1,7 @@ +from kmk.common.types import AttrDict +from kmk.common.util import flatten_dict + + class DiodeOrientation: ''' Orientation of diodes on handwired boards. You can think of: @@ -19,11 +23,30 @@ class KeycodeCategory(type): __dict__, limited to just keys we're likely to care about (though this could be opened up further later). ''' - return { + + hidden = ('to_dict', 'recursive_dict', 'contains') + return AttrDict({ key: getattr(cls, key) for key in dir(cls) - if not key.startswith('_') - } + if not key.startswith('_') and key not in hidden + }) + + @classmethod + def recursive_dict(cls): + ''' + to_dict() executed recursively all the way down a tree + ''' + ret = cls.to_dict() + + for key, val in ret.items(): + try: + nested_ret = val.recursive_dict() + except (AttributeError, NameError): + continue + + ret[key] = nested_ret + + return ret @classmethod def contains(cls, kc): @@ -115,16 +138,19 @@ class Keycodes(KeycodeCategory): KC_X = 27 KC_Y = 28 KC_Z = 29 - KC_1 = 30 - KC_2 = 31 - KC_3 = 32 - KC_4 = 33 - KC_5 = 34 - KC_6 = 35 - KC_7 = 36 - KC_8 = 37 - KC_9 = 38 - KC_0 = 39 + + # Aliases to play nicely with AttrDict, since KC.1 isn't a valid + # attribute key in Python, but KC.N1 is + KC_1 = KC_N1 = 30 + KC_2 = KC_N2 = 31 + KC_3 = KC_N3 = 32 + KC_4 = KC_N4 = 33 + KC_5 = KC_N5 = 34 + KC_6 = KC_N6 = 35 + KC_7 = KC_N7 = 36 + KC_8 = KC_N8 = 37 + KC_9 = KC_N9 = 38 + KC_0 = KC_N0 = 39 KC_ENTER = 40 KC_ESC = 41 @@ -194,6 +220,11 @@ class Keycodes(KeycodeCategory): KC_KP_PERIOD = 99 +ALL_KEYS = KC = AttrDict({ + k.replace('KC_', ''): v + for k, v in flatten_dict(Keycodes.recursive_dict()).items() +}) + char_lookup = { "\n": (Keycodes.Common.KC_ENTER,), "\t": (Keycodes.Common.KC_TAB,), diff --git a/kmk/common/types.py b/kmk/common/types.py new file mode 100644 index 0000000..732741d --- /dev/null +++ b/kmk/common/types.py @@ -0,0 +1,12 @@ +class AttrDict(dict): + ''' + Primitive support for accessing dictionary entries in dot notation. + Mostly for user-facing stuff (allows for `k.KC_ESC` rather than + `k['KC_ESC']`, which gets a bit obnoxious). + + This is read-only on purpose. + ''' + def __getattr__(self, key): + return self[key] + + diff --git a/kmk/common/util.py b/kmk/common/util.py new file mode 100644 index 0000000..35111f6 --- /dev/null +++ b/kmk/common/util.py @@ -0,0 +1,10 @@ +def flatten_dict(d): + items = {} + + for k, v in d.items(): + if isinstance(v, dict): + items.update(flatten_dict(v)) + else: + items[k] = v + + return items