mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 11:32:42 +00:00
110 lines
4.5 KiB
Bash
110 lines
4.5 KiB
Bash
#!/bin/bash
|
|
APP=$1
|
|
declare -a INSTANCES
|
|
|
|
# Per-class launch commands for kitty-* (class -> command run via `kitty -e`).
|
|
# Unmapped classes just open a plain kitty with that class.
|
|
declare -A KITTY_CMDS=(
|
|
# [kitty-lazygit]="lazygit"
|
|
# [kitty-btop]="btop"
|
|
)
|
|
|
|
# Handle webapp cycling and launching
|
|
if [[ "$APP" == "webapp" ]]; then
|
|
# Cycle all WebApps: Firefox SSAs (WebApp-*) and Chromium/Brave SSAs (chrome-*-Default).
|
|
# Falls back to launching YouTube if none are open. Excludes real browsers (chromium/brave-*).
|
|
INSTANCES=($(niri msg -j windows | jq -r '.[] | select((.app_id // "") | ascii_downcase | test("^(webapp-|chrome-)")) | .id'))
|
|
FALLBACK_APP="webapp-youtube"
|
|
elif [[ "$APP" == webapp-* ]]; then
|
|
# Extract the webapp name (e.g., "webapp-claude" -> "Claude")
|
|
WEBAPP_NAME=$(echo "$APP" | sed 's/webapp-//' | sed 's/.*/\u&/')
|
|
# Find matching WebApp by prefix (case-insensitive match)
|
|
APP_ID=$(niri msg -j windows | jq -r ".[] | select(.app_id | test(\"WebApp-${WEBAPP_NAME}\"; \"i\")) | .app_id" | head -1)
|
|
|
|
if [ -z "$APP_ID" ]; then
|
|
# No instance running, launch via gtk-launch
|
|
DESKTOP_FILE=$(find ~/.local/share/applications -iname "WebApp-${WEBAPP_NAME}*.desktop" -print -quit 2>/dev/null)
|
|
if [ -n "$DESKTOP_FILE" ]; then
|
|
gtk-launch "$(basename "$DESKTOP_FILE")"
|
|
else
|
|
echo "No desktop file found for WebApp-${WEBAPP_NAME}"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
INSTANCES=($(niri msg -j windows | jq -r ".[] | select(.app_id | test(\"WebApp-${WEBAPP_NAME}\"; \"i\")) | .id"))
|
|
elif [[ "$APP" == "kitty" ]]; then
|
|
# Cycle through ALL kitty windows (any class: kitty, kitty-nvim, ...)
|
|
INSTANCES=($(niri msg -j windows | jq -r '.[] | select((.app_id // "") | ascii_downcase | startswith("kitty")) | .id'))
|
|
elif [[ "$APP" == kitty-* ]]; then
|
|
# Specific kitty class, e.g. kitty-nvim -> app_id "kitty-nvim"
|
|
INSTANCES=($(niri msg -j windows | jq -r --arg cls "$APP" \
|
|
'.[] | select((.app_id // "") | ascii_downcase == ($cls | ascii_downcase)) | .id'))
|
|
|
|
if [ ${#INSTANCES[@]} -eq 0 ]; then
|
|
cmd="${KITTY_CMDS[$APP]:-}"
|
|
if [ -n "$cmd" ]; then
|
|
niri msg action spawn -- kitty --class "$APP" -e $cmd
|
|
else
|
|
niri msg action spawn -- kitty --class "$APP"
|
|
fi
|
|
exit 0
|
|
fi
|
|
elif [[ "$APP" == "ghostty" ]]; then
|
|
# Cycle through Ghostty terminals (case-insensitive app_id match)
|
|
INSTANCES=($(niri msg -j windows | jq -r '.[] | select(.app_id | test("ghostty"; "i")) | .id'))
|
|
elif [[ "$APP" == "browser" ]]; then
|
|
# Cycle through all browsers (zen/brave/chromium/firefox), launch default if none
|
|
INSTANCES=($(niri msg -j windows | jq -r '.[] | select((.app_id // "") | ascii_downcase | test("^(zen|brave|chromium|firefox)")) | .id'))
|
|
DEFAULT_SPAWN="zen"
|
|
elif [[ "$APP" == "terminal" ]]; then
|
|
# Cycle through all terminals (ghostty/kitty/alacritty), launch default if none
|
|
INSTANCES=($(niri msg -j windows | jq -r '.[] | select((.app_id // "") | ascii_downcase | test("kitty|alacritty|ghostty")) | .id'))
|
|
DEFAULT_SPAWN="kitty"
|
|
elif [[ "$APP" == "ai" ]]; then
|
|
# Cycle through AI desktop apps (Claude/Hermes), launch Hermes if none
|
|
INSTANCES=($(niri msg -j windows | jq -r '.[] | select((.app_id // "") | ascii_downcase | test("claude|hermes")) | .id'))
|
|
DEFAULT_SPAWN="hermes desktop"
|
|
else
|
|
INSTANCES=($(niri msg -j windows | jq -r ".[] | select(.app_id==\"${APP}\") | .id"))
|
|
fi
|
|
|
|
# Launch if no instances
|
|
if [ ${#INSTANCES[@]} -eq 0 ]; then
|
|
if [ -n "${DEFAULT_SPAWN:-}" ]; then
|
|
niri msg action spawn -- $DEFAULT_SPAWN
|
|
exit 0
|
|
fi
|
|
if [ -n "${FALLBACK_APP:-}" ]; then
|
|
exec "$0" "$FALLBACK_APP"
|
|
fi
|
|
# Removed "kitty" from this block so it falls through to the spawn command
|
|
if [[ "$APP" == "webapp" || "$APP" == "ghostty" ]]; then
|
|
echo "No ${APP} windows running"
|
|
exit 0
|
|
fi
|
|
niri msg action spawn -- $APP
|
|
exit 0
|
|
fi
|
|
|
|
# Focus logic
|
|
if [ ${#INSTANCES[@]} -eq 1 ]; then
|
|
niri msg action focus-window --id ${INSTANCES[0]}
|
|
else
|
|
ISORTED=($(printf "%s\n" "${INSTANCES[@]}" | sort -n))
|
|
FOCUSED=$(niri msg -j focused-window | jq '.id')
|
|
|
|
if [[ ! " ${ISORTED[@]} " =~ ${FOCUSED} ]]; then
|
|
niri msg action focus-window --id ${ISORTED[0]}
|
|
else
|
|
new_index=0
|
|
for i in "${!ISORTED[@]}"; do
|
|
if [ "${ISORTED[$i]}" -eq "${FOCUSED}" ]; then
|
|
new_index=$(( (i + 1) % ${#ISORTED[@]} ))
|
|
break
|
|
fi
|
|
done
|
|
niri msg action focus-window --id ${ISORTED[$new_index]}
|
|
fi
|
|
fi
|