|
@@ -1,30 +1,19 @@
|
|
|
#!/bin/bash
|
|
#!/bin/bash
|
|
|
-# Run a command, or search the web for it.
|
|
|
|
|
|
|
+# Fuzzel's normal application launcher, with a web-search escape hatch.
|
|
|
#
|
|
#
|
|
|
-# Enter run it if it is an executable, otherwise search for it
|
|
|
|
|
-# Alt+Enter always search, even if it looks like a command
|
|
|
|
|
|
|
+# Enter launch the highlighted application
|
|
|
|
|
+# Alt+Enter search the web for whatever you typed
|
|
|
#
|
|
#
|
|
|
-# 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).
|
|
|
|
|
|
|
+# 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"
|
|
browser_app_id="google-chrome"
|
|
|
search_url="https://duckduckgo.com/?q="
|
|
search_url="https://duckduckgo.com/?q="
|
|
|
|
|
|
|
|
-# Executables in PATH. Deliberately not `compgen -c`: that also lists shell
|
|
|
|
|
-# builtins and keywords (cd, alias, if, ...), which `command -v` reports as
|
|
|
|
|
-# found but `exec` cannot run.
|
|
|
|
|
-list_path_bins() {
|
|
|
|
|
- local IFS=: dir file
|
|
|
|
|
- for dir in $PATH; do
|
|
|
|
|
- [[ -d $dir ]] || continue
|
|
|
|
|
- for file in "$dir"/*; do
|
|
|
|
|
- [[ -f $file && -x $file ]] && printf '%s\n' "${file##*/}"
|
|
|
|
|
- done
|
|
|
|
|
- done | sort -u
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
search_web() {
|
|
search_web() {
|
|
|
local query
|
|
local query
|
|
|
query=$(jq -rn --arg q "$1" '$q|@uri')
|
|
query=$(jq -rn --arg q "$1" '$q|@uri')
|
|
@@ -45,27 +34,17 @@ search_web() {
|
|
|
done
|
|
done
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-result=$(list_path_bins | fuzzel --dmenu)
|
|
|
|
|
-status=$?
|
|
|
|
|
|
|
+# No arguments: we are the keybinding. Start fuzzel with its default list.
|
|
|
|
|
+if (( $# == 0 )); then
|
|
|
|
|
+ exec fuzzel --launch-prefix="$(realpath -- "$0")"
|
|
|
|
|
+fi
|
|
|
|
|
|
|
|
-[[ -z $result ]] && exit 0
|
|
|
|
|
|
|
+# 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
|
|
|
|
|
|
|
|
-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
|
|
|
|
|
- ;;
|
|
|
|
|
-esac
|
|
|
|
|
|
|
+search_web "$*"
|