Add key coord combos

Added an option to use key coord in the matrix to make combos.
this allows to press / release combos regardless of layer and Key.
This commit is contained in:
Anton K. (ai Doge) 2022-09-17 17:57:11 -04:00 committed by xs5871
parent ea3f59340d
commit 891cd1a67f
2 changed files with 36 additions and 13 deletions

View File

@ -27,6 +27,7 @@ Optional arguments that customize individual combos:
* `per_key_timeout`: If True, reset timeout on every key press (default for
sequences).
* `timeout`: Set the time window within which the match has to happen in ms.
* `match_coord`: If True, matches key position in the matrix.
## Example Code
```python
@ -43,6 +44,8 @@ make_key(
combos.combos = [
Chord((KC.A, KC.B), KC.LSFT),
Chord((KC.A, KC.B, KC.C), KC.LALT),
Chord((0, 1), KC.ESC, match_coord=True),
Chord((8, 9, 10), KC.MO(4), match_coord=True),
Sequence((KC.LEADER, KC.A, KC.B), KC.C),
Sequence((KC.E, KC.F), KC.MYKEY, timeout=500, per_key_timeout=False, fast_reset=False)
]

View File

@ -1,5 +1,5 @@
try:
from typing import Optional, Tuple
from typing import Optional, Tuple, Union
except ImportError:
pass
from micropython import const
@ -24,14 +24,16 @@ class Combo:
_remaining = []
_timeout = None
_state = _ComboState.IDLE
_match_coord = False
def __init__(
self,
match: Tuple[Key, ...],
match: Tuple[Union[Key, int], ...],
result: Key,
fast_reset=None,
per_key_timeout=None,
timeout=None,
match_coord=None,
):
'''
match: tuple of keys (KC.A, KC.B)
@ -45,22 +47,36 @@ class Combo:
self.per_key_timeout = per_key_timeout
if timeout is not None:
self.timeout = timeout
if match_coord is not None:
self._match_coord = match_coord
def __repr__(self):
return f'{self.__class__.__name__}({[k.code for k in self.match]})'
def matches(self, key):
def matches(self, key: Key, int_coord: int):
raise NotImplementedError
def has_match(self, key: Key, int_coord: int):
return self._match_coord and int_coord in self.match or key in self.match
def insert(self, key: Key, int_coord: int):
if self._match_coord:
self._remaining.insert(0, int_coord)
else:
self._remaining.insert(0, key)
def reset(self):
self._remaining = list(self.match)
class Chord(Combo):
def matches(self, key):
if key in self._remaining:
def matches(self, key: Key, int_coord: int):
if not self._match_coord and key in self._remaining:
self._remaining.remove(key)
return True
elif self._match_coord and int_coord in self._remaining:
self._remaining.remove(int_coord)
return True
else:
return False
@ -70,8 +86,12 @@ class Sequence(Combo):
per_key_timeout = True
timeout = 1000
def matches(self, key):
if self._remaining and self._remaining[0] == key:
def matches(self, key: Key, int_coord: int):
if (
not self._match_coord and self._remaining and self._remaining[0] == key
) or (
self._match_coord and self._remaining and self._remaining[0] == int_coord
):
self._remaining.pop(0)
return True
else:
@ -127,7 +147,7 @@ class Combos(Module):
for combo in self.combos:
if combo._state != _ComboState.MATCHING:
continue
if combo.matches(key):
if combo.matches(key, int_coord):
continue
combo._state = _ComboState.IDLE
if combo._timeout:
@ -182,7 +202,7 @@ class Combos(Module):
for combo in self.combos:
if combo._state != _ComboState.ACTIVE:
continue
if key in combo.match:
if combo.has_match(key, int_coord):
# Deactivate combo if it matches current key.
self.deactivate(keyboard, combo)
@ -190,7 +210,7 @@ class Combos(Module):
self.reset_combo(keyboard, combo)
self._key_buffer = []
else:
combo._remaining.insert(0, key)
combo.insert(key, int_coord)
combo._state = _ComboState.MATCHING
key = combo.result
@ -203,7 +223,7 @@ class Combos(Module):
for combo in self.combos:
if combo._state != _ComboState.MATCHING:
continue
if key not in combo.match:
if not combo.has_match(key, int_coord):
continue
# Combo matches, but first key released before timeout.
@ -216,7 +236,7 @@ class Combos(Module):
if combo.fast_reset:
self.reset_combo(keyboard, combo)
else:
combo._remaining.insert(0, key)
combo.insert(key, int_coord)
combo._state = _ComboState.MATCHING
self.reset(keyboard)
@ -236,7 +256,7 @@ class Combos(Module):
# Anything between first and last key released.
else:
combo._remaining.insert(0, key)
combo.insert(key, int_coord)
# Don't propagate key-release events for keys that have been
# buffered. Append release events only if corresponding press is in