From 33dbeb01b329292d826e1d84b07c86b25487c41a Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Mon, 9 Jun 2025 23:43:50 +1000 Subject: feat: add toggle command --- src/subcommands/toggle.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++- src/utils/hypr.py | 27 ++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/utils/hypr.py (limited to 'src') diff --git a/src/subcommands/toggle.py b/src/subcommands/toggle.py index 37f9a2b..e293669 100644 --- a/src/subcommands/toggle.py +++ b/src/subcommands/toggle.py @@ -1,11 +1,82 @@ from argparse import Namespace +from utils import hypr + class Command: args: Namespace + clients: list[dict[str, any]] = None + app2unit: str = None def __init__(self, args: Namespace) -> None: self.args = args def run(self) -> None: - pass + getattr(self, self.args.workspace)() + + def get_clients(self) -> list[dict[str, any]]: + if self.clients is None: + self.clients = hypr.message("clients") + + return self.clients + + def get_app2unit(self) -> str: + if self.app2unit is None: + import shutil + + self.app2unit = shutil.which("app2unit") + + return self.app2unit + + def move_client(self, selector: callable, workspace: str) -> None: + for client in self.get_clients(): + if selector(client): + hypr.dispatch("movetoworkspacesilent", f"special:{workspace},address:{client['address']}") + + def spawn_client(self, selector: callable, spawn: list[str]) -> bool: + exists = any(selector(client) for client in self.get_clients()) + + if not exists: + import subprocess + + subprocess.Popen([self.get_app2unit(), "--", *spawn], start_new_session=True) + + return not exists + + def spawn_or_move(self, selector: callable, spawn: list[str], workspace: str) -> None: + if not self.spawn_client(selector, spawn): + self.move_client(selector, workspace) + + def communication(self) -> None: + self.spawn_or_move(lambda c: c["class"] == "discord", ["discord"], "communication") + self.move_client(lambda c: c["class"] == "whatsapp", "communication") + + def music(self) -> None: + self.spawn_or_move( + lambda c: c["class"] == "Spotify" or c["initialTitle"] == "Spotify" or c["initialTitle"] == "Spotify Free", + ["spicetify", "watch", "-s"], + "music", + ) + self.move_client(lambda c: c["class"] == "feishin", "music") + + def sysmon(self) -> None: + self.spawn_client( + lambda c: c["class"] == "btop" and c["title"] == "btop" and c["workspace"]["name"] == "special:sysmon", + ["foot", "-a", "btop", "-T", "btop", "--", "btop"], + "sysmon", + ) + + def todo(self) -> None: + self.spawn_or_move(lambda c: c["class"] == "Todoist", ["todoist"], "todo") + + def specialws(self) -> None: + workspaces = hypr.message("workspaces") + on_special_ws = any(ws["name"] == "special:special" for ws in workspaces) + toggle_ws = "special" + + if not on_special_ws: + active_ws = hypr.message("activewindow")["workspace"]["name"] + if active_ws.startswith("special:"): + toggle_ws = active_ws[8:] + + hypr.dispatch("togglespecialworkspace", toggle_ws) diff --git a/src/utils/hypr.py b/src/utils/hypr.py new file mode 100644 index 0000000..d829f22 --- /dev/null +++ b/src/utils/hypr.py @@ -0,0 +1,27 @@ +import json as j +import os +import socket + +socket_path = f"{os.getenv('XDG_RUNTIME_DIR')}/hypr/{os.getenv('HYPRLAND_INSTANCE_SIGNATURE')}/.socket.sock" + + +def message(msg: str, json: bool = True) -> str or dict[str, any]: + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock: + sock.connect(socket_path) + + if json: + msg = f"j/{msg}" + sock.send(msg.encode()) + + resp = sock.recv(8192).decode() + while True: + new_resp = sock.recv(8192) + if not new_resp: + break + resp += new_resp.decode() + + return j.loads(resp) if json else resp + + +def dispatch(dispatcher: str, *args: list[any]) -> bool: + return message(f"dispatch {dispatcher} {' '.join(str(a) for a in args)}".rstrip(), json=False) == "ok" -- cgit v1.2.3-freya