|
@@ -1,7 +1,13 @@
|
|
|
#!/bin/bash
|
|
#!/bin/bash
|
|
|
-# Run a command, or fall back to a web search if it isn't one.
|
|
|
|
|
-# fuzzel --dmenu prints the typed string as-is when nothing matches,
|
|
|
|
|
-# which is what makes the search fallback work.
|
|
|
|
|
|
|
+# Run a command, or search the web for it.
|
|
|
|
|
+#
|
|
|
|
|
+# Enter run it if it is an executable, otherwise search for it
|
|
|
|
|
+# Alt+Enter always search, even if it looks like a command
|
|
|
|
|
+#
|
|
|
|
|
+# The second one exists because deciding by "is the first word a binary?" gets
|
|
|
|
|
+# it wrong for ordinary phrases: test, who, which, sort, time and file are all
|
|
|
|
|
+# real executables. Alt+Enter is bound to fuzzel's custom-1, which is dmenu-only
|
|
|
|
|
+# and exits with code 10 (see [key-bindings] in fuzzel.ini).
|
|
|
|
|
|
|
|
browser_app_id="google-chrome"
|
|
browser_app_id="google-chrome"
|
|
|
search_url="https://duckduckgo.com/?q="
|
|
search_url="https://duckduckgo.com/?q="
|
|
@@ -19,27 +25,47 @@ list_path_bins() {
|
|
|
done | sort -u
|
|
done | sort -u
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-result=$(list_path_bins | fuzzel --dmenu)
|
|
|
|
|
-[[ -z $result ]] && exit 0
|
|
|
|
|
|
|
+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
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-# type -P looks only at PATH, so builtins and keywords correctly fall through
|
|
|
|
|
-# to the search branch instead of failing silently in exec.
|
|
|
|
|
-if type -P "${result%% *}" >/dev/null 2>&1; then
|
|
|
|
|
- exec $result
|
|
|
|
|
-fi
|
|
|
|
|
|
|
+result=$(list_path_bins | fuzzel --dmenu)
|
|
|
|
|
+status=$?
|
|
|
|
|
|
|
|
-query=$(jq -rn --arg q "$result" '$q|@uri')
|
|
|
|
|
-xdg-open "$search_url$query" &
|
|
|
|
|
|
|
+[[ -z $result ]] && exit 0
|
|
|
|
|
|
|
|
-# 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.
|
|
|
|
|
-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
|
|
|
|
|
|
|
+case $status in
|
|
|
|
|
+ # Alt+Enter: search regardless of what the text looks like.
|
|
|
|
|
+ 10)
|
|
|
|
|
+ search_web "$result"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ # Enter: run it if it really is an executable. type -P looks only at PATH,
|
|
|
|
|
+ # so builtins and keywords fall through to the search instead of failing
|
|
|
|
|
+ # silently in exec.
|
|
|
|
|
+ 0)
|
|
|
|
|
+ if type -P "${result%% *}" >/dev/null 2>&1; then
|
|
|
|
|
+ exec $result
|
|
|
|
|
+ fi
|
|
|
|
|
+ search_web "$result"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ # Escape, or fuzzel failed to start.
|
|
|
|
|
+ *)
|
|
|
exit 0
|
|
exit 0
|
|
|
- fi
|
|
|
|
|
- sleep 0.05
|
|
|
|
|
-done
|
|
|
|
|
|
|
+ ;;
|
|
|
|
|
+esac
|