From f663e6f6908a9dfb05ac22e867e726c1bf6f0960 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:41:05 +1000 Subject: internal: refactor for packaging Package using python-build, python-installer and hatch --- src/caelestia/subcommands/toggle.py | 82 +++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/caelestia/subcommands/toggle.py (limited to 'src/caelestia/subcommands/toggle.py') diff --git a/src/caelestia/subcommands/toggle.py b/src/caelestia/subcommands/toggle.py new file mode 100644 index 0000000..2122910 --- /dev/null +++ b/src/caelestia/subcommands/toggle.py @@ -0,0 +1,82 @@ +from argparse import Namespace + +from caelestia.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: + 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) -- cgit v1.2.3-freya From 3fa4a5f7b74a8e05a5cc0fdfaa2fc85f071a4dbe Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Wed, 11 Jun 2025 20:42:33 +1000 Subject: toggles: fix sysmon + not toggling ws --- src/caelestia/subcommands/toggle.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/caelestia/subcommands/toggle.py') diff --git a/src/caelestia/subcommands/toggle.py b/src/caelestia/subcommands/toggle.py index 2122910..fd49c30 100644 --- a/src/caelestia/subcommands/toggle.py +++ b/src/caelestia/subcommands/toggle.py @@ -50,6 +50,7 @@ class Command: def communication(self) -> None: self.spawn_or_move(lambda c: c["class"] == "discord", ["discord"], "communication") self.move_client(lambda c: c["class"] == "whatsapp", "communication") + hypr.dispatch("togglespecialworkspace", "communication") def music(self) -> None: self.spawn_or_move( @@ -58,16 +59,18 @@ class Command: "music", ) self.move_client(lambda c: c["class"] == "feishin", "music") + hypr.dispatch("togglespecialworkspace", "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", ) + hypr.dispatch("togglespecialworkspace", "sysmon") def todo(self) -> None: self.spawn_or_move(lambda c: c["class"] == "Todoist", ["todoist"], "todo") + hypr.dispatch("togglespecialworkspace", "todo") def specialws(self) -> None: workspaces = hypr.message("workspaces") -- cgit v1.2.3-freya From 796d538b168855ebd2afd62278800151816adcab Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Fri, 13 Jun 2025 00:42:46 +1000 Subject: feat: impl screenshot command --- src/caelestia/parser.py | 2 +- src/caelestia/subcommands/screenshot.py | 69 ++++++++++++++++++++++++++++++++- src/caelestia/subcommands/toggle.py | 14 +------ src/caelestia/utils/paths.py | 3 ++ 4 files changed, 74 insertions(+), 14 deletions(-) (limited to 'src/caelestia/subcommands/toggle.py') diff --git a/src/caelestia/parser.py b/src/caelestia/parser.py index f8c7bac..02ac3b9 100644 --- a/src/caelestia/parser.py +++ b/src/caelestia/parser.py @@ -60,7 +60,7 @@ def parse_args() -> (argparse.ArgumentParser, argparse.Namespace): # Create parser for screenshot opts screenshot_parser = command_parser.add_parser("screenshot", help="take a screenshot") screenshot_parser.set_defaults(cls=screenshot.Command) - screenshot_parser.add_argument("-r", "--region", help="take a screenshot of a region") + screenshot_parser.add_argument("-r", "--region", nargs="?", const="slurp", help="take a screenshot of a region") screenshot_parser.add_argument( "-f", "--freeze", action="store_true", help="freeze the screen while selecting a region" ) diff --git a/src/caelestia/subcommands/screenshot.py b/src/caelestia/subcommands/screenshot.py index 37f9a2b..73d65f7 100644 --- a/src/caelestia/subcommands/screenshot.py +++ b/src/caelestia/subcommands/screenshot.py @@ -1,4 +1,9 @@ +import subprocess from argparse import Namespace +from datetime import datetime + +from caelestia.utils import hypr +from caelestia.utils.paths import screenshots_cache_dir, screenshots_dir class Command: @@ -8,4 +13,66 @@ class Command: self.args = args def run(self) -> None: - pass + if self.args.region: + self.region() + else: + self.fullscreen() + + def region(self) -> None: + freeze_proc = None + + if self.args.freeze: + freeze_proc = subprocess.Popen(["wayfreeze", "--hide-cursor"]) + + if self.args.region == "slurp": + ws = hypr.message("activeworkspace")["id"] + geoms = [ + f"{','.join(map(str, c['at']))} {'x'.join(map(str, c['size']))}" + for c in hypr.message("clients") + if c["workspace"]["id"] == ws + ] + region = subprocess.check_output(["slurp"], input="\n".join(geoms), text=True) + else: + region = self.args.region + + sc_data = subprocess.check_output(["grim", "-l", "0", "-g", region.strip(), "-"]) + swappy = subprocess.Popen(["swappy", "-f", "-"], stdin=subprocess.PIPE, start_new_session=True) + swappy.stdin.write(sc_data) + swappy.stdin.close() + + if freeze_proc: + freeze_proc.kill() + + def fullscreen(self) -> None: + sc_data = subprocess.check_output(["grim", "-"]) + + subprocess.run(["wl-copy"], input=sc_data) + + dest = screenshots_cache_dir / datetime.now().strftime("%Y%m%d%H%M%S") + screenshots_cache_dir.mkdir(exist_ok=True, parents=True) + dest.write_bytes(sc_data) + + action = subprocess.check_output( + [ + "notify-send", + "-i", + "image-x-generic-symbolic", + "-h", + f"STRING:image-path:{dest}", + "-a", + "caelestia-cli", + "--action=open=Open", + "--action=save=Save", + "Screenshot taken", + f"Screenshot stored in {dest} and copied to clipboard", + ], + text=True, + ).strip() + + if action == "open": + subprocess.Popen(["swappy", "-f", dest], start_new_session=True) + elif action == "save": + new_dest = (screenshots_dir / dest.name).with_suffix(".png") + new_dest.parent.mkdir(exist_ok=True, parents=True) + dest.rename(new_dest) + subprocess.run(["notify-send", "Screenshot saved", f"Saved to {new_dest}"]) diff --git a/src/caelestia/subcommands/toggle.py b/src/caelestia/subcommands/toggle.py index fd49c30..b8ad11b 100644 --- a/src/caelestia/subcommands/toggle.py +++ b/src/caelestia/subcommands/toggle.py @@ -1,3 +1,4 @@ +import subprocess from argparse import Namespace from caelestia.utils import hypr @@ -6,7 +7,6 @@ from caelestia.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 @@ -20,14 +20,6 @@ class Command: 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): @@ -37,9 +29,7 @@ class Command: 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) + subprocess.Popen(["app2unit", "--", *spawn], start_new_session=True) return not exists diff --git a/src/caelestia/utils/paths.py b/src/caelestia/utils/paths.py index 37aeeef..6a98dae 100644 --- a/src/caelestia/utils/paths.py +++ b/src/caelestia/utils/paths.py @@ -28,6 +28,9 @@ wallpaper_link_path = c_state_dir / "wallpaper/current" wallpaper_thumbnail_path = c_state_dir / "wallpaper/thumbnail.jpg" wallpapers_cache_dir = c_cache_dir / "wallpapers" +screenshots_dir = Path.home() / "Pictures/Screenshots" +screenshots_cache_dir = c_cache_dir / "screenshots" + def compute_hash(path: Path | str) -> str: sha = hashlib.sha256() -- cgit v1.2.3-freya