Skip to content

Instantly share code, notes, and snippets.

@charles-l
Last active May 4, 2024 16:51
Show Gist options
  • Save charles-l/6507437fe65a41b03911ca5ce04ecc46 to your computer and use it in GitHub Desktop.
Save charles-l/6507437fe65a41b03911ca5ce04ecc46 to your computer and use it in GitHub Desktop.
python port of jumpapp
#!/usr/bin/env python3
# depends on having `wmctrl`, `xdotool`, and `zenity` installed.
import argparse
import re
import subprocess
import os
import traceback
parser = argparse.ArgumentParser()
parser.add_argument("command")
parser.add_argument("args", nargs='*')
parser.add_argument("--flatpak", help="the application is a flatpak (so spawn it through flatpak run)", action='store_true')
args = parser.parse_args()
def fromhex(s):
return int(s.removeprefix("0x"), 16)
def focused_window() -> int:
wid, = re.search(r"window id # (\w+),", subprocess.check_output("xprop -root _NET_ACTIVE_WINDOW".split(), text=True)).groups(1)
return fromhex(wid)
try:
windows_lines = subprocess.check_output(["wmctrl", "-lx"], text=True).strip().split('\n')
windows = []
for w in windows_lines:
r = {}
widhex, n, r['wmclass'], _, r['title'] = re.split(r'\s+', w.strip(), 4)
r['wid'] = fromhex(widhex)
r['desktop_number'] = int(n)
windows.append(r)
matching = [w for w in windows if args.command in w['wmclass'].lower()]
match matching:
case []: # spawn
if args.flatpak:
appname, = [x for x in subprocess.check_output("flatpak list --columns=application".split(), text=True).strip().split() if args.command in x.lower()]
os.spawnlp(os.P_NOWAIT, "flatpak", "flatpak", "run", appname)
else:
os.spawnlp(os.P_NOWAIT, args.command, args.command, *args.args)
case [w]: # raise or lower
if focused_window() == w["wid"]:
os.system("xdotool getactivewindow windowminimize")
else:
os.system(f'wmctrl -i -a {hex(w["wid"])}')
case [*ws]: # cycle
wid = focused_window()
i = next((i for i, w in enumerate(matching) if w['wid'] == wid), 0)
i = (i + 1) % len(matching)
os.system(f'wmctrl -i -a {hex(matching[i]["wid"])}')
except Exception as e:
s = traceback.format_exc()
subprocess.run(["zenity", "--error", "--text", s, "--no-wrap", "--no-markup", "--title", "jumpapp error"])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment