diff --git a/util.py b/util.py new file mode 100644 index 0000000..bcc71ed --- /dev/null +++ b/util.py @@ -0,0 +1,58 @@ +import subprocess +from dataclasses import dataclass +from typing import Optional + +@dataclass +class RofiResult: + """Data returned from Rofi. + + Attributes + ---------- + index + Index within entries of the selected entry. + `None` if nothing was selected. + value + Selected entry's string value. + `None` if the value is not in the list or nothing was selected. + custom_bind + ID of custom bind used to select entry. None if no custom bind was used. + """ + index: Optional[int] + value: str + custom_bind: Optional[int] + + +def rofi(entries: list[str], prompt: str="> ", fuzzy=True, extra_args=[]) -> Optional[RofiResult]: + """Start a Rofi prompt. + + Returns + ------- + None if the prompt was cancelled, or a `RofiResult`. + """ + args = ["rofi", "-dmenu", "-sep", "\\0"] + args += ["-p", prompt] + + if fuzzy: + args += ["-matching", "fuzzy"] + + args += extra_args + + ret = RofiResult(None, "", None) + + res = subprocess.run(args, input="\0".join(entries), stdout=subprocess.PIPE, text=True) + match res.returncode: + case 0: + pass + case 1: + return None + case x if x >= 10 and x <= 28: + ret.custom_bind = x - 9 + case _ as retc: + raise RuntimeError(f"Rofi returned an unexpected return code `{retc}`.") + ret.value = res.stdout.strip() + try: + ret.index = entries.index(ret.value) + except ValueError: + pass + + return ret