summaryrefslogtreecommitdiff
path: root/Meta
diff options
context:
space:
mode:
authorBen Wiederhake <BenWiederhake.GitHub@gmx.de>2021-01-30 08:39:45 +0100
committerAndreas Kling <kling@serenityos.org>2021-02-01 09:54:32 +0100
commitd47ed358015a83523e1895ec5df21f9226f8ad0c (patch)
tree226c2164dbb1ac6c012d2e4429a47cd1e8d017da /Meta
parent9f60ce4801bb997acf05f7c290c6bcf1144575f1 (diff)
downloadserenity-d47ed358015a83523e1895ec5df21f9226f8ad0c.zip
Meta: Add script that checks consistency of keymaps
Diffstat (limited to 'Meta')
-rwxr-xr-xMeta/lint-ci.sh1
-rwxr-xr-xMeta/lint-keymaps.py128
2 files changed, 129 insertions, 0 deletions
diff --git a/Meta/lint-ci.sh b/Meta/lint-ci.sh
index 2467757df3..ec91e941fd 100755
--- a/Meta/lint-ci.sh
+++ b/Meta/lint-ci.sh
@@ -20,6 +20,7 @@ for cmd in \
Meta/check-style.sh \
Meta/lint-executable-resources.sh \
Meta/lint-ipc-ids.sh \
+ Meta/lint-keymaps.py \
Meta/lint-shell-scripts.sh \
Meta/lint-prettier.sh \
Meta/lint-python.sh; do
diff --git a/Meta/lint-keymaps.py b/Meta/lint-keymaps.py
new file mode 100755
index 0000000000..27508804e4
--- /dev/null
+++ b/Meta/lint-keymaps.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+
+import json
+import os
+import sys
+
+
+PERMITTED_MAPS = ['map', 'shift_map', 'alt_map', 'altgr_map', 'shift_altgr_map']
+REQUIRED_MAPS = ['map', 'shift_map', 'alt_map']
+# See Userland/Libraries/LibKeyboard/CharacterMapFile.cpp
+# and Userland/Libraries/LibKeyboard/CharacterMap.cpp.
+GOOD_MAP_LENGTHS = {90, 128}
+
+
+def report(filename, problem):
+ print('{}: {}'.format(filename, problem))
+
+
+def validate_single_map(filename, mapname, values):
+ all_good = True
+
+ if not isinstance(values, list):
+ report(filename, '"{}" is not an array'.format(mapname))
+ return False # Cannot continue other checks
+
+ if not any(values):
+ report(filename, 'no values set in {}'.format(mapname))
+ all_good = False
+
+ for i, c in enumerate(values):
+ if len(c) > 1:
+ report(filename, 'more than one character ("{}") for charmap index {} of {}'.format(c, i, mapname))
+ all_good = False
+
+ # TODO: Require that a few keys are set?
+
+ if len(values) not in GOOD_MAP_LENGTHS:
+ report(filename, 'length {} of map {} is suspicious. Off-by-one?'.format(len(values), mapname))
+ all_good = False
+
+ return all_good
+
+
+def validate_fullmap(filename, fullmap):
+ all_good = True
+
+ if not isinstance(fullmap, dict):
+ report(filename, 'is not an object')
+ return False # Cannot continue other checks
+
+ for name, map_ in fullmap.items():
+ if name not in PERMITTED_MAPS:
+ report(filename, 'contains unknown entry {}'.format(name))
+ all_good = False
+
+ all_good &= validate_single_map(filename, name, map_)
+
+ for name in REQUIRED_MAPS:
+ if name not in fullmap:
+ report(filename, 'map {} is missing'.format(name))
+ all_good = False
+
+ if 'altgr_map' in fullmap and 'alt_map' in fullmap and fullmap['altgr_map'] == fullmap['alt_map']:
+ report(filename, 'altgr_map is identical to alt_map. Remove altgr_map for the same effect.')
+ report(filename, '(Or add new characters!)')
+ all_good = False
+
+ if 'shift_altgr_map' in fullmap and 'alt_map' in fullmap and fullmap['shift_altgr_map'] == fullmap['alt_map']:
+ report(filename, 'shift_altgr_map is identical to alt_map. Remove shift_altgr_map for the same effect.')
+ report(filename, '(Or add new characters!)')
+ all_good = False
+
+ return all_good
+
+
+def run_with(filenames):
+ passed = 0
+ for filename in filenames:
+ with open(filename, 'r') as fp:
+ fullmap = json.load(fp)
+ if validate_fullmap(filename, fullmap):
+ passed += 1
+
+ print('{} out of {} keymaps passed.'.format(passed, len(filenames)))
+ return passed == len(filenames)
+
+
+def list_files_here():
+ filelist = []
+ for filename in os.listdir():
+ if filename.endswith('.json'):
+ filelist.append(filename)
+ else:
+ report(filename, 'weird filename (ignored)')
+ # Files are in "filesystem" order. Sort them for slightly more
+ # aesthetically pleasing output.
+ filelist.sort()
+ return filelist
+
+
+def run_here():
+ return run_with(list_files_here())
+
+
+def display_for(filename, index):
+ with open(filename, 'r') as fp:
+ fullmap = json.load(fp)
+ for name in PERMITTED_MAPS:
+ c = None
+ if name in fullmap:
+ m = fullmap[name]
+ if len(m) > index and m[index]:
+ c = m[index]
+ if c is None:
+ print('{}: None'.format(name))
+ else:
+ print('{}: "{}"'.format(name, c))
+
+
+if __name__ == '__main__':
+ os.chdir(os.path.dirname(__file__) + "/../Base/res/keymaps/")
+ if len(sys.argv) == 1:
+ exit(0 if run_here() else 1)
+ elif len(sys.argv) == 3:
+ display_for('{}.json'.format(sys.argv[1]), int(sys.argv[2], 0))
+ else:
+ print('USAGE: {} [mapcode index]'.format(sys.argv[0]), file=sys.stderr)
+ exit(1)