macro_recorder: basic macro optimizer
parent
abf62439e4
commit
e5e342d397
|
|
@ -2,7 +2,12 @@
|
||||||
from keycodes import keycode_label
|
from keycodes import keycode_label
|
||||||
|
|
||||||
|
|
||||||
class KeyDown:
|
class BasicAction:
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class KeyDown(BasicAction):
|
||||||
|
|
||||||
def __init__(self, keycode):
|
def __init__(self, keycode):
|
||||||
self.keycode = keycode
|
self.keycode = keycode
|
||||||
|
|
@ -10,8 +15,11 @@ class KeyDown:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Down({})".format(keycode_label(self.keycode.code))
|
return "Down({})".format(keycode_label(self.keycode.code))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, KeyDown) and other.keycode == self.keycode
|
||||||
|
|
||||||
class KeyUp:
|
|
||||||
|
class KeyUp(BasicAction):
|
||||||
|
|
||||||
def __init__(self, keycode):
|
def __init__(self, keycode):
|
||||||
self.keycode = keycode
|
self.keycode = keycode
|
||||||
|
|
@ -19,8 +27,11 @@ class KeyUp:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Up({})".format(keycode_label(self.keycode.code))
|
return "Up({})".format(keycode_label(self.keycode.code))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, KeyUp) and other.keycode == self.keycode
|
||||||
|
|
||||||
class KeyTap:
|
|
||||||
|
class KeyTap(BasicAction):
|
||||||
|
|
||||||
def __init__(self, keycode):
|
def __init__(self, keycode):
|
||||||
self.keycode = keycode
|
self.keycode = keycode
|
||||||
|
|
@ -28,11 +39,17 @@ class KeyTap:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Tap({})".format(keycode_label(self.keycode.code))
|
return "Tap({})".format(keycode_label(self.keycode.code))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, KeyTap) and other.keycode == self.keycode
|
||||||
|
|
||||||
class KeyString:
|
|
||||||
|
class KeyString(BasicAction):
|
||||||
|
|
||||||
def __init__(self, string):
|
def __init__(self, string):
|
||||||
self.string = string
|
self.string = string
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "SendString({})".format(self.string)
|
return "SendString({})".format(self.string)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return isinstance(other, KeyString) and other.string == self.string
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
from macro_key import KeyUp, KeyDown, KeyTap
|
||||||
|
|
||||||
|
|
||||||
|
def remove_repeats(sequence):
|
||||||
|
""" Removes exact repetition, i.e. two Down or two Up of the same key """
|
||||||
|
out = []
|
||||||
|
for k in sequence:
|
||||||
|
if out and (isinstance(k, KeyDown) or isinstance(k, KeyUp)) and k == out[-1]:
|
||||||
|
continue
|
||||||
|
out.append(k)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def replace_with_tap(sequence):
|
||||||
|
""" Replaces a sequence of Down/Up with a Tap """
|
||||||
|
out = []
|
||||||
|
sequence = sequence[:]
|
||||||
|
while len(sequence) > 0:
|
||||||
|
if len(sequence) >= 2 and isinstance(sequence[0], KeyDown) and isinstance(sequence[1], KeyUp) and \
|
||||||
|
sequence[0].keycode == sequence[1].keycode:
|
||||||
|
key = KeyTap(sequence[0].keycode)
|
||||||
|
out.append(key)
|
||||||
|
sequence.pop(0)
|
||||||
|
sequence.pop(0)
|
||||||
|
else:
|
||||||
|
out.append(sequence[0])
|
||||||
|
sequence.pop(0)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def macro_optimize(sequence):
|
||||||
|
sequence = remove_repeats(sequence)
|
||||||
|
sequence = replace_with_tap(sequence)
|
||||||
|
return sequence
|
||||||
|
|
@ -9,6 +9,7 @@ from fbs_runtime.application_context import is_frozen
|
||||||
from basic_editor import BasicEditor
|
from basic_editor import BasicEditor
|
||||||
from keycodes import KEYCODES_BASIC
|
from keycodes import KEYCODES_BASIC
|
||||||
from macro_key import KeyDown, KeyUp
|
from macro_key import KeyDown, KeyUp
|
||||||
|
from macro_optimizer import macro_optimize
|
||||||
from util import tr
|
from util import tr
|
||||||
from vial_device import VialKeyboard
|
from vial_device import VialKeyboard
|
||||||
|
|
||||||
|
|
@ -202,6 +203,7 @@ class MacroRecorder(BasicEditor):
|
||||||
self.recorder.start()
|
self.recorder.start()
|
||||||
|
|
||||||
def on_stop(self):
|
def on_stop(self):
|
||||||
|
self.keystrokes = macro_optimize(self.keystrokes)
|
||||||
print(self.keystrokes)
|
print(self.keystrokes)
|
||||||
|
|
||||||
def on_keystroke(self, keystroke):
|
def on_keystroke(self, keystroke):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from keycodes import find_keycode
|
||||||
|
from macro_key import KeyDown, KeyTap
|
||||||
|
from macro_optimizer import remove_repeats
|
||||||
|
|
||||||
|
|
||||||
|
KC_A = find_keycode(0x04)
|
||||||
|
KC_B = find_keycode(0x05)
|
||||||
|
KC_C = find_keycode(0x06)
|
||||||
|
|
||||||
|
|
||||||
|
class TestMacro(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_remove_repeats(self):
|
||||||
|
self.assertEqual(remove_repeats([KeyDown(KC_A), KeyDown(KC_A)]), [KeyDown(KC_A)])
|
||||||
|
self.assertEqual(remove_repeats([KeyDown(KC_A), KeyDown(KC_B), KeyDown(KC_B), KeyDown(KC_C), KeyDown(KC_C)]),
|
||||||
|
[KeyDown(KC_A), KeyDown(KC_B), KeyDown(KC_C)])
|
||||||
|
|
||||||
|
# don't remove repeated taps
|
||||||
|
self.assertEqual(remove_repeats([KeyTap(KC_A), KeyTap(KC_A)]), [KeyTap(KC_A), KeyTap(KC_A)])
|
||||||
Loading…
Reference in New Issue