dev: automated commit - 2025-11-28 21:56:48
This commit is contained in:
parent
3a4ed1d45c
commit
0aface6777
10 changed files with 413 additions and 655 deletions
|
|
@ -1,109 +1,108 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
#!/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...]
|
||||
|
||||
# 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
|
||||
Examples:
|
||||
niri-launch-or-focus firefox
|
||||
niri-launch-or-focus code --class Code --title "My Project"
|
||||
niri-launch-or-focus kitty --class kitty
|
||||
"""
|
||||
|
||||
CLASS=""
|
||||
TITLE=""
|
||||
ARGS=()
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--class)
|
||||
CLASS="$2"
|
||||
shift 2
|
||||
;;
|
||||
--title)
|
||||
TITLE="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
ARGS+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ ${#ARGS[@]} -eq 0 ]; then
|
||||
echo "Usage: $0 <command> [--class CLASS] [--title TITLE] [args...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
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
|
||||
|
||||
COMMAND="${ARGS[0]}"
|
||||
APP_NAME=$(basename "$COMMAND")
|
||||
unset 'ARGS[0]'
|
||||
ARGS=("${ARGS[@]}")
|
||||
|
||||
# If class/title were provided as flags, add them to command args (for apps that support them)
|
||||
if [ -n "$CLASS" ]; then
|
||||
ARGS=("--class=$CLASS" "${ARGS[@]}")
|
||||
fi
|
||||
if [ -n "$TITLE" ]; then
|
||||
ARGS=("--title=$TITLE" "${ARGS[@]}")
|
||||
fi
|
||||
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,
|
||||
)
|
||||
|
||||
# Find window by app_id (niri uses app-id), title, or app name
|
||||
find_window() {
|
||||
local class="$1"
|
||||
local title="$2"
|
||||
local app="$3"
|
||||
|
||||
# Check if jq is available
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
echo "Error: jq is required but not found. Please install jq." >&2
|
||||
return 1
|
||||
fi
|
||||
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,
|
||||
)
|
||||
|
||||
# Get windows list from niri as JSON
|
||||
local windows_json
|
||||
windows_json=$(niri msg -j windows 2>/dev/null || echo "[]")
|
||||
|
||||
if [ -z "$windows_json" ] || [ "$windows_json" = "[]" ]; then
|
||||
return 1
|
||||
fi
|
||||
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)
|
||||
|
||||
# Use jq to find matching window
|
||||
local window_id
|
||||
|
||||
if [ -n "$class" ]; then
|
||||
# Match by class (app_id)
|
||||
window_id=$(echo "$windows_json" | jq -r --arg class "$class" '
|
||||
.[] | select(.app_id | ascii_downcase == ($class | ascii_downcase)) | .id
|
||||
' | head -1)
|
||||
elif [ -n "$title" ]; then
|
||||
# Match by title
|
||||
window_id=$(echo "$windows_json" | jq -r --arg title "$title" '
|
||||
.[] | select(.title == $title) | .id
|
||||
' | head -1)
|
||||
else
|
||||
# Match by app name (basename of command)
|
||||
window_id=$(echo "$windows_json" | jq -r --arg app "$app" '
|
||||
.[] | select(.app_id | ascii_downcase == ($app | ascii_downcase)) | .id
|
||||
' | head -1)
|
||||
fi
|
||||
|
||||
if [ -n "$window_id" ] && [ "$window_id" != "null" ]; then
|
||||
echo "$window_id"
|
||||
return 0
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Try to find existing window
|
||||
WINDOW_ID=$(find_window "$CLASS" "$TITLE" "$APP_NAME" || echo "")
|
||||
|
||||
# Focus if found, otherwise launch
|
||||
if [ -n "$WINDOW_ID" ]; then
|
||||
niri msg action focus-window --id "$WINDOW_ID" >/dev/null 2>&1
|
||||
else
|
||||
"$COMMAND" "${ARGS[@]}" >/dev/null 2>&1 &
|
||||
disown
|
||||
fi
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue