niri-launch-or-focus 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. # Simple script to launch an application or focus it if already running in niri
  4. # Usage: niri-launch-or-focus <command> [--class CLASS] [--title TITLE] [args...]
  5. #
  6. # Examples:
  7. # niri-launch-or-focus firefox
  8. # niri-launch-or-focus code --class Code --title "My Project"
  9. # niri-launch-or-focus kitty --class kitty
  10. CLASS=""
  11. TITLE=""
  12. ARGS=()
  13. # Parse arguments
  14. while [[ $# -gt 0 ]]; do
  15. case $1 in
  16. --class)
  17. CLASS="$2"
  18. shift 2
  19. ;;
  20. --title)
  21. TITLE="$2"
  22. shift 2
  23. ;;
  24. *)
  25. ARGS+=("$1")
  26. shift
  27. ;;
  28. esac
  29. done
  30. if [ ${#ARGS[@]} -eq 0 ]; then
  31. echo "Usage: $0 <command> [--class CLASS] [--title TITLE] [args...]" >&2
  32. exit 1
  33. fi
  34. COMMAND="${ARGS[0]}"
  35. APP_NAME=$(basename "$COMMAND")
  36. unset 'ARGS[0]'
  37. ARGS=("${ARGS[@]}")
  38. # If class/title were provided as flags, add them to command args (for apps that support them)
  39. if [ -n "$CLASS" ]; then
  40. ARGS=("--class=$CLASS" "${ARGS[@]}")
  41. fi
  42. if [ -n "$TITLE" ]; then
  43. ARGS=("--title=$TITLE" "${ARGS[@]}")
  44. fi
  45. # Find window by app_id (niri uses app-id), title, or app name
  46. find_window() {
  47. local class="$1"
  48. local title="$2"
  49. local app="$3"
  50. # Check if jq is available
  51. if ! command -v jq >/dev/null 2>&1; then
  52. echo "Error: jq is required but not found. Please install jq." >&2
  53. return 1
  54. fi
  55. # Get windows list from niri as JSON
  56. local windows_json
  57. windows_json=$(niri msg -j windows 2>/dev/null || echo "[]")
  58. if [ -z "$windows_json" ] || [ "$windows_json" = "[]" ]; then
  59. return 1
  60. fi
  61. # Use jq to find matching window
  62. local window_id
  63. if [ -n "$class" ]; then
  64. # Match by class (app_id)
  65. window_id=$(echo "$windows_json" | jq -r --arg class "$class" '
  66. .[] | select(.app_id | ascii_downcase == ($class | ascii_downcase)) | .id
  67. ' | head -1)
  68. elif [ -n "$title" ]; then
  69. # Match by title
  70. window_id=$(echo "$windows_json" | jq -r --arg title "$title" '
  71. .[] | select(.title == $title) | .id
  72. ' | head -1)
  73. else
  74. # Match by app name (basename of command)
  75. window_id=$(echo "$windows_json" | jq -r --arg app "$app" '
  76. .[] | select(.app_id | ascii_downcase == ($app | ascii_downcase)) | .id
  77. ' | head -1)
  78. fi
  79. if [ -n "$window_id" ] && [ "$window_id" != "null" ]; then
  80. echo "$window_id"
  81. return 0
  82. fi
  83. return 1
  84. }
  85. # Try to find existing window
  86. WINDOW_ID=$(find_window "$CLASS" "$TITLE" "$APP_NAME" || echo "")
  87. # Focus if found, otherwise launch
  88. if [ -n "$WINDOW_ID" ]; then
  89. niri msg action focus-window --id "$WINDOW_ID" >/dev/null 2>&1
  90. else
  91. "$COMMAND" "${ARGS[@]}" >/dev/null 2>&1 &
  92. disown
  93. fi