dotfiles/local-bin/.local/bin/niri-launch-or-focus

108 lines
3.1 KiB
Python
Executable file

#!/usr/bin/env python3
"""
Simple script to launch an application or focus it if already running in niri
Usage: niri-launch-or-focus <command> [--class CLASS] [--title TITLE] [args...]
Examples:
niri-launch-or-focus firefox
niri-launch-or-focus code --class Code --title "My Project"
niri-launch-or-focus kitty --class kitty
"""
import argparse
import json
import subprocess
import sys
def find_window(class_name=None, title=None, app_name=None):
"""Find window by app_id (class), title, or app name."""
try:
result = subprocess.run(
["niri", "msg", "--json", "windows"],
capture_output=True,
text=True,
check=False,
)
windows_json = result.stdout.strip()
if not windows_json or windows_json == "[]":
return None
windows = json.loads(windows_json)
for window in windows:
app_id = window.get("app_id", "").lower()
if class_name:
if app_id == class_name.lower():
return window.get("id")
elif title:
if window.get("title") == title:
return window.get("id")
elif app_name:
if app_id == app_name.lower():
return window.get("id")
return None
except (json.JSONDecodeError, subprocess.SubprocessError, KeyError):
return None
def focus_window(window_id):
"""Focus a window by ID."""
subprocess.run(
["niri", "msg", "action", "focus-window", "--id", str(window_id)],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
def launch_command(command, args):
"""Launch a command in the background."""
subprocess.Popen(
[command] + args,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True,
)
def main():
parser = argparse.ArgumentParser(
description="Launch an application or focus it if already running in niri"
)
parser.add_argument("command", help="Command to run")
parser.add_argument("--class", dest="class_name", help="Window class (app_id)")
parser.add_argument("--title", help="Window title")
parser.add_argument("args", nargs=argparse.REMAINDER, help="Additional arguments for command")
args = parser.parse_args()
# Extract app name from command (basename)
app_name = args.command.split("/")[-1]
# Try to find existing window
window_id = find_window(
class_name=args.class_name,
title=args.title,
app_name=app_name if not args.class_name and not args.title else None,
)
# Build command arguments
cmd_args = []
if args.class_name:
cmd_args.append(f"--class={args.class_name}")
if args.title:
cmd_args.append(f"--title={args.title}")
cmd_args.extend(args.args)
# Focus if found, otherwise launch
if window_id:
focus_window(window_id)
else:
launch_command(args.command, cmd_args)
if __name__ == "__main__":
main()