main
59c7d64 ยท 8 days ago 139 commits
  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