Compare commits

...

1 Commits

Author SHA1 Message Date
xs5871
9c1bd210eb
Reduce key dictionary memory footprint
Instead of indexing `Key` objects that have multiple names by each
individual name, index by the set of names. This reduces the size of the
default key dictionary by a factor of between 2 and 3, and as result
also reduces reallocations/defragmentation.
Instead of instantiating all module/extension keys by default, append
them to the `maybe_key`-generator list.
2023-01-31 00:50:54 +00:00
27 changed files with 439 additions and 434 deletions

View File

@ -1,35 +1,42 @@
'''Adds international keys''' '''Adds international keys'''
from kmk.extensions import Extension from kmk.extensions import Extension
from kmk.keys import make_key from kmk.keys import KC, make_key
class International(Extension): class International(Extension):
'''Adds international keys''' '''Adds international keys'''
def __init__(self): def __init__(self):
# International KC._generators.append(self.maybe_make_media_key)
make_key(code=50, names=('NONUS_HASH', 'NUHS'))
make_key(code=100, names=('NONUS_BSLASH', 'NUBS'))
make_key(code=101, names=('APP', 'APPLICATION', 'SEL', 'WINMENU'))
make_key(code=135, names=('INT1', 'RO')) @staticmethod
make_key(code=136, names=('INT2', 'KANA')) def maybe_make_media_key(candidate):
make_key(code=137, names=('INT3', 'JYEN')) codes = (
make_key(code=138, names=('INT4', 'HENK')) (50, ('NONUS_HASH', 'NUHS')),
make_key(code=139, names=('INT5', 'MHEN')) (100, ('NONUS_BSLASH', 'NUBS')),
make_key(code=140, names=('INT6',)) (101, ('APP', 'APPLICATION', 'SEL', 'WINMENU')),
make_key(code=141, names=('INT7',)) (135, ('INT1', 'RO')),
make_key(code=142, names=('INT8',)) (136, ('INT2', 'KANA')),
make_key(code=143, names=('INT9',)) (137, ('INT3', 'JYEN')),
make_key(code=144, names=('LANG1', 'HAEN')) (138, ('INT4', 'HENK')),
make_key(code=145, names=('LANG2', 'HAEJ')) (139, ('INT5', 'MHEN')),
make_key(code=146, names=('LANG3',)) (140, ('INT6',)),
make_key(code=147, names=('LANG4',)) (141, ('INT7',)),
make_key(code=148, names=('LANG5',)) (142, ('INT8',)),
make_key(code=149, names=('LANG6',)) (143, ('INT9',)),
make_key(code=150, names=('LANG7',)) (144, ('LANG1', 'HAEN')),
make_key(code=151, names=('LANG8',)) (145, ('LANG2', 'HAEJ')),
make_key(code=152, names=('LANG9',)) (146, ('LANG3',)),
(147, ('LANG4',)),
(148, ('LANG5',)),
(149, ('LANG6',)),
(150, ('LANG7',)),
(151, ('LANG8',)),
(152, ('LANG9',)),
)
for code, names in codes:
if candidate in names:
return make_key(code=code, names=names)
def on_runtime_enable(self, sandbox): def on_runtime_enable(self, sandbox):
return return

View File

@ -2,7 +2,8 @@ import pwmio
from math import e, exp, pi, sin from math import e, exp, pi, sin
from kmk.extensions import Extension, InvalidExtensionEnvironment from kmk.extensions import Extension, InvalidExtensionEnvironment
from kmk.keys import make_argumented_key, make_key from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key, make_key
from kmk.utils import clamp from kmk.utils import clamp
@ -61,35 +62,51 @@ class LED(Extension):
if user_animation is not None: if user_animation is not None:
self.user_animation = user_animation self.user_animation = user_animation
make_argumented_key( KC._generators.append(self.maybe_make_led_key())
names=('LED_TOG',),
validator=self._led_key_validator, def maybe_make_led_key(self):
on_press=self._key_led_tog, argumented_keys = (
(
('LED_TOG',),
self._key_led_tog,
),
(
('LED_INC',),
self._key_led_inc,
),
(
('LED_DEC',),
self._key_led_dec,
),
(
('LED_SET',),
self._key_led_set,
),
) )
make_argumented_key( keys = (
names=('LED_INC',), (('LED_ANI',), self._key_led_ani),
validator=self._led_key_validator, (('LED_AND',), self._key_led_and),
on_press=self._key_led_inc, (('LED_MODE_PLAIN', 'LED_M_P'), self._key_led_mode_static),
) (('LED_MODE_BREATHE', 'LED_M_B'), self._key_led_mode_breathe),
make_argumented_key(
names=('LED_DEC',),
validator=self._led_key_validator,
on_press=self._key_led_dec,
)
make_argumented_key(
names=('LED_SET',),
validator=self._led_set_key_validator,
on_press=self._key_led_set,
)
make_key(names=('LED_ANI',), on_press=self._key_led_ani)
make_key(names=('LED_AND',), on_press=self._key_led_and)
make_key(
names=('LED_MODE_PLAIN', 'LED_M_P'), on_press=self._key_led_mode_static
)
make_key(
names=('LED_MODE_BREATHE', 'LED_M_B'), on_press=self._key_led_mode_breathe
) )
def closure(candidate):
for names, on_press in argumented_keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=self._led_key_validator,
on_press=on_press,
on_release=handler_passthrough,
)
for names, on_press in keys:
if candidate in names:
return make_key(
names=names, on_press=on_press, on_release=handler_passthrough
)
return closure
def __repr__(self): def __repr__(self):
return f'LED({self._to_dict()})' return f'LED({self._to_dict()})'

View File

@ -1,9 +1,13 @@
from kmk.extensions import Extension from kmk.extensions import Extension
from kmk.keys import make_consumer_key from kmk.keys import KC, make_consumer_key
class MediaKeys(Extension): class MediaKeys(Extension):
def __init__(self): def __init__(self):
KC._generators.append(self.maybe_make_media_key)
@staticmethod
def maybe_make_media_key(candidate):
# Consumer ("media") keys. Most known keys aren't supported here. A much # Consumer ("media") keys. Most known keys aren't supported here. A much
# longer list used to exist in this file, but the codes were almost certainly # longer list used to exist in this file, but the codes were almost certainly
# incorrect, conflicting with each other, or otherwise 'weird'. We'll add them # incorrect, conflicting with each other, or otherwise 'weird'. We'll add them
@ -14,20 +18,23 @@ class MediaKeys(Extension):
# support PC media keys, so I don't know how much value we would get out of # support PC media keys, so I don't know how much value we would get out of
# adding the old Apple-specific consumer codes, but again, PRs welcome if the # adding the old Apple-specific consumer codes, but again, PRs welcome if the
# lack of them impacts you. # lack of them impacts you.
make_consumer_key(code=226, names=('AUDIO_MUTE', 'MUTE')) # 0xE2 codes = (
make_consumer_key(code=233, names=('AUDIO_VOL_UP', 'VOLU')) # 0xE9 (226, ('AUDIO_MUTE', 'MUTE')), # 0xE2
make_consumer_key(code=234, names=('AUDIO_VOL_DOWN', 'VOLD')) # 0xEA (233, ('AUDIO_VOL_UP', 'VOLU')), # 0xE9
make_consumer_key(code=111, names=('BRIGHTNESS_UP', 'BRIU')) # 0x6F (234, ('AUDIO_VOL_DOWN', 'VOLD')), # 0xEA
make_consumer_key(code=112, names=('BRIGHTNESS_DOWN', 'BRID')) # 0x70 (111, ('BRIGHTNESS_UP', 'BRIU')), # 0x6F
make_consumer_key(code=181, names=('MEDIA_NEXT_TRACK', 'MNXT')) # 0xB5 (112, ('BRIGHTNESS_DOWN', 'BRID')), # 0x70
make_consumer_key(code=182, names=('MEDIA_PREV_TRACK', 'MPRV')) # 0xB6 (181, ('MEDIA_NEXT_TRACK', 'MNXT')), # 0xB5
make_consumer_key(code=183, names=('MEDIA_STOP', 'MSTP')) # 0xB7 (182, ('MEDIA_PREV_TRACK', 'MPRV')), # 0xB6
make_consumer_key( (183, ('MEDIA_STOP', 'MSTP')), # 0xB7
code=205, names=('MEDIA_PLAY_PAUSE', 'MPLY') (205, ('MEDIA_PLAY_PAUSE', 'MPLY')), # 0xCD (this may not be right)
) # 0xCD (this may not be right) (184, ('MEDIA_EJECT', 'EJCT')), # 0xB8
make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8 (179, ('MEDIA_FAST_FORWARD', 'MFFD')), # 0xB3
make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3 (180, ('MEDIA_REWIND', 'MRWD')), # 0xB4
make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4 )
for code, names in codes:
if candidate in names:
return make_consumer_key(code=code, names=names)
def on_runtime_enable(self, sandbox): def on_runtime_enable(self, sandbox):
return return

View File

@ -4,7 +4,7 @@ from storage import getmount
from kmk.extensions import Extension from kmk.extensions import Extension
from kmk.handlers.stock import passthrough as handler_passthrough from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key from kmk.keys import KC, make_key
class Color: class Color:
@ -69,16 +69,35 @@ class Rgb_matrix(Extension):
else: else:
self.ledDisplay = ledDisplay self.ledDisplay = ledDisplay
make_key( KC._generators.append(self.maybe_make_peg_rgb_key())
names=('RGB_TOG',), on_press=self._rgb_tog, on_release=handler_passthrough
) def maybe_make_peg_rgb_key(self):
make_key( keys = (
names=('RGB_BRI',), on_press=self._rgb_bri, on_release=handler_passthrough (
) ('RGB_TOG',),
make_key( self._rgb_tog,
names=('RGB_BRD',), on_press=self._rgb_brd, on_release=handler_passthrough ),
(
('RGB_BRI',),
self._rgb_bri,
),
(
('RGB_BRD',),
self._rgb_brd,
),
) )
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names,
on_press=on_press,
on_release=handler_passthrough,
)
return closure
def _rgb_tog(self, *args, **kwargs): def _rgb_tog(self, *args, **kwargs):
if self.enable: if self.enable:
self.off() self.off()

View File

@ -3,7 +3,7 @@ from math import e, exp, pi, sin
from kmk.extensions import Extension from kmk.extensions import Extension
from kmk.handlers.stock import passthrough as handler_passthrough from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key from kmk.keys import KC, make_key
from kmk.kmktime import PeriodicTimer from kmk.kmktime import PeriodicTimer
from kmk.utils import Debug, clamp from kmk.utils import Debug, clamp
@ -157,69 +157,37 @@ class RGB(Extension):
self._substep = 0 self._substep = 0
make_key( KC._generators.append(self.maybe_make_rgb_key())
names=('RGB_TOG',), on_press=self._rgb_tog, on_release=handler_passthrough
) def maybe_make_rgb_key(self):
make_key( keys = (
names=('RGB_HUI',), on_press=self._rgb_hui, on_release=handler_passthrough (('RGB_TOG',), self._rgb_tog),
) (('RGB_HUI',), self._rgb_hui),
make_key( (('RGB_HUD',), self._rgb_hud),
names=('RGB_HUD',), on_press=self._rgb_hud, on_release=handler_passthrough (('RGB_SAI',), self._rgb_sai),
) (('RGB_SAD',), self._rgb_sad),
make_key( (('RGB_VAI',), self._rgb_vai),
names=('RGB_SAI',), on_press=self._rgb_sai, on_release=handler_passthrough (('RGB_VAD',), self._rgb_vad),
) (('RGB_ANI',), self._rgb_ani),
make_key( (('RGB_AND',), self._rgb_and),
names=('RGB_SAD',), on_press=self._rgb_sad, on_release=handler_passthrough (('RGB_MODE_PLAIN', 'RGB_M_P'), self._rgb_mode_static),
) (('RGB_MODE_BREATHE', 'RGB_M_B'), self._rgb_mode_breathe),
make_key( (('RGB_MODE_RAINBOW', 'RGB_M_R'), self._rgb_mode_rainbow),
names=('RGB_VAI',), on_press=self._rgb_vai, on_release=handler_passthrough (('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), self._rgb_mode_breathe_rainbow),
) (('RGB_MODE_SWIRL', 'RGB_M_S'), self._rgb_mode_swirl),
make_key( (('RGB_MODE_KNIGHT', 'RGB_M_K'), self._rgb_mode_knight),
names=('RGB_VAD',), on_press=self._rgb_vad, on_release=handler_passthrough (('RGB_RESET', 'RGB_RST'), self._rgb_reset),
)
make_key(
names=('RGB_ANI',), on_press=self._rgb_ani, on_release=handler_passthrough
)
make_key(
names=('RGB_AND',), on_press=self._rgb_and, on_release=handler_passthrough
)
make_key(
names=('RGB_MODE_PLAIN', 'RGB_M_P'),
on_press=self._rgb_mode_static,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_BREATHE', 'RGB_M_B'),
on_press=self._rgb_mode_breathe,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_RAINBOW', 'RGB_M_R'),
on_press=self._rgb_mode_rainbow,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'),
on_press=self._rgb_mode_breathe_rainbow,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_SWIRL', 'RGB_M_S'),
on_press=self._rgb_mode_swirl,
on_release=handler_passthrough,
)
make_key(
names=('RGB_MODE_KNIGHT', 'RGB_M_K'),
on_press=self._rgb_mode_knight,
on_release=handler_passthrough,
)
make_key(
names=('RGB_RESET', 'RGB_RST'),
on_press=self._rgb_reset,
on_release=handler_passthrough,
) )
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names, on_press=on_press, on_release=handler_passthrough
)
return closure
def on_runtime_enable(self, sandbox): def on_runtime_enable(self, sandbox):
return return

View File

@ -4,7 +4,8 @@ import pwmio
import time import time
from kmk.extensions import Extension, InvalidExtensionEnvironment from kmk.extensions import Extension, InvalidExtensionEnvironment
from kmk.keys import make_key from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_key
class statusLED(Extension): class statusLED(Extension):
@ -32,8 +33,24 @@ class statusLED(Extension):
self.brightness_step = brightness_step self.brightness_step = brightness_step
self.brightness_limit = brightness_limit self.brightness_limit = brightness_limit
make_key(names=('SLED_INC',), on_press=self._key_led_inc) KC._generators.append(self.maybe_make_status_led_key())
make_key(names=('SLED_DEC',), on_press=self._key_led_dec)
def maybe_make_status_led_key(self):
keys = (
(('SLED_INC',), self._key_led_inc),
(('SLED_DEC',), self._key_led_dec),
)
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names,
on_press=on_press,
on_release=handler_passthrough,
)
return closure
def _layer_indicator(self, layer_active, *args, **kwargs): def _layer_indicator(self, layer_active, *args, **kwargs):
''' '''

View File

@ -35,7 +35,7 @@ def simple_key_sequence(seq):
meta=KeySequenceMeta(seq), meta=KeySequenceMeta(seq),
on_press=sequence_press_handler, on_press=sequence_press_handler,
on_release=passthrough, on_release=passthrough,
) )[0]
def send_string(message): def send_string(message):
@ -124,7 +124,7 @@ def unicode_codepoint_sequence(codepoints):
simple_key_sequence(_winc_unicode_sequence(kc_macros, keyboard)), True simple_key_sequence(_winc_unicode_sequence(kc_macros, keyboard)), True
) )
return make_key(on_press=_unicode_sequence) return make_key(on_press=_unicode_sequence)[0]
def _ralt_unicode_sequence(kc_macros, keyboard): def _ralt_unicode_sequence(kc_macros, keyboard):

View File

@ -34,8 +34,8 @@ debug = Debug(__name__)
def maybe_make_key( def maybe_make_key(
code: Optional[int], code: Optional[int] = None,
names: Tuple[str, ...], names: Tuple[str, ...] = tuple(), # NOQA
*args, *args,
**kwargs, **kwargs,
) -> Callable[[str], Key]: ) -> Callable[[str], Key]:
@ -401,6 +401,7 @@ KEY_GENERATORS = (
class KeyAttrDict: class KeyAttrDict:
__cache = {} __cache = {}
_generators = list(KEY_GENERATORS)
def __iter__(self): def __iter__(self):
return self.__cache.__iter__() return self.__cache.__iter__()
@ -419,24 +420,30 @@ class KeyAttrDict:
def clear(self): def clear(self):
self.__cache.clear() self.__cache.clear()
self._generators = list(KEY_GENERATORS)
def __getitem__(self, key: Key): def __getitem__(self, name: str):
try: for names, key in self.__cache.items():
return self.__cache[key] if name in names:
except KeyError: return key
pass
for func in KEY_GENERATORS: for func in self._generators:
maybe_key = func(key) maybe_key = func(name)
if maybe_key: if maybe_key:
break break
else:
raise ValueError(f'Invalid key: {key}') if not maybe_key:
raise ValueError(f'Invalid key: {name}')
key, names = maybe_key
if names:
self.__cache[names] = key
if debug.enabled: if debug.enabled:
debug(f'{key}: {maybe_key}') debug(f'{name}: {key}')
return self.__cache[key] return key
# Global state, will be filled in throughout this file, and # Global state, will be filled in throughout this file, and
@ -671,7 +678,7 @@ class ConsumerKey(Key):
def make_key( def make_key(
code: Optional[int] = None, code: Optional[int] = None,
names: Tuple[str, ...] = tuple(), # NOQA names: Optional[Tuple[str, ...]] = tuple(), # NOQA
type: KeyType = KeyType.SIMPLE, type: KeyType = KeyType.SIMPLE,
**kwargs, **kwargs,
) -> Key: ) -> Key:
@ -713,10 +720,7 @@ def make_key(
key = constructor(code=code, **kwargs) key = constructor(code=code, **kwargs)
for name in names: return key, names
KC[name] = key
return key
def make_mod_key(code: int, names: Tuple[str, ...], *args, **kwargs) -> Key: def make_mod_key(code: int, names: Tuple[str, ...], *args, **kwargs) -> Key:
@ -762,7 +766,4 @@ def make_argumented_key(
'should have been raised.' 'should have been raised.'
) )
for name in names: return _argumented_key, names
KC[name] = _argumented_key
return _argumented_key

View File

@ -1,4 +1,5 @@
from kmk.keys import FIRST_KMK_INTERNAL_KEY, KC, ModifierKey, make_key from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import FIRST_KMK_INTERNAL_KEY, KC, ModifierKey, maybe_make_key
from kmk.modules import Module from kmk.modules import Module
@ -16,12 +17,16 @@ class CapsWord(Module):
self._timeout_key = False self._timeout_key = False
self._cw_active = False self._cw_active = False
self.timeout = timeout self.timeout = timeout
make_key( KC._generators.append(self.maybe_make_capsword_key())
def maybe_make_capsword_key(self):
return maybe_make_key(
names=( names=(
'CAPSWORD', 'CAPSWORD',
'CW', 'CW',
), ),
on_press=self.cw_pressed, on_press=self.cw_pressed,
on_release=handler_passthrough,
) )
def during_bootup(self, keyboard): def during_bootup(self, keyboard):

View File

@ -1,3 +1,4 @@
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, ModifierKey, make_key from kmk.keys import KC, ModifierKey, make_key
from kmk.modules import Module from kmk.modules import Module
@ -12,16 +13,26 @@ class CgSwap(Module):
KC.LGUI: KC.LCTL, KC.LGUI: KC.LCTL,
KC.RGUI: KC.RCTL, KC.RGUI: KC.RCTL,
} }
make_key( KC._generators.append(self.maybe_make_cgswap_key())
names=('CG_SWAP',),
) def maybe_make_cgswap_key(self):
make_key( keys = (
names=('CG_NORM',), (('CG_SWAP',),),
) (('CG_NORM',),),
make_key( (('CG_TOGG',),),
names=('CG_TOGG',),
) )
def closure(candidate):
for names in keys:
if candidate in names:
return make_key(
names=names,
on_press=handler_passthrough,
on_release=handler_passthrough,
)
return closure
def during_bootup(self, keyboard): def during_bootup(self, keyboard):
return return

View File

@ -5,7 +5,7 @@ except ImportError:
from micropython import const from micropython import const
import kmk.handlers.stock as handlers import kmk.handlers.stock as handlers
from kmk.keys import Key, make_key from kmk.keys import KC, Key, maybe_make_key
from kmk.kmk_keyboard import KMKKeyboard from kmk.kmk_keyboard import KMKKeyboard
from kmk.modules import Module from kmk.modules import Module
@ -102,11 +102,12 @@ class Combos(Module):
def __init__(self, combos=[]): def __init__(self, combos=[]):
self.combos = combos self.combos = combos
self._key_buffer = [] self._key_buffer = []
KC._generators.append(
make_key( maybe_make_key(
names=('LEADER', 'LDR'), names=('LEADER', 'LDR'),
on_press=handlers.passthrough, on_press=handlers.passthrough,
on_release=handlers.passthrough, on_release=handlers.passthrough,
)
) )
def during_bootup(self, keyboard): def during_bootup(self, keyboard):

View File

@ -3,6 +3,7 @@ from supervisor import ticks_ms
from collections import namedtuple from collections import namedtuple
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key from kmk.keys import KC, make_argumented_key
from kmk.kmktime import check_deadline, ticks_diff from kmk.kmktime import check_deadline, ticks_diff
from kmk.modules import Module from kmk.modules import Module
@ -45,41 +46,33 @@ class DynamicSequences(Module):
self.index = 0 self.index = 0
self.start_time = 0 self.start_time = 0
self.current_repetition = 0 self.current_repetition = 0
self.last_config_frame = set()
self.timeout = timeout self.timeout = timeout
self.key_interval = key_interval self.key_interval = key_interval
self.use_recorded_speed = use_recorded_speed self.use_recorded_speed = use_recorded_speed
# Create keycodes KC._generators.append(self.maybe_make_sequence_key())
make_argumented_key(
validator=DSMeta, names=('RECORD_SEQUENCE',), on_press=self._record_sequence def maybe_make_sequence_key(self):
keys = (
(('RECORD_SEQUENCE',), DSMeta, self._record_sequence),
(('PLAY_SEQUENCE',), DSMeta, self._play_sequence),
(('SET_SEQUENCE', 'STOP_SEQUENCE'), DSMeta, self._stop_sequence),
(('SET_SEQUENCE_REPETITIONS',), DSMeta, self._set_sequence_repetitions),
(('SET_SEQUENCE_INTERVAL',), DSMeta, self._set_sequence_interval),
) )
make_argumented_key( def closure(candidate):
validator=DSMeta, names=('PLAY_SEQUENCE',), on_press=self._play_sequence for names, validator, on_press in keys:
) if candidate in names:
return make_argumented_key(
names=names,
validator=validator,
on_press=on_press,
on_release=handler_passthrough,
)
make_argumented_key( return closure
validator=DSMeta,
names=(
'SET_SEQUENCE',
'STOP_SEQUENCE',
),
on_press=self._stop_sequence,
)
make_argumented_key(
validator=DSMeta,
names=('SET_SEQUENCE_REPETITIONS',),
on_press=self._set_sequence_repetitions,
)
make_argumented_key(
validator=DSMeta,
names=('SET_SEQUENCE_INTERVAL',),
on_press=self._set_sequence_interval,
)
def _record_sequence(self, key, keyboard, *args, **kwargs): def _record_sequence(self, key, keyboard, *args, **kwargs):
self._stop_sequence(key, keyboard) self._stop_sequence(key, keyboard)

View File

@ -1,6 +1,6 @@
from micropython import const from micropython import const
from kmk.keys import KC, make_argumented_key from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules import Module from kmk.modules import Module
from kmk.utils import Debug from kmk.utils import Debug
@ -55,11 +55,13 @@ class HoldTap(Module):
self.key_buffer = [] self.key_buffer = []
self.key_states = {} self.key_states = {}
if not KC.get('HT'): if not KC.get('HT'):
make_argumented_key( KC._generators.append(
validator=HoldTapKeyMeta, maybe_make_argumented_key(
names=('HT',), validator=HoldTapKeyMeta,
on_press=self.ht_pressed, names=('HT',),
on_release=self.ht_released, on_press=self.ht_pressed,
on_release=self.ht_released,
)
) )
def during_bootup(self, keyboard): def during_bootup(self, keyboard):

View File

@ -1,4 +1,5 @@
'''One layer isn't enough. Adds keys to get to more of them''' '''One layer isn't enough. Adds keys to get to more of them'''
from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key from kmk.keys import KC, make_argumented_key
from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta
from kmk.utils import Debug from kmk.utils import Debug
@ -39,46 +40,31 @@ class Layers(HoldTap):
def __init__(self): def __init__(self):
# Layers # Layers
super().__init__() super().__init__()
make_argumented_key( KC._generators.append(self.maybe_make_layer_key())
validator=layer_key_validator,
names=('MO',), def maybe_make_layer_key(self):
on_press=self._mo_pressed, keys = (
on_release=self._mo_released, (('MO',), layer_key_validator, self._mo_pressed, self._mo_released),
) (('DF',), layer_key_validator, self._df_pressed, handler_passthrough),
make_argumented_key( (('LM',), layer_key_validator, self._lm_pressed, self._lm_released),
validator=layer_key_validator, (('TG',), layer_key_validator, self._tg_pressed, handler_passthrough),
names=('DF',), (('TO',), layer_key_validator, self._to_pressed, handler_passthrough),
on_press=self._df_pressed, (('LT',), layer_key_validator_lt, self.ht_pressed, self.ht_released),
) (('TT',), layer_key_validator_tt, self.ht_pressed, self.ht_released),
make_argumented_key(
validator=layer_key_validator,
names=('LM',),
on_press=self._lm_pressed,
on_release=self._lm_released,
)
make_argumented_key(
validator=layer_key_validator,
names=('TG',),
on_press=self._tg_pressed,
)
make_argumented_key(
validator=layer_key_validator,
names=('TO',),
on_press=self._to_pressed,
)
make_argumented_key(
validator=layer_key_validator_lt,
names=('LT',),
on_press=self.ht_pressed,
on_release=self.ht_released,
)
make_argumented_key(
validator=layer_key_validator_tt,
names=('TT',),
on_press=self.ht_pressed,
on_release=self.ht_released,
) )
def closure(candidate):
for names, validator, on_press, on_release in keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=validator,
on_press=on_press,
on_release=on_release,
)
return closure
def _df_pressed(self, key, keyboard, *args, **kwargs): def _df_pressed(self, key, keyboard, *args, **kwargs):
''' '''
Switches the default layer Switches the default layer

View File

@ -8,7 +8,8 @@ from adafruit_midi.program_change import ProgramChange
from adafruit_midi.start import Start from adafruit_midi.start import Start
from adafruit_midi.stop import Stop from adafruit_midi.stop import Stop
from kmk.keys import make_argumented_key from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import KC, make_argumented_key
from kmk.modules import Module from kmk.modules import Module
@ -21,42 +22,6 @@ class midiNoteValidator:
class MidiKeys(Module): class MidiKeys(Module):
def __init__(self): def __init__(self):
make_argumented_key(
names=('MIDI_CC',),
validator=ControlChange,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_NOTE',),
validator=midiNoteValidator,
on_press=self.note_on,
on_release=self.note_off,
)
make_argumented_key(
names=('MIDI_PB',),
validator=PitchBend,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_PC',),
validator=ProgramChange,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_START',),
validator=Start,
on_press=self.on_press,
)
make_argumented_key(
names=('MIDI_STOP',),
validator=Stop,
on_press=self.on_press,
)
try: try:
self.midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0) self.midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0)
@ -65,6 +30,37 @@ class MidiKeys(Module):
# if debug_enabled: # if debug_enabled:
print('No midi device found.') print('No midi device found.')
KC._generators.append(self.maybe_make_midi_key())
def maybe_make_midi_key(self):
keys = (
(('MIDI_CC',), ControlChange),
(('MIDI_PB',), PitchBend),
(('MIDI_PC',), ProgramChange),
(('MIDI_START',), Start),
(('MIDI_STOP',), Stop),
)
note = ('MIDI_NOTE',)
def closure(candidate):
if candidate in note:
return make_argumented_key(
names=('MIDI_NOTE',),
validator=midiNoteValidator,
on_press=self.note_on,
on_release=self.note_off,
)
for names, validator in keys:
if candidate in names:
return make_argumented_key(
names=names,
validator=validator,
on_press=self.on_press,
on_release=handler_passthrough,
)
return closure
def during_bootup(self, keyboard): def during_bootup(self, keyboard):
return None return None

View File

@ -1,13 +1,15 @@
from kmk.keys import make_argumented_key from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta from kmk.modules.holdtap import HoldTap, HoldTapKeyMeta
class ModTap(HoldTap): class ModTap(HoldTap):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
make_argumented_key( KC._generators.append(
validator=HoldTapKeyMeta, maybe_make_argumented_key(
names=('MT',), validator=HoldTapKeyMeta,
on_press=self.ht_pressed, names=('MT',),
on_release=self.ht_released, on_press=self.ht_pressed,
on_release=self.ht_released,
)
) )

View File

@ -1,7 +1,7 @@
from supervisor import ticks_ms from supervisor import ticks_ms
from kmk.hid import HID_REPORT_SIZES, HIDReportTypes from kmk.hid import HID_REPORT_SIZES, HIDReportTypes
from kmk.keys import make_key from kmk.keys import KC, make_key
from kmk.modules import Module from kmk.modules import Module
@ -34,65 +34,30 @@ class MouseKeys(Module):
self.ac_interval = 100 # Delta ms to apply acceleration self.ac_interval = 100 # Delta ms to apply acceleration
self._next_interval = 0 # Time for next tick interval self._next_interval = 0 # Time for next tick interval
self.move_step = 1 self.move_step = 1
KC._generators.append(self.maybe_make_mouse_key())
make_key( def maybe_make_mouse_key(self):
names=('MB_LMB',), keys = (
on_press=self._mb_lmb_press, (('MB_LMB',), self._mb_lmb_press, self._mb_lmb_release),
on_release=self._mb_lmb_release, (('MB_MMB',), self._mb_mmb_press, self._mb_mmb_release),
) (('MB_RMB',), self._mb_rmb_press, self._mb_rmb_release),
make_key( (('MW_UP',), self._mw_up_press, self._mw_up_release),
names=('MB_MMB',), (('MW_DOWN', 'MW_DN'), self._mw_down_press, self._mw_down_release),
on_press=self._mb_mmb_press, (('MS_UP',), self._ms_up_press, self._ms_up_release),
on_release=self._mb_mmb_release, (('MS_DOWN', 'MS_DN'), self._ms_down_press, self._ms_down_release),
) (('MS_LEFT', 'MS_LT'), self._ms_left_press, self._ms_left_release),
make_key( (('MS_RIGHT', 'MS_RT'), self._ms_right_press, self._ms_right_release),
names=('MB_RMB',),
on_press=self._mb_rmb_press,
on_release=self._mb_rmb_release,
)
make_key(
names=('MW_UP',),
on_press=self._mw_up_press,
on_release=self._mw_up_release,
)
make_key(
names=(
'MW_DOWN',
'MW_DN',
),
on_press=self._mw_down_press,
on_release=self._mw_down_release,
)
make_key(
names=('MS_UP',),
on_press=self._ms_up_press,
on_release=self._ms_up_release,
)
make_key(
names=(
'MS_DOWN',
'MS_DN',
),
on_press=self._ms_down_press,
on_release=self._ms_down_release,
)
make_key(
names=(
'MS_LEFT',
'MS_LT',
),
on_press=self._ms_left_press,
on_release=self._ms_left_release,
)
make_key(
names=(
'MS_RIGHT',
'MS_RT',
),
on_press=self._ms_right_press,
on_release=self._ms_right_release,
) )
def closure(candidate):
for names, on_press, on_release in keys:
if candidate in names:
return make_key(
names=names, on_press=on_press, on_release=on_release
)
return closure
def during_bootup(self, keyboard): def during_bootup(self, keyboard):
return return

View File

@ -1,4 +1,4 @@
from kmk.keys import make_argumented_key from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta
@ -11,11 +11,13 @@ class OneShot(HoldTap):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
make_argumented_key( KC._generators.append(
validator=oneshot_validator, maybe_make_argumented_key(
names=('OS', 'ONESHOT'), validator=oneshot_validator,
on_press=self.osk_pressed, names=('OS', 'ONESHOT'),
on_release=self.osk_released, on_press=self.osk_pressed,
on_release=self.osk_released,
)
) )
def process_key(self, keyboard, current_key, is_pressed, int_coord): def process_key(self, keyboard, current_key, is_pressed, int_coord):

View File

@ -7,7 +7,7 @@ from micropython import const
import math import math
import struct import struct
from kmk.keys import make_argumented_key, make_key from kmk.keys import KC, maybe_make_argumented_key, maybe_make_key
from kmk.kmktime import PeriodicTimer from kmk.kmktime import PeriodicTimer
from kmk.modules import Module from kmk.modules import Module
from kmk.modules.mouse_keys import PointingDevice from kmk.modules.mouse_keys import PointingDevice
@ -198,15 +198,18 @@ class Trackball(Module):
f'Invalid chip ID: 0x{chip_id:04X}, expected 0x{CHIP_ID:04X}' f'Invalid chip ID: 0x{chip_id:04X}, expected 0x{CHIP_ID:04X}'
) )
make_key( KC._generators.append(
names=('TB_MODE', 'TB_NEXT_HANDLER', 'TB_N'), maybe_make_key(
on_press=self._tb_handler_next_press, names=('TB_MODE', 'TB_NEXT_HANDLER', 'TB_N'),
on_press=self._tb_handler_next_press,
)
) )
KC._generators.append(
make_argumented_key( maybe_make_argumented_key(
validator=layer_key_validator, validator=layer_key_validator,
names=('TB_HANDLER', 'TB_H'), names=('TB_HANDLER', 'TB_H'),
on_press=self._tb_handler_press, on_press=self._tb_handler_press,
)
) )
def during_bootup(self, keyboard): def during_bootup(self, keyboard):

View File

@ -5,7 +5,7 @@ from supervisor import ticks_ms
from time import sleep from time import sleep
from kmk.handlers.stock import passthrough as handler_passthrough from kmk.handlers.stock import passthrough as handler_passthrough
from kmk.keys import make_key from kmk.keys import KC, make_key
from kmk.kmktime import check_deadline from kmk.kmktime import check_deadline
from kmk.modules import Module from kmk.modules import Module
@ -20,16 +20,26 @@ class Power(Module):
self._i2c = 0 self._i2c = 0
self._loopcounter = 0 self._loopcounter = 0
make_key( KC._generators.append(self.maybe_make_power_key())
names=('PS_TOG',), on_press=self._ps_tog, on_release=handler_passthrough
) def maybe_make_power_key(self):
make_key( keys = (
names=('PS_ON',), on_press=self._ps_enable, on_release=handler_passthrough (('PS_TOG',), self._ps_tog),
) (('PS_ON',), self._ps_enable),
make_key( (('PS_OFF',), self._ps_disable),
names=('PS_OFF',), on_press=self._ps_disable, on_release=handler_passthrough
) )
def closure(candidate):
for names, on_press in keys:
if candidate in names:
return make_key(
names=names,
on_press=on_press,
on_release=handler_passthrough,
)
return closure
def __repr__(self): def __repr__(self):
return f'Power({self._to_dict()})' return f'Power({self._to_dict()})'

View File

@ -1,6 +1,6 @@
from random import randint from random import randint
from kmk.keys import make_argumented_key from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules import Module from kmk.modules import Module
@ -28,11 +28,13 @@ class RapidFire(Module):
_waiting_keys = [] _waiting_keys = []
def __init__(self): def __init__(self):
make_argumented_key( KC._generators.append(
validator=RapidFireMeta, maybe_make_argumented_key(
names=('RF',), validator=RapidFireMeta,
on_press=self._rf_pressed, names=('RF',),
on_release=self._rf_released, on_press=self._rf_pressed,
on_release=self._rf_released,
)
) )
def _get_repeat(self, key): def _get_repeat(self, key):

View File

@ -1,4 +1,4 @@
from kmk.keys import make_argumented_key from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules import Module from kmk.modules import Module
@ -12,11 +12,13 @@ class StickyMod(Module):
def __init__(self): def __init__(self):
self._active = False self._active = False
self._active_key = None self._active_key = None
make_argumented_key( KC._generators.append(
names=('SM',), maybe_make_argumented_key(
validator=StickyModMeta, names=('SM',),
on_press=self.sm_pressed, validator=StickyModMeta,
on_release=self.sm_released, on_press=self.sm_pressed,
on_release=self.sm_released,
)
) )
def during_bootup(self, keyboard): def during_bootup(self, keyboard):

View File

@ -1,4 +1,4 @@
from kmk.keys import KC, make_argumented_key from kmk.keys import KC, maybe_make_argumented_key
from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta from kmk.modules.holdtap import ActivationType, HoldTap, HoldTapKeyMeta
@ -30,11 +30,13 @@ class TapDanceKeyMeta:
class TapDance(HoldTap): class TapDance(HoldTap):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
make_argumented_key( KC._generators.append(
validator=TapDanceKeyMeta, maybe_make_argumented_key(
names=('TD',), validator=TapDanceKeyMeta,
on_press=self.td_pressed, names=('TD',),
on_release=self.td_released, on_press=self.td_pressed,
on_release=self.td_released,
)
) )
self.td_counts = {} self.td_counts = {}

View File

@ -9,6 +9,9 @@ from tests.keyboard_test import KeyboardTest
class TestHoldTap(unittest.TestCase): class TestHoldTap(unittest.TestCase):
def setUp(self):
KC.clear()
def test_holdtap(self): def test_holdtap(self):
keyboard = KeyboardTest( keyboard = KeyboardTest(
[Layers(), ModTap(), OneShot()], [Layers(), ModTap(), OneShot()],

View File

@ -1,6 +1,6 @@
import unittest import unittest
from kmk.keys import KC, Key, ModifierKey, make_key from kmk.keys import KC, Key, ModifierKey, make_key, maybe_make_key
from tests.keyboard_test import KeyboardTest from tests.keyboard_test import KeyboardTest
@ -131,20 +131,14 @@ class TestKeys_dot(unittest.TestCase):
KC.invalid_key KC.invalid_key
def test_custom_key(self): def test_custom_key(self):
created = make_key( KC._generators.append(
KC.N2.code, maybe_make_key(
names=( KC.N2.code,
'EURO', names=('EURO', ''),
'', has_modifiers={KC.LSFT.code, KC.ROPT.code},
), )
has_modifiers={KC.LSFT.code, KC.ROPT.code},
) )
assert created is KC.get('EURO') assert KC.get('') is KC.get('EURO')
assert created is KC.get('')
def test_match_exactly_case(self):
created = make_key(names=('ThIs_Is_A_StRaNgE_kEy',))
assert created is KC.get('ThIs_Is_A_StRaNgE_kEy')
class TestKeys_index(unittest.TestCase): class TestKeys_index(unittest.TestCase):
@ -176,20 +170,14 @@ class TestKeys_index(unittest.TestCase):
KC['not_a_valid_key'] KC['not_a_valid_key']
def test_custom_key(self): def test_custom_key(self):
created = make_key( KC._generators.append(
KC['N2'].code, maybe_make_key(
names=( KC.N2.code,
'EURO', names=('EURO', ''),
'', has_modifiers={KC.LSFT.code, KC.ROPT.code},
), )
has_modifiers={KC['LSFT'].code, KC['ROPT'].code},
) )
assert created is KC['EURO'] assert KC.get('') is KC.get('EURO')
assert created is KC['']
def test_match_exactly_case(self):
created = make_key(names=('ThIs_Is_A_StRaNgE_kEy',))
assert created is KC['ThIs_Is_A_StRaNgE_kEy']
class TestKeys_get(unittest.TestCase): class TestKeys_get(unittest.TestCase):
@ -224,20 +212,14 @@ class TestKeys_get(unittest.TestCase):
assert KC.get('not_a_valid_key') is None assert KC.get('not_a_valid_key') is None
def test_custom_key(self): def test_custom_key(self):
created = make_key( KC._generators.append(
KC.get('N2').code, maybe_make_key(
names=( KC.N2.code,
'EURO', names=('EURO', ''),
'', has_modifiers={KC.LSFT.code, KC.ROPT.code},
), )
has_modifiers={KC.get('LSFT').code, KC.get('ROPT').code},
) )
assert created is KC.get('EURO') assert KC.get('') is KC.get('EURO')
assert created is KC.get('')
def test_match_exactly_case(self):
created = make_key(names=('ThIs_Is_A_StRaNgE_kEy',))
assert created is KC.get('ThIs_Is_A_StRaNgE_kEy')
def test_underscore(self): def test_underscore(self):
assert KC.get('_') assert KC.get('_')
@ -251,8 +233,8 @@ class TestKeys_instances(unittest.TestCase):
KC.clear() KC.clear()
def test_make_key_new_instance(self): def test_make_key_new_instance(self):
key1 = make_key(code=1) key1, _ = make_key(code=1)
key2 = make_key(code=1) key2, _ = make_key(code=1)
assert key1 is not key2 assert key1 is not key2
assert key1.code == key2.code assert key1.code == key2.code

View File

@ -7,6 +7,7 @@ from tests.keyboard_test import KeyboardTest
class TestLayers(unittest.TestCase): class TestLayers(unittest.TestCase):
def setUp(self): def setUp(self):
KC.clear()
self.kb = KeyboardTest( self.kb = KeyboardTest(
[Layers()], [Layers()],
[ [

View File

@ -9,6 +9,7 @@ from tests.keyboard_test import KeyboardTest
class TestTapDance(unittest.TestCase): class TestTapDance(unittest.TestCase):
def setUp(self): def setUp(self):
KC.clear()
self.keyboard = KeyboardTest( self.keyboard = KeyboardTest(
[Layers(), HoldTap(), TapDance()], [Layers(), HoldTap(), TapDance()],
[ [