1#!/usr/bin/env bash
2
3# ==============================================================================
4# smart-launch
5# A unified script to focus a Hyprland window if it exists, or launch it if not.
6# Supports Standard GUI apps, TUIs (via xdg-terminal-exec), and Web Apps.
7# ==============================================================================
8
9show_help() {
10 echo "Usage: $(basename "$0") [OPTIONS] <PATTERN> [COMMAND/URL]"
11 echo ""
12 echo "Options:"
13 echo " -t, --tui Launch as a Terminal UI (sets specific App ID)"
14 echo " -w, --web Launch as a Web App (using --app mode)"
15 echo " -c, --cmd Custom launch command (overrides default behavior)"
16 echo " -n, --new Force a new instance (do not focus existing windows)"
17 echo " -h, --help Show this help message"
18 echo ""
19 echo "Examples:"
20 echo " Standard: $(basename "$0") firefox"
21 echo " New Instance: $(basename "$0") --new firefox"
22 echo " TUI: $(basename "$0") --tui btop"
23}
24
25# --- Browser Detection ---
26get_browser() {
27 local browser
28 browser=$(xdg-settings get default-web-browser)
29 case $browser in
30 google-chrome*|brave-browser*|microsoft-edge*|opera*|vivaldi*|helium*) ;;
31 *) browser="chromium" ;;
32 esac
33 echo "$browser"
34}
35
36# --- Argument Parsing ---
37MODE="standard"
38FORCE_NEW=0
39
40while [[ "$#" -gt 0 ]]; do
41 case $1 in
42 -t|--tui) MODE="tui"; shift ;;
43 -w|--web|--webapp) MODE="web"; shift ;;
44 -c|--cmd) MODE="custom"; shift ;;
45 -n|--new) FORCE_NEW=1; shift ;;
46 -h|--help) show_help; exit 0 ;;
47 -*) echo "Unknown option: $1"; show_help; exit 1 ;;
48 *) break ;;
49 esac
50done
51
52if [[ -z "$1" ]]; then
53 echo "Error: Missing arguments."
54 show_help
55 exit 1
56fi
57
58# --- Logic Configuration ---
59
60WINDOW_PATTERN="$1"
61LAUNCH_CMD=""
62
63case $MODE in
64 tui)
65 BIN_NAME=$(basename "$1")
66 BIN_NAME=${BIN_NAME// /-}
67 BIN_NAME=${BIN_NAME//./-}
68 BIN_NAME=${BIN_NAME%-}
69 APP_ID="org.wraith.${BIN_NAME}"
70 WINDOW_PATTERN="$APP_ID"
71
72 shift
73 if [[ -n "$1" ]]; then CMD_ARGS="$@"; else CMD_ARGS="$BIN_NAME"; fi
74 LAUNCH_CMD="uwsm-app -- xdg-terminal-exec --app-id='$APP_ID' -e $CMD_ARGS"
75 ;;
76
77 web)
78 shift
79 URL="$1"
80 shift
81 EXTRA_ARGS="$@"
82 # BROWSER=$(get_browser)
83 BROWSER="chromium-pwa"
84 LAUNCH_CMD="uwsm-app -- $BROWSER --app=$URL $EXTRA_ARGS"
85 ;;
86
87 custom)
88 shift
89 LAUNCH_CMD="$@"
90 ;;
91
92 standard)
93 LAUNCH_CMD="uwsm-app -- $WINDOW_PATTERN"
94 ;;
95esac
96
97# --- Hyprland Detection Logic ---
98
99WINDOW_ADDRESS=""
100
101# Only check for existing windows if NOT forcing a new instance
102if [[ $FORCE_NEW -eq 0 ]]; then
103 WINDOW_ADDRESS=$(hyprctl clients -j | jq -r --arg p "$WINDOW_PATTERN" '
104 map(select(
105 (.class | test("\\b" + $p + "\\b"; "i")) or
106 (.initialClass | test("\\b" + $p + "\\b"; "i")) or
107 (.class | contains($p)) or
108 (.class | test($p; "i"))
109 ))
110 | sort_by(.focusHistoryID)
111 | reverse
112 | .[0].address // empty'
113 )
114fi
115
116# --- Execution ---
117
118if [[ -n $WINDOW_ADDRESS && $WINDOW_ADDRESS != "null" ]]; then
119 echo "Focusing window: $WINDOW_PATTERN ($WINDOW_ADDRESS)"
120 hyprctl dispatch "hl.dsp.focus({ window = 'address:$WINDOW_ADDRESS' })"
121else
122 echo "Launching new instance: $LAUNCH_CMD"
123 eval exec setsid $LAUNCH_CMD &>/dev/null &
124fi