keycodes: pass initial serialize/deserialize test
parent
ad34e2464b
commit
54972955cc
|
|
@ -6,7 +6,8 @@ import operator
|
||||||
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLineEdit, QLabel
|
from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLineEdit, QLabel
|
||||||
|
|
||||||
from keycodes import KEYCODES_SPECIAL, KEYCODES_BASIC, KEYCODES_SHIFTED, KEYCODES_ISO, KEYCODES_BACKLIGHT, \
|
from keycodes import KEYCODES_SPECIAL, KEYCODES_BASIC, KEYCODES_SHIFTED, KEYCODES_ISO, KEYCODES_BACKLIGHT, \
|
||||||
KEYCODES_MEDIA, KEYCODES_USER, QK_LCTL, QK_LSFT, QK_LALT, QK_LGUI, QK_RCTL, QK_RSFT, QK_RALT, QK_RGUI, QK_LAYER_TAP
|
KEYCODES_MEDIA, KEYCODES_USER, QK_LCTL, QK_LSFT, QK_LALT, QK_LGUI, QK_RCTL, QK_RSFT, QK_RALT, QK_RGUI, QK_LAYER_TAP, \
|
||||||
|
MOD_MEH, MOD_HYPR
|
||||||
from util import tr
|
from util import tr
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,6 +40,7 @@ def RCTL(kc): return (QK_RCTL | (kc))
|
||||||
def RSFT(kc): return (QK_RSFT | (kc))
|
def RSFT(kc): return (QK_RSFT | (kc))
|
||||||
def RALT(kc): return (QK_RALT | (kc))
|
def RALT(kc): return (QK_RALT | (kc))
|
||||||
def RGUI(kc): return (QK_RGUI | (kc))
|
def RGUI(kc): return (QK_RGUI | (kc))
|
||||||
|
def C_S(kc): return (QK_LCTL | QK_LSFT | (kc))
|
||||||
def HYPR(kc): return (QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | (kc))
|
def HYPR(kc): return (QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | (kc))
|
||||||
def MEH(kc): return (QK_LCTL | QK_LSFT | QK_LALT | (kc))
|
def MEH(kc): return (QK_LCTL | QK_LSFT | QK_LALT | (kc))
|
||||||
def LCAG(kc): return (QK_LCTL | QK_LALT | QK_LGUI | (kc))
|
def LCAG(kc): return (QK_LCTL | QK_LALT | QK_LGUI | (kc))
|
||||||
|
|
@ -85,6 +87,7 @@ functions = {
|
||||||
"LCTL": LCTL, "LSFT": LSFT, "LALT": LALT, "LGUI": LGUI, "LOPT": LALT, "LCMD": LGUI, "LWIN": LGUI,
|
"LCTL": LCTL, "LSFT": LSFT, "LALT": LALT, "LGUI": LGUI, "LOPT": LALT, "LCMD": LGUI, "LWIN": LGUI,
|
||||||
"RCTL": RCTL, "RSFT": RSFT, "RALT": RALT, "RGUI": RGUI, "ALGR": RALT, "ROPT": RALT, "RCMD": RGUI, "RWIN": RGUI,
|
"RCTL": RCTL, "RSFT": RSFT, "RALT": RALT, "RGUI": RGUI, "ALGR": RALT, "ROPT": RALT, "RCMD": RGUI, "RWIN": RGUI,
|
||||||
"HYPR": HYPR, "MEH": MEH, "LCAG": LCAG, "SGUI": SGUI, "SCMD": SGUI, "SWIN": SGUI,
|
"HYPR": HYPR, "MEH": MEH, "LCAG": LCAG, "SGUI": SGUI, "SCMD": SGUI, "SWIN": SGUI,
|
||||||
|
"C_S": C_S,
|
||||||
"LCA": LCA, "LSA": LSA, "RSA": RSA, "RCS": RCS, "SAGR": RSA,
|
"LCA": LCA, "LSA": LSA, "RSA": RSA, "RCS": RCS, "SAGR": RSA,
|
||||||
"C": LCTL, "S": LSFT, "A": LALT, "G": LGUI,
|
"C": LCTL, "S": LSFT, "A": LALT, "G": LGUI,
|
||||||
"LT": LT, "TO": TO, "MO": MO, "DF": DF, "TG": TG, "OSL": OSL, "LM": LM, "OSM": OSM, "TT": TT, "MT": MT,
|
"LT": LT, "TO": TO, "MO": MO, "DF": DF, "TG": TG, "OSL": OSL, "LM": LM, "OSM": OSM, "TT": TT, "MT": MT,
|
||||||
|
|
@ -99,6 +102,40 @@ functions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AnyKeycode:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.ops = simpleeval.DEFAULT_OPERATORS.copy()
|
||||||
|
self.ops.update({
|
||||||
|
ast.BitOr: operator.or_,
|
||||||
|
ast.BitXor: operator.xor,
|
||||||
|
ast.BitAnd: operator.and_,
|
||||||
|
})
|
||||||
|
self.names = dict()
|
||||||
|
self.prepare_names()
|
||||||
|
|
||||||
|
def prepare_names(self):
|
||||||
|
for kc in KEYCODES_SPECIAL + KEYCODES_BASIC + KEYCODES_SHIFTED + KEYCODES_ISO + KEYCODES_BACKLIGHT + \
|
||||||
|
KEYCODES_MEDIA + KEYCODES_USER:
|
||||||
|
for qmk_id in kc.alias:
|
||||||
|
self.names[qmk_id] = kc.code
|
||||||
|
self.names.update({
|
||||||
|
"MOD_LCTL": MOD_LCTL,
|
||||||
|
"MOD_LSFT": MOD_LSFT,
|
||||||
|
"MOD_LALT": MOD_LALT,
|
||||||
|
"MOD_LGUI": MOD_LGUI,
|
||||||
|
"MOD_RCTL": MOD_RCTL,
|
||||||
|
"MOD_RSFT": MOD_RSFT,
|
||||||
|
"MOD_RALT": MOD_RALT,
|
||||||
|
"MOD_RGUI": MOD_RGUI,
|
||||||
|
"MOD_MEH": MOD_MEH,
|
||||||
|
"MOD_HYPR": MOD_HYPR,
|
||||||
|
})
|
||||||
|
|
||||||
|
def decode(self, s):
|
||||||
|
return simpleeval.simple_eval(s, names=self.names, functions=functions, operators=self.ops)
|
||||||
|
|
||||||
|
|
||||||
class AnyKeycodeDialog(QDialog):
|
class AnyKeycodeDialog(QDialog):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
@ -120,39 +157,15 @@ class AnyKeycodeDialog(QDialog):
|
||||||
self.layout.addWidget(self.buttons)
|
self.layout.addWidget(self.buttons)
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
self.ops = simpleeval.DEFAULT_OPERATORS.copy()
|
self.any = AnyKeycode()
|
||||||
self.ops.update({
|
|
||||||
ast.BitOr: operator.or_,
|
|
||||||
ast.BitXor: operator.xor,
|
|
||||||
ast.BitAnd: operator.and_,
|
|
||||||
})
|
|
||||||
self.names = dict()
|
|
||||||
self.prepare_names()
|
|
||||||
|
|
||||||
self.value = -1
|
self.value = -1
|
||||||
self.on_change()
|
self.on_change()
|
||||||
|
|
||||||
def prepare_names(self):
|
|
||||||
for kc in KEYCODES_SPECIAL + KEYCODES_BASIC + KEYCODES_SHIFTED + KEYCODES_ISO + KEYCODES_BACKLIGHT + \
|
|
||||||
KEYCODES_MEDIA + KEYCODES_USER:
|
|
||||||
for qmk_id in kc.alias:
|
|
||||||
self.names[qmk_id] = kc.code
|
|
||||||
self.names.update({
|
|
||||||
"MOD_LCTL": MOD_LCTL,
|
|
||||||
"MOD_LSFT": MOD_LSFT,
|
|
||||||
"MOD_LALT": MOD_LALT,
|
|
||||||
"MOD_LGUI": MOD_LGUI,
|
|
||||||
"MOD_RCTL": MOD_RCTL,
|
|
||||||
"MOD_RSFT": MOD_RSFT,
|
|
||||||
"MOD_RALT": MOD_RALT,
|
|
||||||
"MOD_RGUI": MOD_RGUI,
|
|
||||||
})
|
|
||||||
|
|
||||||
def on_change(self):
|
def on_change(self):
|
||||||
text = self.txt_entry.text()
|
text = self.txt_entry.text()
|
||||||
value = err = None
|
value = err = None
|
||||||
try:
|
try:
|
||||||
value = simpleeval.simple_eval(text, names=self.names, functions=functions, operators=self.ops)
|
value = self.any.decode(text)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err = str(e)
|
err = str(e)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,13 @@ class Keycode:
|
||||||
if masked:
|
if masked:
|
||||||
self.masked_keycodes.add(code)
|
self.masked_keycodes.add(code)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find(cls, code):
|
||||||
|
for keycode in KEYCODES:
|
||||||
|
if keycode.code == code:
|
||||||
|
return keycode
|
||||||
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def find_outer_keycode(cls, code):
|
def find_outer_keycode(cls, code):
|
||||||
"""
|
"""
|
||||||
|
|
@ -41,10 +48,7 @@ class Keycode:
|
||||||
"""
|
"""
|
||||||
if cls.is_mask(code):
|
if cls.is_mask(code):
|
||||||
code = code & 0xFF00
|
code = code & 0xFF00
|
||||||
for keycode in KEYCODES:
|
return cls.find(code)
|
||||||
if keycode.code == code:
|
|
||||||
return keycode
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def find_by_recorder_alias(cls, alias):
|
def find_by_recorder_alias(cls, alias):
|
||||||
|
|
@ -76,17 +80,31 @@ class Keycode:
|
||||||
return tooltip
|
return tooltip
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def serialize(cls, qmk_id):
|
def serialize(cls, code):
|
||||||
# TODO
|
if not cls.is_mask(code):
|
||||||
pass
|
kc = cls.find(code)
|
||||||
|
if kc is not None:
|
||||||
|
return kc.qmk_id
|
||||||
|
elif cls.is_mask(code):
|
||||||
|
outer = cls.find_outer_keycode(code)
|
||||||
|
inner = cls.find(code & 0xFF)
|
||||||
|
if outer is not None and inner is not None:
|
||||||
|
return outer.qmk_id.replace("(kc)", "({})".format(inner.qmk_id))
|
||||||
|
return code
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def deserialize(cls, val):
|
def deserialize(cls, val):
|
||||||
|
from any_keycode_dialog import AnyKeycode
|
||||||
|
|
||||||
if isinstance(val, int):
|
if isinstance(val, int):
|
||||||
return val
|
return val
|
||||||
if "(" not in val and val in cls.qmk_id_to_keycode:
|
if "(" not in val and val in cls.qmk_id_to_keycode:
|
||||||
return cls.qmk_id_to_keycode[val].code
|
return cls.qmk_id_to_keycode[val].code
|
||||||
# TODO: process macro-like keycodes with () etc
|
anykc = AnyKeycode()
|
||||||
|
try:
|
||||||
|
return anykc.decode(val)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,8 @@ from keycodes import Keycode
|
||||||
class TestKeycode(unittest.TestCase):
|
class TestKeycode(unittest.TestCase):
|
||||||
|
|
||||||
def test_serialize(self):
|
def test_serialize(self):
|
||||||
print(Keycode.serialize(0x100))
|
# at a minimum, we should be able to deserialize/serialize everything
|
||||||
print(Keycode.deserialize("KC_A"))
|
for x in range(2 ** 16):
|
||||||
|
s = Keycode.serialize(x)
|
||||||
|
d = Keycode.deserialize(s)
|
||||||
|
self.assertEqual(d, x, "{} serialized into {} deserialized into {}".format(x, s, d))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue