fuzzel-run-or-search.sh 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. #!/bin/bash
  2. # Run a command, or fall back to a web search if it isn't one.
  3. # fuzzel --dmenu prints the typed string as-is when nothing matches,
  4. # which is what makes the search fallback work.
  5. browser_app_id="google-chrome"
  6. search_url="https://duckduckgo.com/?q="
  7. # Executables in PATH. Deliberately not `compgen -c`: that also lists shell
  8. # builtins and keywords (cd, alias, if, ...), which `command -v` reports as
  9. # found but `exec` cannot run.
  10. list_path_bins() {
  11. local IFS=: dir file
  12. for dir in $PATH; do
  13. [[ -d $dir ]] || continue
  14. for file in "$dir"/*; do
  15. [[ -f $file && -x $file ]] && printf '%s\n' "${file##*/}"
  16. done
  17. done | sort -u
  18. }
  19. result=$(list_path_bins | fuzzel --dmenu)
  20. [[ -z $result ]] && exit 0
  21. # type -P looks only at PATH, so builtins and keywords correctly fall through
  22. # to the search branch instead of failing silently in exec.
  23. if type -P "${result%% *}" >/dev/null 2>&1; then
  24. exec $result
  25. fi
  26. query=$(jq -rn --arg q "$result" '$q|@uri')
  27. xdg-open "$search_url$query" &
  28. # Wait for the browser window instead of guessing at a fixed sleep: a cold
  29. # start takes well over half a second, while an already-running Chrome is
  30. # ready almost immediately.
  31. for _ in $(seq 40); do
  32. if swaymsg -t get_tree |
  33. jq -e --arg id "$browser_app_id" \
  34. 'recurse(.nodes[]?, .floating_nodes[]?) | select(.app_id == $id)' >/dev/null; then
  35. swaymsg "[app_id=\"$browser_app_id\"] focus" >/dev/null
  36. exit 0
  37. fi
  38. sleep 0.05
  39. done