Skip to content

Commit

Permalink
Refactor key meta (#995)
Browse files Browse the repository at this point in the history
* Refactor key.meta: make_argumented_key

* Refactor key.meta: dynamic sequences

* Refactor key.meta: holdtap

* Refactor key.meta: layers

* Refactor key.meta: led

* Refactor key.meta: macros

* Refactor key.meta: midi

* Refactor key.meta: oneshot

* Refactor key.meta: pimoroni trackball

* Refactor key.meta: rapid fire

* Refactor key.meta: sticky keys

* Refactor key.meta: sticky mod

* Refactor key.meta: tapdance

* Remove key.meta

* Cleanup make_key/make_argumented_key calls
  • Loading branch information
xs5871 authored Jul 1, 2024
1 parent b736166 commit 1004dc6
Show file tree
Hide file tree
Showing 18 changed files with 349 additions and 379 deletions.
2 changes: 1 addition & 1 deletion docs/en/sticky_mod.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sticky_mod = StickyMod()
keyboard.modules.append(sticky_mod)
keyboard.keymap = [
[
KC.SM(kc=KC.TAB, mod=KC.LALT),
KC.SM(key=KC.TAB, mod=KC.LALT),
KC.SM(KC.TAB, KC.LSFT(KC.LALT)),
],
]
Expand Down
36 changes: 15 additions & 21 deletions kmk/extensions/led.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@
from math import e, exp, pi, sin

from kmk.extensions import Extension, InvalidExtensionEnvironment
from kmk.keys import make_argumented_key, make_key
from kmk.keys import Key, make_argumented_key, make_key
from kmk.utils import clamp


class LEDKeyMeta:
def __init__(self, *leds):
class LEDKey(Key):
def __init__(self, *leds, brightness=None, **kwargs):
super().__init__(**kwargs)
self.leds = leds
self.brightness = None


def led_set_key(brightness, *leds):
return LEDKey(*leds, brightness=brightness)


class AnimationModes:
OFF = 0
STATIC = 1
Expand Down Expand Up @@ -63,22 +68,22 @@ def __init__(

make_argumented_key(
names=('LED_TOG',),
validator=self._led_key_validator,
constructor=LEDKey,
on_press=self._key_led_tog,
)
make_argumented_key(
names=('LED_INC',),
validator=self._led_key_validator,
constructor=LEDKey,
on_press=self._key_led_inc,
)
make_argumented_key(
names=('LED_DEC',),
validator=self._led_key_validator,
constructor=LEDKey,
on_press=self._key_led_dec,
)
make_argumented_key(
names=('LED_SET',),
validator=self._led_set_key_validator,
constructor=led_set_key,
on_press=self._key_led_set,
)
make_key(names=('LED_ANI',), on_press=self._key_led_ani)
Expand Down Expand Up @@ -216,17 +221,6 @@ def animate(self):
else:
self.off()

def _led_key_validator(self, *leds):
if leds:
for led in leds:
assert self._leds[led]
return LEDKeyMeta(*leds)

def _led_set_key_validator(self, brightness, *leds):
meta = self._led_key_validator(*leds)
meta.brightness = brightness
return meta

def _key_led_tog(self, *args, **kwargs):
if self.animation_mode == AnimationModes.STATIC_STANDBY:
self.animation_mode = AnimationModes.STATIC
Expand All @@ -236,13 +230,13 @@ def _key_led_tog(self, *args, **kwargs):
self._enabled = not self._enabled

def _key_led_inc(self, key, *args, **kwargs):
self.increase_brightness(leds=key.meta.leds)
self.increase_brightness(leds=key.leds)

def _key_led_dec(self, key, *args, **kwargs):
self.decrease_brightness(leds=key.meta.leds)
self.decrease_brightness(leds=key.leds)

def _key_led_set(self, key, *args, **kwargs):
self.set_brightness(percent=key.meta.brightness, leds=key.meta.leds)
self.set_brightness(percent=key.brightness, leds=key.leds)

def _key_led_ani(self, *args, **kwargs):
self.increase_ani()
Expand Down
29 changes: 17 additions & 12 deletions kmk/extensions/media_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,23 @@ def __init__(self):
# adding the old Apple-specific consumer codes, but again, PRs welcome if the
# lack of them impacts you.

make_key(code=0xE2, names=('AUDIO_MUTE', 'MUTE'), key_type=ConsumerKey)
make_key(code=0xE9, names=('AUDIO_VOL_UP', 'VOLU'), key_type=ConsumerKey)
make_key(code=0xEA, names=('AUDIO_VOL_DOWN', 'VOLD'), key_type=ConsumerKey)
make_key(code=0x6F, names=('BRIGHTNESS_UP', 'BRIU'), key_type=ConsumerKey)
make_key(code=0x70, names=('BRIGHTNESS_DOWN', 'BRID'), key_type=ConsumerKey)
make_key(code=0xB5, names=('MEDIA_NEXT_TRACK', 'MNXT'), key_type=ConsumerKey)
make_key(code=0xB6, names=('MEDIA_PREV_TRACK', 'MPRV'), key_type=ConsumerKey)
make_key(code=0xB7, names=('MEDIA_STOP', 'MSTP'), key_type=ConsumerKey)
make_key(code=0xCD, names=('MEDIA_PLAY_PAUSE', 'MPLY'), key_type=ConsumerKey)
make_key(code=0xB8, names=('MEDIA_EJECT', 'EJCT'), key_type=ConsumerKey)
make_key(code=0xB3, names=('MEDIA_FAST_FORWARD', 'MFFD'), key_type=ConsumerKey)
make_key(code=0xB4, names=('MEDIA_REWIND', 'MRWD'), key_type=ConsumerKey)
codes = (
(0xE2, ('AUDIO_MUTE', 'MUTE')),
(0xE9, ('AUDIO_VOL_UP', 'VOLU')),
(0xEA, ('AUDIO_VOL_DOWN', 'VOLD')),
(0x6F, ('BRIGHTNESS_UP', 'BRIU')),
(0x70, ('BRIGHTNESS_DOWN', 'BRID')),
(0xB5, ('MEDIA_NEXT_TRACK', 'MNXT')),
(0xB6, ('MEDIA_PREV_TRACK', 'MPRV')),
(0xB7, ('MEDIA_STOP', 'MSTP')),
(0xCD, ('MEDIA_PLAY_PAUSE', 'MPLY')),
(0xB8, ('MEDIA_EJECT', 'EJCT')),
(0xB3, ('MEDIA_FAST_FORWARD', 'MFFD')),
(0xB4, ('MEDIA_REWIND', 'MRWD')),
)

for code, names in codes:
make_key(names=names, constructor=ConsumerKey, code=code)

def on_runtime_enable(self, sandbox):
return
Expand Down
79 changes: 28 additions & 51 deletions kmk/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,28 @@ class AX:


def maybe_make_key(
code: Optional[int],
names: Tuple[str, ...],
*args,
**kwargs,
) -> Callable[[str], Key]:
def closure(candidate):
if candidate in names:
return make_key(code=code, names=names, *args, **kwargs)
return make_key(names=names, *args, **kwargs)

return closure


def maybe_make_argumented_key(
validator=lambda *validator_args, **validator_kwargs: object(),
names: Tuple[str, ...] = tuple(), # NOQA
*constructor_args,
**constructor_kwargs,
names: Tuple[str, ...],
constructor: [Key, Callable[[...], Key]],
**kwargs,
) -> Callable[[str], Key]:
def closure(candidate):
if candidate in names:
return make_argumented_key(
validator,
names,
*constructor_args,
**constructor_kwargs,
names=names,
constructor=constructor,
**kwargs,
)

return closure
Expand Down Expand Up @@ -99,9 +96,9 @@ def maybe_make_alpha_key(candidate: str) -> Optional[Key]:
candidate_upper = candidate.upper()
if candidate_upper in ALL_ALPHAS:
return make_key(
code=4 + ALL_ALPHAS.index(candidate_upper),
names=(candidate_upper, candidate.lower()),
key_type=KeyboardKey,
constructor=KeyboardKey,
code=4 + ALL_ALPHAS.index(candidate_upper),
)


Expand All @@ -113,9 +110,9 @@ def maybe_make_numeric_key(candidate: str) -> Optional[Key]:
offset = ALL_NUMBER_ALIASES.index(candidate)

return make_key(
code=30 + offset,
names=(ALL_NUMBERS[offset], ALL_NUMBER_ALIASES[offset]),
key_type=KeyboardKey,
constructor=KeyboardKey,
code=30 + offset,
)


Expand All @@ -137,7 +134,7 @@ def maybe_make_mod_key(candidate: str) -> Optional[Key]:

for code, names in mods:
if candidate in names:
return make_key(code=code, names=names, key_type=ModifierKey)
return make_key(names=names, constructor=ModifierKey, code=code)


def maybe_make_more_ascii(candidate: str) -> Optional[Key]:
Expand All @@ -162,7 +159,7 @@ def maybe_make_more_ascii(candidate: str) -> Optional[Key]:

for code, names in codes:
if candidate in names:
return make_key(code=code, names=names, key_type=KeyboardKey)
return make_key(names=names, constructor=KeyboardKey, code=code)


def maybe_make_fn_key(candidate: str) -> Optional[Key]:
Expand Down Expand Up @@ -195,7 +192,7 @@ def maybe_make_fn_key(candidate: str) -> Optional[Key]:

for code, names in codes:
if candidate in names:
return make_key(code=code, names=names, key_type=KeyboardKey)
return make_key(names=names, constructor=KeyboardKey, code=code)


def maybe_make_navlock_key(candidate: str) -> Optional[Key]:
Expand Down Expand Up @@ -224,7 +221,7 @@ def maybe_make_navlock_key(candidate: str) -> Optional[Key]:

for code, names in codes:
if candidate in names:
return make_key(code=code, names=names, key_type=KeyboardKey)
return make_key(names=names, constructor=KeyboardKey, code=code)


def maybe_make_numpad_key(candidate: str) -> Optional[Key]:
Expand Down Expand Up @@ -253,7 +250,7 @@ def maybe_make_numpad_key(candidate: str) -> Optional[Key]:

for code, names in codes:
if candidate in names:
return make_key(code=code, names=names, key_type=KeyboardKey)
return make_key(names=names, constructor=KeyboardKey, code=code)


def maybe_make_shifted_key(candidate: str) -> Optional[Key]:
Expand Down Expand Up @@ -284,7 +281,7 @@ def maybe_make_shifted_key(candidate: str) -> Optional[Key]:
for code, names in codes:
if candidate in names:
return make_key(
code=code, names=names, key_type=ModifiedKey, modifier=KC.LSFT
names=names, constructor=ModifiedKey, code=code, modifier=KC.LSFT
)


Expand Down Expand Up @@ -315,7 +312,7 @@ def maybe_make_international_key(candidate: str) -> Optional[Key]:

for code, names in codes:
if candidate in names:
return make_key(code=code, names=names, key_type=KeyboardKey)
return make_key(names=names, constructor=KeyboardKey, code=code)


def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
Expand All @@ -341,13 +338,11 @@ def maybe_make_firmware_key(candidate: str) -> Optional[Key]:
maybe_make_numeric_key,
maybe_make_firmware_key,
maybe_make_key(
None,
('BKDL',),
on_press=handlers.bkdl_pressed,
on_release=handlers.bkdl_released,
),
maybe_make_key(
None,
('GESC', 'GRAVE_ESC'),
on_press=handlers.gesc_pressed,
on_release=handlers.gesc_released,
Expand Down Expand Up @@ -444,9 +439,7 @@ def __init__(
self,
on_press: Callable[[object, Key, Keyboard, ...], None] = handlers.passthrough,
on_release: Callable[[object, Key, Keyboard, ...], None] = handlers.passthrough,
meta: object = object(),
):
self.meta = meta
self._on_press = on_press
self._on_release = on_release

Expand All @@ -463,8 +456,6 @@ def on_release(self, keyboard: Keyboard, coord_int: Optional[int] = None) -> Non
class _DefaultKey(Key):
'''Meta class implementing handlers for Keys with HID codes.'''

meta = None

def __init__(self, code: Optional[int] = None):
self.code = code

Expand Down Expand Up @@ -499,7 +490,6 @@ def __call__(self, key: Key) -> Key:


class ModifiedKey(Key):
meta = None
code = -1

def __init__(self, code: [Key, int], modifier: [ModifierKey]):
Expand Down Expand Up @@ -545,18 +535,13 @@ class MouseKey(_DefaultKey):


def make_key(
code: Optional[int] = None,
names: Tuple[str, ...] = tuple(), # NOQA
key_type: Key = Key,
names: Tuple[str, ...],
constructor: Key = Key,
**kwargs,
) -> Key:
'''
Create a new key, aliased by `names` in the KC lookup table.
If a code is not specified, the key is assumed to be a custom
internal key to be handled in a state callback rather than
sent directly to the OS.
Names are globally unique. If a later key is created with
the same name as an existing entry in `KC`, it will overwrite
the existing entry.
Expand All @@ -566,10 +551,7 @@ def make_key(
All **kwargs are passed to the Key constructor
'''

if code is None:
key = key_type(**kwargs)
else:
key = key_type(code, **kwargs)
key = constructor(**kwargs)

for name in names:
KC[name] = key
Expand All @@ -580,20 +562,15 @@ def make_key(
# Argumented keys are implicitly internal, so auto-gen of code
# is almost certainly the best plan here
def make_argumented_key(
validator: object = lambda *validator_args, **validator_kwargs: object(),
names: Tuple[str, ...] = tuple(), # NOQA
*constructor_args,
**constructor_kwargs,
names: Tuple[str, ...],
constructor: [Key, Callable[[...], Key]],
**_kwargs,
) -> Key:

def _argumented_key(*user_args, **user_kwargs) -> Key:
return Key(
*constructor_args,
meta=validator(*user_args, **user_kwargs),
**constructor_kwargs,
)
def argumented_key(*args, **kwargs) -> Key:
return constructor(*args, **kwargs, **_kwargs)

for name in names:
KC[name] = _argumented_key
KC[name] = argumented_key

return _argumented_key
return argumented_key
Loading

0 comments on commit 1004dc6

Please sign in to comment.