#!/bin/bash # Fuzzel's normal application launcher, with a web-search escape hatch. # # Enter launch the highlighted application # Alt+Enter search the web for whatever you typed # # The script plays two roles. With no arguments it starts fuzzel, passing # itself as --launch-prefix. Fuzzel then re-invokes it with the argv it was # about to run, which is where the search fallback happens: Alt+Enter is bound # to execute-input (see [key-bindings] in fuzzel.ini), which hands over the # raw input text rather than a desktop entry, and raw text that isn't an # executable becomes a search. browser_app_id="google-chrome" search_url="https://duckduckgo.com/?q=" search_web() { local query query=$(jq -rn --arg q "$1" '$q|@uri') xdg-open "$search_url$query" & # Wait for the browser window instead of guessing at a fixed sleep: a cold # start takes well over half a second, while an already-running Chrome is # ready almost immediately. local _ for _ in $(seq 40); do if swaymsg -t get_tree | jq -e --arg id "$browser_app_id" \ 'recurse(.nodes[]?, .floating_nodes[]?) | select(.app_id == $id)' >/dev/null; then swaymsg "[app_id=\"$browser_app_id\"] focus" >/dev/null return 0 fi sleep 0.05 done } # No arguments: we are the keybinding. Start fuzzel with its default list. if (( $# == 0 )); then exec fuzzel --launch-prefix="$(realpath -- "$0")" fi # Arguments: fuzzel is asking us to launch something. It exports desktop entry # metadata only for real entries, so DESKTOP_ENTRY_ID tells the two apart - # checking whether argv looks like a command does not, because "who is alan # turing" and "test if it works" both start with a real executable. if [[ -n ${DESKTOP_ENTRY_ID:-} ]]; then exec "$@" fi search_web "$*"