Skip to content

Commit 18f43de

Browse files
committed
check_layout.py: Check that some keys have a role
1 parent b5f4913 commit 18f43de

File tree

1 file changed

+36
-19
lines changed

1 file changed

+36
-19
lines changed

check_layout.py

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,37 +40,50 @@ def unexpected_keys(keys, symbols, msg):
4040
if len(unexpected) > 0:
4141
warn("%s, unexpected: %s" % (msg, key_list_str(unexpected)))
4242

43-
# Write to [keys] and [dup].
44-
def parse_row_from_et(row, keys, dup):
45-
for key in row:
46-
for attr in key.keys():
43+
def duplicates(keys):
44+
dup = [ k for k, key_elts in keys.items() if len(key_elts) >= 2 ]
45+
if len(dup) > 0:
46+
warn("Duplicate keys: " + key_list_str(dup))
47+
48+
def should_have_role(keys_map, role, keys):
49+
def is_center_key(key):
50+
def center(key_elt): return key_elt.get("key0", key_elt.get("c"))
51+
return any(( center(key_elt) == key for key_elt in keys_map.get(key, []) ))
52+
def key_roles(key):
53+
return ( key_elt.get("role", "normal") for key_elt in keys_map[key] )
54+
for key in keys:
55+
if is_center_key(key) and role not in key_roles(key):
56+
warn("Key '%s' is not on a key with role=\"%s\"" % (key, role))
57+
58+
# Write to [keys], dict of keyvalue to the key elements they appear in
59+
def parse_row_from_et(row, keys):
60+
for key_elt in row:
61+
for attr in key_elt.keys():
4762
if attr in KEY_ATTRIBUTES:
48-
k = key.get(attr).removeprefix("\\")
49-
if k in keys: dup.add(k)
50-
keys.add(k)
63+
k = key_elt.get(attr).removeprefix("\\")
64+
keys.setdefault(k, []).append(key_elt)
5165

5266
def parse_layout(fname):
53-
keys = set()
54-
dup = set()
67+
keys = {}
5568
root = ET.parse(fname).getroot()
5669
if root.tag != "keyboard":
5770
return None
5871
for row in root:
59-
parse_row_from_et(row, keys, dup)
60-
return root, keys, dup
72+
parse_row_from_et(row, keys)
73+
return root, keys
6174

6275
def parse_row(fname):
63-
keys = set()
64-
dup = set()
76+
keys = {}
6577
root = ET.parse(fname).getroot()
6678
if root.tag != "row":
6779
return None
68-
parse_row_from_et(root, keys, dup)
69-
return root, keys, dup
80+
parse_row_from_et(root, keys)
81+
return root, keys
7082

7183
def check_layout(layout):
72-
root, keys, dup = layout
73-
if len(dup) > 0: warn("Duplicate keys: " + key_list_str(dup))
84+
root, keys_map = layout
85+
keys = set(keys_map.keys())
86+
duplicates(keys_map)
7487
missing_some_of(keys, "~!@#$%^&*(){}`[]=\\-_;:/.,?<>'\"+|", "ASCII punctuation")
7588
missing_some_of(keys, "0123456789", "digits")
7689
missing_required(keys, ["backspace", "delete"], "Layout doesn't define some important keys")
@@ -91,8 +104,8 @@ def check_layout(layout):
91104
missing_required(keys, ["shift", "loc capslock"], "Missing important key")
92105
missing_required(keys, ["loc esc", "loc tab"], "Missing programming keys")
93106

94-
_, bottom_row_keys, _ = parse_row("res/xml/bottom_row.xml")
95-
107+
_, bottom_row_keys_map = parse_row("res/xml/bottom_row.xml")
108+
bottom_row_keys = set(bottom_row_keys_map.keys())
96109
if root.get("bottom_row") == "false":
97110
missing_required(keys, bottom_row_keys,
98111
"Layout redefines the bottom row but some important keys are missing")
@@ -103,6 +116,10 @@ def check_layout(layout):
103116
if root.get("script") == None:
104117
warn("Layout doesn't specify a script.")
105118

119+
should_have_role(keys_map, "action",
120+
[ "shift", "ctrl", "fn", "backspace", "enter" ])
121+
should_have_role(keys_map, "space_bar", [ "space" ])
122+
106123
for fname in sorted(glob.glob("srcs/layouts/*.xml")):
107124
layout_id, _ = os.path.splitext(os.path.basename(fname))
108125
if layout_id in KNOWN_NOT_LAYOUT:

0 commit comments

Comments
 (0)