verbose = False
-DEFAULT_RULES_XML = '@XKB_CONFIG_ROOT@/rules/evdev.xml'
+DEFAULT_RULES_XML = "@XKB_CONFIG_ROOT@/rules/evdev.xml"
# Meson needs to fill this in so we can call the tool in the buildir.
-EXTRA_PATH = '@MESON_BUILD_ROOT@'
-os.environ['PATH'] = ':'.join([EXTRA_PATH, os.getenv('PATH')])
+EXTRA_PATH = "@MESON_BUILD_ROOT@"
+os.environ["PATH"] = ":".join([EXTRA_PATH, os.getenv("PATH")])
def escape(s):
if not verbose and os.isatty(sys.stdout.fileno()):
try:
from tqdm import tqdm
+
progress_bar = tqdm
except ImportError:
pass
def __str__(self):
s = []
rmlvo = [x or "" for x in self.rmlvo]
- rmlvo = ', '.join([f'"{x}"' for x in rmlvo])
- s.append(f'- rmlvo: [{rmlvo}]')
+ rmlvo = ", ".join([f'"{x}"' for x in rmlvo])
+ s.append(f"- rmlvo: [{rmlvo}]")
s.append(f' cmd: "{escape(self.command)}"')
- s.append(f' status: {self.exitstatus}')
+ s.append(f" status: {self.exitstatus}")
if self.error:
s.append(f' error: "{escape(self.error.strip())}"')
- return '\n'.join(s)
+ return "\n".join(s)
def run(self):
raise NotImplementedError
class XkbCompInvocation(Invocation):
def run(self):
r, m, l, v, o = self.rmlvo
- args = ['setxkbmap', '-print']
+ args = ["setxkbmap", "-print"]
if r is not None:
- args.append('-rules')
- args.append('{}'.format(r))
+ args.append("-rules")
+ args.append("{}".format(r))
if m is not None:
- args.append('-model')
- args.append('{}'.format(m))
+ args.append("-model")
+ args.append("{}".format(m))
if l is not None:
- args.append('-layout')
- args.append('{}'.format(l))
+ args.append("-layout")
+ args.append("{}".format(l))
if v is not None:
- args.append('-variant')
- args.append('{}'.format(v))
+ args.append("-variant")
+ args.append("{}".format(v))
if o is not None:
- args.append('-option')
- args.append('{}'.format(o))
+ args.append("-option")
+ args.append("{}".format(o))
- xkbcomp_args = ['xkbcomp', '-xkb', '-', '-']
+ xkbcomp_args = ["xkbcomp", "-xkb", "-", "-"]
self.command = " ".join(args + ["|"] + xkbcomp_args)
- setxkbmap = subprocess.Popen(args, stdout=subprocess.PIPE,
- stderr=subprocess.PIPE, universal_newlines=True)
+ setxkbmap = subprocess.Popen(
+ args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ )
stdout, stderr = setxkbmap.communicate()
if "Cannot open display" in stderr:
self.error = stderr
self.exitstatus = 90
else:
- xkbcomp = subprocess.Popen(xkbcomp_args, stdin=subprocess.PIPE,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- universal_newlines=True)
+ xkbcomp = subprocess.Popen(
+ xkbcomp_args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ )
stdout, stderr = xkbcomp.communicate(stdout)
if xkbcomp.returncode != 0:
self.error = "failed to compile keymap"
class XkbcommonInvocation(Invocation):
+ UNRECOGNIZED_KEYSYM_ERROR = "XKB-107"
+
def run(self):
r, m, l, v, o = self.rmlvo
args = [
- 'xkbcli-compile-keymap', # this is run in the builddir
- '--verbose',
- '--rules', r,
- '--model', m,
- '--layout', l,
+ "xkbcli-compile-keymap", # this is run in the builddir
+ "--verbose",
+ "--rules",
+ r,
+ "--model",
+ m,
+ "--layout",
+ l,
]
if v is not None:
- args += ['--variant', v]
+ args += ["--variant", v]
if o is not None:
- args += ['--options', o]
+ args += ["--options", o]
self.command = " ".join(args)
try:
- output = subprocess.check_output(args, stderr=subprocess.STDOUT,
- universal_newlines=True)
- if "unrecognized keysym" in output:
- for line in output.split('\n'):
- if "unrecognized keysym" in line:
+ output = subprocess.check_output(
+ args, stderr=subprocess.STDOUT, universal_newlines=True
+ )
+ if self.UNRECOGNIZED_KEYSYM_ERROR in output:
+ for line in output.split("\n"):
+ if self.UNRECOGNIZED_KEYSYM_ERROR in line:
self.error = line
self.exitstatus = 99 # tool doesn't generate this one
else:
def xkbcommontool(rmlvo):
try:
- r = rmlvo.get('r', 'evdev')
- m = rmlvo.get('m', 'pc105')
- l = rmlvo.get('l', 'us')
- v = rmlvo.get('v', None)
- o = rmlvo.get('o', None)
+ r = rmlvo.get("r", "evdev")
+ m = rmlvo.get("m", "pc105")
+ l = rmlvo.get("l", "us")
+ v = rmlvo.get("v", None)
+ o = rmlvo.get("o", None)
tool = XkbcommonInvocation(r, m, l, v, o)
tool.run()
return tool
def xkbcomp(rmlvo):
try:
- r = rmlvo.get('r', 'evdev')
- m = rmlvo.get('m', 'pc105')
- l = rmlvo.get('l', 'us')
- v = rmlvo.get('v', None)
- o = rmlvo.get('o', None)
+ r = rmlvo.get("r", "evdev")
+ m = rmlvo.get("m", "pc105")
+ l = rmlvo.get("l", "us")
+ v = rmlvo.get("v", None)
+ o = rmlvo.get("o", None)
tool = XkbCompInvocation(r, m, l, v, o)
tool.run()
return tool
def parse(path):
root = ET.fromstring(open(path).read())
- layouts = root.findall('layoutList/layout')
+ layouts = root.findall("layoutList/layout")
- options = [
- e.text
- for e in root.findall('optionList/group/option/configItem/name')
- ]
+ options = [e.text for e in root.findall("optionList/group/option/configItem/name")]
combos = []
for l in layouts:
- layout = l.find('configItem/name').text
- combos.append({'l': layout})
+ layout = l.find("configItem/name").text
+ combos.append({"l": layout})
- variants = l.findall('variantList/variant')
+ variants = l.findall("variantList/variant")
for v in variants:
- variant = v.find('configItem/name').text
+ variant = v.find("configItem/name").text
- combos.append({'l': layout, 'v': variant})
+ combos.append({"l": layout, "v": variant})
for option in options:
- combos.append({'l': layout, 'v': variant, 'o': option})
+ combos.append({"l": layout, "v": variant, "o": option})
return combos
keymap_file = fname
if keymap_file_fd:
keymap_file_fd.close()
- keymap_file_fd = open(keymap_file, 'a')
+ keymap_file_fd = open(keymap_file, "a")
- rmlvo = ', '.join([x or '' for x in invocation.rmlvo])
+ rmlvo = ", ".join([x or "" for x in invocation.rmlvo])
print(f"// {rmlvo}", file=keymap_file_fd)
print(invocation.keymap, file=keymap_file_fd)
keymap_file_fd.flush()
global verbose
tools = {
- 'libxkbcommon': xkbcommontool,
- 'xkbcomp': xkbcomp,
+ "libxkbcommon": xkbcommontool,
+ "xkbcomp": xkbcomp,
}
parser = argparse.ArgumentParser(
- description='Tool to test all layout/variant/option combinations.'
+ description="""
+ This tool compiles a keymap for each layout, variant and
+ options combination in the given rules XML file. The output
+ of this tool is YAML, use your favorite YAML parser to
+ extract error messages. Errors are printed to stderr.
+ """
+ )
+ parser.add_argument(
+ "path",
+ metavar="/path/to/evdev.xml",
+ nargs="?",
+ type=str,
+ default=DEFAULT_RULES_XML,
+ help="Path to xkeyboard-config's evdev.xml",
+ )
+ parser.add_argument(
+ "--tool",
+ choices=tools.keys(),
+ type=str,
+ default="libxkbcommon",
+ help="parsing tool to use",
+ )
+ parser.add_argument(
+ "--jobs",
+ "-j",
+ type=int,
+ default=os.cpu_count() * 4,
+ help="number of processes to use",
+ )
+ parser.add_argument("--verbose", "-v", default=False, action="store_true")
+ parser.add_argument(
+ "--keymap-output-dir",
+ default=None,
+ type=str,
+ help="Directory to print compiled keymaps to",
+ )
+ parser.add_argument(
+ "--layout", default=None, type=str, help="Only test the given layout"
+ )
+ parser.add_argument(
+ "--variant", default=None, type=str, help="Only test the given variant"
+ )
+ parser.add_argument(
+ "--option", default=None, type=str, help="Only test the given option"
)
- parser.add_argument('path', metavar='/path/to/evdev.xml',
- nargs='?', type=str,
- default=DEFAULT_RULES_XML,
- help='Path to xkeyboard-config\'s evdev.xml')
- parser.add_argument('--tool', choices=tools.keys(),
- type=str, default='libxkbcommon',
- help='parsing tool to use')
- parser.add_argument('--jobs', '-j', type=int,
- default=os.cpu_count() * 4,
- help='number of processes to use')
- parser.add_argument('--verbose', '-v', default=False, action="store_true")
- parser.add_argument('--keymap-output-dir', default=None, type=str,
- help='Directory to print compiled keymaps to')
- parser.add_argument('--layout', default=None, type=str,
- help='Only test the given layout')
- parser.add_argument('--variant', default=None, type=str,
- help='Only test the given variant')
- parser.add_argument('--option', default=None, type=str,
- help='Only test the given option')
args = parser.parse_args()
tool = tools[args.tool]
if any([args.layout, args.variant, args.option]):
- combos = [{
- 'l': args.layout,
- 'v': args.variant,
- 'o': args.option,
- }]
+ combos = [
+ {
+ "l": args.layout,
+ "v": args.variant,
+ "o": args.option,
+ }
+ ]
else:
combos = parse(args.path)
failed = run(combos, tool, args.jobs, keymapdir)
sys.exit(failed)
-if __name__ == '__main__':
+if __name__ == "__main__":
try:
main(sys.argv)
except KeyboardInterrupt:
- print('# Exiting after Ctrl+C')
+ print("# Exiting after Ctrl+C")