2021-12-05 15:24:51 +01:00
|
|
|
import unittest
|
|
|
|
|
|
|
|
from kmk.keys import KC
|
2023-03-03 10:32:41 +01:00
|
|
|
from kmk.modules.holdtap import HoldTap, HoldTapRepeat
|
2021-12-05 15:24:51 +01:00
|
|
|
from kmk.modules.layers import Layers
|
|
|
|
from tests.keyboard_test import KeyboardTest
|
|
|
|
|
|
|
|
|
|
|
|
class TestHoldTap(unittest.TestCase):
|
2023-03-03 10:32:41 +01:00
|
|
|
def setUp(self):
|
|
|
|
KC.clear()
|
|
|
|
|
2023-03-08 21:14:24 +01:00
|
|
|
self.t_within = 2 * KeyboardTest.loop_delay_ms
|
2023-03-13 23:14:49 +01:00
|
|
|
self.t_after = 6 * KeyboardTest.loop_delay_ms
|
|
|
|
tap_time = 5 * KeyboardTest.loop_delay_ms
|
2023-03-08 21:14:24 +01:00
|
|
|
|
|
|
|
# overide default timeouts
|
|
|
|
HoldTap.tap_time = tap_time
|
|
|
|
|
2022-06-10 14:10:42 +02:00
|
|
|
def test_holdtap(self):
|
2023-03-08 21:14:24 +01:00
|
|
|
t_within = self.t_within
|
|
|
|
t_after = self.t_after
|
|
|
|
|
2021-12-05 15:24:51 +01:00
|
|
|
keyboard = KeyboardTest(
|
2023-03-03 10:32:41 +01:00
|
|
|
[Layers(), HoldTap()],
|
2021-12-05 15:24:51 +01:00
|
|
|
[
|
2023-03-08 21:14:24 +01:00
|
|
|
[
|
|
|
|
KC.HT(KC.A, KC.LCTL),
|
|
|
|
KC.LT(1, KC.B),
|
|
|
|
KC.C,
|
|
|
|
KC.D,
|
|
|
|
],
|
2023-02-16 06:48:54 +01:00
|
|
|
[KC.N1, KC.N2, KC.N3, KC.N4],
|
2021-12-05 15:24:51 +01:00
|
|
|
],
|
|
|
|
debug_enabled=False,
|
|
|
|
)
|
|
|
|
|
2023-03-08 21:14:24 +01:00
|
|
|
keyboard.test(
|
|
|
|
'HT tap behaviour', [(0, True), t_within, (0, False)], [{KC.A}, {}]
|
|
|
|
)
|
2021-12-05 15:24:51 +01:00
|
|
|
|
|
|
|
keyboard.test(
|
2023-03-08 21:14:24 +01:00
|
|
|
'HT hold behaviour', [(0, True), t_after, (0, False)], [{KC.LCTL}, {}]
|
2021-12-05 15:24:51 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
# TODO test multiple mods being held
|
|
|
|
|
2023-03-03 10:32:41 +01:00
|
|
|
# HT
|
2021-12-05 15:24:51 +01:00
|
|
|
keyboard.test(
|
2023-03-03 10:32:41 +01:00
|
|
|
'HT within tap time sequential -> tap behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(0, True), t_within, (0, False), (3, True), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.A}, {}, {KC.D}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
2023-03-03 10:32:41 +01:00
|
|
|
'HT within tap time rolling -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(0, True), t_within, (3, True), t_after, (0, False), (3, False)],
|
2022-02-07 19:56:32 +01:00
|
|
|
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.D}, {}],
|
2021-12-05 15:24:51 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
2023-03-03 10:32:41 +01:00
|
|
|
'HT within tap time nested -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(0, True), t_within, (3, True), (3, False), t_after, (0, False)],
|
2022-02-07 19:56:32 +01:00
|
|
|
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.LCTL}, {}],
|
2021-12-05 15:24:51 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
2023-03-03 10:32:41 +01:00
|
|
|
'HT after tap time sequential -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(0, True), t_after, (0, False), (3, True), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.LCTL}, {}, {KC.D}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
2023-03-03 10:32:41 +01:00
|
|
|
'HT after tap time rolling -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(0, True), t_after, (3, True), (0, False), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.D}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
2023-03-03 10:32:41 +01:00
|
|
|
'HT after tap time nested -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(0, True), t_after, (3, True), (3, False), (0, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.LCTL}, {KC.LCTL, KC.D}, {KC.LCTL}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
# LT
|
|
|
|
keyboard.test(
|
|
|
|
'LT within tap time sequential -> tap behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(1, True), t_within, (1, False), (3, True), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.B}, {}, {KC.D}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'LT within tap time rolling -> tap behavior',
|
2023-03-13 23:14:49 +01:00
|
|
|
[(1, True), t_within, (3, True), (1, False), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.B}, {KC.B, KC.D}, {KC.D}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'LT within tap time nested -> tap behavior',
|
2023-03-13 23:14:49 +01:00
|
|
|
[(1, True), t_within, (3, True), (3, False), (1, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.B}, {KC.B, KC.D}, {KC.B}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'LT after tap time sequential -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(1, True), t_after, (1, False), (3, True), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.D}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'LT after tap time rolling -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(1, True), t_after, (3, True), (1, False), (3, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.N4}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'LT after tap time nested -> hold behavior',
|
2023-03-08 21:14:24 +01:00
|
|
|
[(1, True), t_after, (3, True), (3, False), (1, False)],
|
2021-12-05 15:24:51 +01:00
|
|
|
[{KC.N4}, {}],
|
|
|
|
)
|
|
|
|
|
2022-06-10 14:10:42 +02:00
|
|
|
keyboard.test(
|
|
|
|
'LT after tap time nested -> hold behavior',
|
|
|
|
[
|
|
|
|
(0, True),
|
2023-03-08 21:14:24 +01:00
|
|
|
t_after,
|
2022-06-10 14:10:42 +02:00
|
|
|
(1, True),
|
2023-03-08 21:14:24 +01:00
|
|
|
t_after,
|
2022-06-10 14:10:42 +02:00
|
|
|
(3, True),
|
|
|
|
(3, False),
|
|
|
|
(1, False),
|
|
|
|
(0, False),
|
|
|
|
],
|
|
|
|
[{KC.LCTL}, {KC.LCTL, KC.N4}, {KC.LCTL}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_holdtap_chain(self):
|
2023-03-08 21:14:24 +01:00
|
|
|
t_after = self.t_after
|
|
|
|
|
2022-06-10 14:10:42 +02:00
|
|
|
keyboard = KeyboardTest(
|
2023-03-03 10:32:41 +01:00
|
|
|
[HoldTap()],
|
2022-06-10 14:10:42 +02:00
|
|
|
[
|
|
|
|
[
|
|
|
|
KC.N0,
|
2023-03-08 21:14:24 +01:00
|
|
|
KC.HT(KC.N1, KC.LCTL),
|
|
|
|
KC.HT(KC.N2, KC.LSFT, tap_interrupted=True),
|
2023-03-03 10:32:41 +01:00
|
|
|
KC.HT(
|
2022-06-10 14:10:42 +02:00
|
|
|
KC.N3,
|
|
|
|
KC.LALT,
|
|
|
|
prefer_hold=False,
|
|
|
|
tap_interrupted=True,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
debug_enabled=False,
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 0',
|
|
|
|
[(1, True), (2, True), (0, True), (0, False), (2, False), (1, False)],
|
|
|
|
[
|
|
|
|
{KC.LCTL},
|
|
|
|
{KC.LCTL, KC.LSFT},
|
|
|
|
{KC.LCTL, KC.LSFT, KC.N0},
|
|
|
|
{KC.LCTL, KC.LSFT},
|
|
|
|
{KC.LCTL},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 1',
|
|
|
|
[(2, True), (1, True), (0, True), (0, False), (1, False), (2, False)],
|
|
|
|
[
|
2023-03-15 21:59:03 +01:00
|
|
|
{KC.LSFT},
|
2022-06-10 14:10:42 +02:00
|
|
|
{KC.LCTL, KC.LSFT},
|
|
|
|
{KC.LCTL, KC.LSFT, KC.N0},
|
|
|
|
{KC.LCTL, KC.LSFT},
|
|
|
|
{KC.LSFT},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 2',
|
|
|
|
[(1, True), (2, True), (0, True), (1, False), (2, False), (0, False)],
|
|
|
|
[
|
|
|
|
{KC.LCTL},
|
|
|
|
{KC.LCTL, KC.LSFT},
|
|
|
|
{KC.LCTL, KC.LSFT, KC.N0},
|
|
|
|
{KC.LSFT, KC.N0},
|
|
|
|
{KC.N0},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 3',
|
|
|
|
[(1, True), (3, True), (0, True), (0, False), (1, False), (3, False)],
|
|
|
|
[
|
|
|
|
{KC.LCTL},
|
|
|
|
{KC.LCTL, KC.N3},
|
|
|
|
{KC.LCTL, KC.N3, KC.N0},
|
|
|
|
{KC.LCTL, KC.N3},
|
|
|
|
{KC.N3},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 4',
|
|
|
|
[(1, True), (3, True), (0, True), (3, False), (1, False), (0, False)],
|
2022-10-02 18:41:33 +02:00
|
|
|
[
|
|
|
|
{KC.LCTL},
|
|
|
|
{KC.LCTL, KC.N3},
|
|
|
|
{KC.LCTL, KC.N0, KC.N3},
|
|
|
|
{KC.LCTL, KC.N0},
|
|
|
|
{KC.N0},
|
|
|
|
{},
|
|
|
|
],
|
2022-06-10 14:10:42 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 5',
|
|
|
|
[(3, True), (1, True), (0, True), (0, False), (1, False), (3, False)],
|
|
|
|
[
|
2023-03-15 21:59:03 +01:00
|
|
|
{KC.N3},
|
2022-06-10 14:10:42 +02:00
|
|
|
{KC.LCTL, KC.N3},
|
|
|
|
{KC.LCTL, KC.N3, KC.N0},
|
|
|
|
{KC.LCTL, KC.N3},
|
|
|
|
{KC.N3},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 6',
|
|
|
|
[
|
|
|
|
(3, True),
|
|
|
|
(1, True),
|
|
|
|
t_after,
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
(1, False),
|
|
|
|
(3, False),
|
|
|
|
],
|
|
|
|
[
|
2022-07-03 17:33:26 +02:00
|
|
|
{KC.LALT},
|
2022-06-10 14:10:42 +02:00
|
|
|
{KC.LCTL, KC.LALT},
|
|
|
|
{KC.LCTL, KC.LALT, KC.N0},
|
|
|
|
{KC.LCTL, KC.LALT},
|
|
|
|
{KC.LALT},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 7',
|
|
|
|
[
|
|
|
|
(1, True),
|
|
|
|
(3, True),
|
|
|
|
t_after,
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
(1, False),
|
|
|
|
(3, False),
|
|
|
|
],
|
|
|
|
[
|
|
|
|
{KC.LCTL},
|
|
|
|
{KC.LCTL, KC.LALT},
|
|
|
|
{KC.LCTL, KC.LALT, KC.N0},
|
|
|
|
{KC.LCTL, KC.LALT},
|
|
|
|
{KC.LALT},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'chained 8',
|
|
|
|
[(2, True), (3, True), (0, True), (0, False), (2, False), (3, False)],
|
|
|
|
[
|
|
|
|
{KC.LSFT},
|
|
|
|
{KC.LSFT, KC.N3},
|
|
|
|
{KC.LSFT, KC.N3, KC.N0},
|
|
|
|
{KC.LSFT, KC.N3},
|
|
|
|
{KC.N3},
|
|
|
|
{},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
2021-12-05 15:24:51 +01:00
|
|
|
# TODO test TT
|
|
|
|
|
2022-10-11 19:44:37 +02:00
|
|
|
def test_holdtap_repeat(self):
|
2023-03-08 21:14:24 +01:00
|
|
|
t_within = self.t_within
|
|
|
|
t_after = self.t_after
|
|
|
|
|
2022-10-11 19:44:37 +02:00
|
|
|
keyboard = KeyboardTest(
|
2023-03-03 10:32:41 +01:00
|
|
|
[HoldTap()],
|
2022-10-14 17:20:55 +02:00
|
|
|
[
|
|
|
|
[
|
2023-03-08 21:14:24 +01:00
|
|
|
KC.HT(KC.A, KC.B, repeat=HoldTapRepeat.ALL),
|
|
|
|
KC.HT(KC.A, KC.B, repeat=HoldTapRepeat.TAP),
|
|
|
|
KC.HT(KC.A, KC.B, repeat=HoldTapRepeat.HOLD),
|
2022-10-14 17:20:55 +02:00
|
|
|
]
|
|
|
|
],
|
2022-10-11 19:44:37 +02:00
|
|
|
debug_enabled=False,
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'repeat tap',
|
|
|
|
[
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
t_within,
|
|
|
|
(0, True),
|
|
|
|
t_after,
|
|
|
|
(0, False),
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
],
|
|
|
|
[{KC.A}, {}, {KC.A}, {}, {KC.A}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'repeat hold',
|
|
|
|
[
|
|
|
|
(0, True),
|
|
|
|
t_after,
|
|
|
|
(0, False),
|
|
|
|
t_within,
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
],
|
|
|
|
[{KC.B}, {}, {KC.B}, {}, {KC.B}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'no repeat after tap_time',
|
|
|
|
[
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
t_after,
|
|
|
|
(0, True),
|
|
|
|
t_after,
|
|
|
|
(0, False),
|
|
|
|
t_after,
|
|
|
|
(0, True),
|
|
|
|
(0, False),
|
|
|
|
],
|
|
|
|
[{KC.A}, {}, {KC.B}, {}, {KC.A}, {}],
|
|
|
|
)
|
|
|
|
|
2022-10-14 17:20:55 +02:00
|
|
|
keyboard.test(
|
|
|
|
'tap repeat / no hold repeat ',
|
|
|
|
[(1, True), t_after, (1, False), (1, True), (1, False)],
|
|
|
|
[{KC.B}, {}, {KC.A}, {}],
|
|
|
|
)
|
|
|
|
|
|
|
|
keyboard.test(
|
|
|
|
'hold repeat / no tap repeat ',
|
|
|
|
[(2, True), (2, False), (2, True), t_after, (2, False)],
|
|
|
|
[{KC.A}, {}, {KC.B}, {}],
|
|
|
|
)
|