From 12eb959d92e7137ef2d4e22e04d5a302070f25ac Mon Sep 17 00:00:00 2001 From: xs5871 Date: Sun, 5 Nov 2023 18:19:50 +0000 Subject: [PATCH] Fix bug where active layer list can become empty * Fix bug where active layer list can become empty by combining MO and TO, * add missing debug hook to `_to_pressed`, * add some unit tests for the layer module, * fix unit test result for empty reports. --- kmk/modules/layers.py | 21 ++++----- tests/keyboard_test.py | 4 +- tests/test_layers.py | 99 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 13 deletions(-) diff --git a/kmk/modules/layers.py b/kmk/modules/layers.py index 89a4cf248..c14eb0f22 100644 --- a/kmk/modules/layers.py +++ b/kmk/modules/layers.py @@ -126,7 +126,7 @@ def _to_pressed(self, key, keyboard, *args, **kwargs): ''' self._active_combo = None keyboard.active_layers.clear() - keyboard.active_layers.insert(0, key.meta.layer) + self.activate_layer(keyboard, key.meta.layer) def _print_debug(self, keyboard): if debug.enabled: @@ -150,15 +150,16 @@ def deactivate_layer(self, keyboard, layer): # This also resolves an issue where using DF() on a layer # triggered by MO() and then defaulting to the MO()'s layer # would result in no layers active. - try: - del_idx = keyboard.active_layers.index(layer) - del keyboard.active_layers[del_idx] - except ValueError: - if debug.enabled: - debug(f'_mo_released: layer {layer} not active') - - if self.combo_layers: - self._deactivate_combo_layer(keyboard, layer) + if len(keyboard.active_layers) > 1: + try: + idx = keyboard.active_layers.index(layer) + del keyboard.active_layers[idx] + except ValueError: + if debug.enabled: + debug(f'_mo_released: layer {layer} not active') + + if self.combo_layers: + self._deactivate_combo_layer(keyboard, layer) self._print_debug(keyboard) diff --git a/tests/keyboard_test.py b/tests/keyboard_test.py index d5018c688..346072aac 100644 --- a/tests/keyboard_test.py +++ b/tests/keyboard_test.py @@ -94,8 +94,8 @@ def test(self, testname, key_events, assert_reports, hid_send): try: hid_report = hid_reports[i] except IndexError: - report_mods = None - report_keys = [None] + report_mods = 0 + report_keys = set() else: report_mods = hid_report[0] report_keys = {code for code in hid_report[2:] if code != 0} diff --git a/tests/test_layers.py b/tests/test_layers.py index ae26acfd1..6239450d4 100644 --- a/tests/test_layers.py +++ b/tests/test_layers.py @@ -5,7 +5,7 @@ from tests.keyboard_test import KeyboardTest -class TestLayers(unittest.TestCase): +class TestHoldTapLayers(unittest.TestCase): def setUp(self): self.kb = KeyboardTest( [Layers()], @@ -48,5 +48,102 @@ def test_layertap(self): ) +class TestLayers(unittest.TestCase): + def setUp(self): + self.kb = KeyboardTest( + [Layers()], + [ + [ + KC.N0, + KC.DF(2), + KC.MO(1), + KC.TG(1), + KC.TO(2), + ], + [KC.N1, KC.DF(0), None, KC.TRNS, KC.TO(1)], + [KC.N2, KC.DF(0)], + ], + debug_enabled=False, + ) + + def test_df_layer(self): + self.kb.test( + '', + [(1, True), (0, True)], + [{KC.N2}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [2]) + self.kb.test( + '', + [(1, False), (0, False)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [2]) + self.kb.test('', [(1, True), (1, False)], [{}]) + + def test_mo_layer(self): + self.assertEqual(self.kb.keyboard.active_layers, [0]) + self.kb.test( + '', + [(2, True), (0, True)], + [{KC.N1}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [1, 0]) + self.kb.test( + '', + [(2, False), (0, False)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [0]) + self.kb.test( + '', + [(2, True), (4, True)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [1]) + self.kb.test( + '', + [(2, False), (4, False)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [1]) + self.kb.test('', [(1, True), (1, False)], [{}]) + + def test_tg_layer(self): + self.kb.test( + '', + [(3, True), (0, True)], + [{KC.N1}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [1, 0]) + self.kb.test( + '', + [(3, False), (0, False)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [1, 0]) + self.kb.test( + '', + [(3, True)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [0]) + + def test_to_layer(self): + self.kb.test( + '', + [(4, True), (0, True)], + [{KC.N2}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [2]) + self.kb.test( + '', + [(4, False), (0, False)], + [{}], + ) + self.assertEqual(self.kb.keyboard.active_layers, [2]) + self.kb.test('', [(1, True), (1, False)], [{}]) + + if __name__ == '__main__': unittest.main()