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:
parent
ea3f59340d
commit
891cd1a67f
@ -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)
|
||||
]
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user