+ progress_bar = noop_progress_bar
+ if not verbose and os.isatty(sys.stdout.fileno()):
+ try:
+ from tqdm import tqdm
+
+ progress_bar = tqdm
+ except ImportError:
+ pass
+
+ return progress_bar
+
+
+class Invocation:
+ def __init__(self, r, m, l, v, o):
+ self.command = ""
+ self.rules = r
+ self.model = m
+ self.layout = l
+ self.variant = v
+ self.option = o
+ self.exitstatus = 77 # default to skipped
+ self.error = None
+ self.keymap = None # The fully compiled keymap
+
+ @property
+ def rmlvo(self):
+ return self.rules, self.model, self.layout, self.variant, self.option
+
+ 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}]")
+ s.append(f' cmd: "{escape(self.command)}"')
+ s.append(f" status: {self.exitstatus}")
+ if self.error:
+ s.append(f' error: "{escape(self.error.strip())}"')
+ 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"]
+ if r is not None:
+ args.append("-rules")
+ args.append("{}".format(r))
+ if m is not None:
+ args.append("-model")
+ args.append("{}".format(m))
+ if l is not None:
+ args.append("-layout")
+ args.append("{}".format(l))
+ if v is not None:
+ args.append("-variant")
+ args.append("{}".format(v))
+ if o is not None:
+ args.append("-option")
+ args.append("{}".format(o))
+
+ xkbcomp_args = ["xkbcomp", "-xkb", "-", "-"]
+
+ self.command = " ".join(args + ["|"] + xkbcomp_args)
+
+ 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,
+ )
+ stdout, stderr = xkbcomp.communicate(stdout)
+ if xkbcomp.returncode != 0:
+ self.error = "failed to compile keymap"
+ self.exitstatus = xkbcomp.returncode
+ else:
+ self.keymap = stdout
+ self.exitstatus = 0