| 1 | #!/bin/bash |
| 2 | # aurora-run: fuzzel-compatible front end for aurora's runner (needs aurora running). |
| 3 | # aurora-run open the app runner (same as SUPER+R) |
| 4 | # aurora-run -d [opts] dmenu: lines on stdin, the choice on stdout, exit 1 when cancelled |
| 5 | # dmenu opts (fuzzel/dmenu spelling): -p/--prompt TEXT, -l/--lines N (0 = input only), --placeholder TEXT, |
| 6 | # --password, --index (print the line number instead). Other fuzzel flags (-i, --width, -fn, ...) are ignored. |
| 7 | # Full reference: aurora-run --help |
| 8 | |
| 9 | usage() { |
| 10 | cat <<'EOF' |
| 11 | aurora-run: aurora's runner and a fuzzel/dmenu replacement for scripts (needs aurora running) |
| 12 | |
| 13 | USAGE |
| 14 | aurora-run open the app runner (same as SUPER+R; again = close) |
| 15 | ... | aurora-run -d [OPTIONS] dmenu mode: one item per stdin line, prints the choice |
| 16 | |
| 17 | DMENU OPTIONS |
| 18 | -d, --dmenu dmenu mode |
| 19 | -p, --prompt TEXT label left of the input (shown in the accent colour) |
| 20 | -l, --lines N visible rows (default 10, capped at 15, shrinks to fit); |
| 21 | 0 = no list, just a text box (stdin optional) |
| 22 | --placeholder TEXT dim hint in the empty input |
| 23 | --password mask the input with * (use with --lines=0) |
| 24 | --index print the 0-based line number instead of the text |
| 25 | (-1 when the typed text was used) |
| 26 | -h, --help this help |
| 27 | Both "--opt VALUE" and "--opt=VALUE" work. Other fuzzel flags (-i, -fn, --width, |
| 28 | --cache, ...) are accepted and ignored, so fuzzel/dmenu lines can just be renamed. |
| 29 | |
| 30 | KEYS |
| 31 | type fuzzy filter (case-insensitive; prefix > word start > substring) |
| 32 | Up/Down, Tab/Shift+Tab, move the selection |
| 33 | Ctrl+N/P, Ctrl+J/K |
| 34 | PgUp/PgDn jump a page |
| 35 | Enter print the selected line (or the typed text if nothing matches) |
| 36 | Ctrl+Enter print the typed text, ignoring the selection |
| 37 | Esc / click outside cancel |
| 38 | |
| 39 | EXIT STATUS |
| 40 | 0 something was chosen (printed on stdout, one line) |
| 41 | 1 cancelled: Esc, click outside, another aurora overlay opened, or a newer |
| 42 | aurora-run -d request replaced this one |
| 43 | 2 aurora not running / exited while waiting, or the IPC call failed |
| 44 | |
| 45 | RUNNER MODE (no -d) |
| 46 | apps (+ their desktop actions), aurora commands (panel tabs, wallpaper, clipboard, |
| 47 | overview, power actions, ...) and everything on $PATH, ranked by launch count. |
| 48 | =EXPR calculator, Enter copies the result >CMD run CMD with sh |
| 49 | Ctrl+Enter runs the selection in foot. |
| 50 | |
| 51 | EXAMPLES |
| 52 | choice=$(printf 'Integrated\nHybrid\nNvidia\n' | aurora-run -d -p "GPU mode:") || exit |
| 53 | query=$(aurora-run -d -l 0 -p "search: ") |
| 54 | pass=$(aurora-run -d --password -l 0 --placeholder "Password:") |
| 55 | n=$(ls | aurora-run -d --index) |
| 56 | EOF |
| 57 | } |
| 58 | |
| 59 | dmenu=0 prompt="" placeholder="" lines="" password=0 index=0 |
| 60 | while [ $# -gt 0 ]; do |
| 61 | case $1 in |
| 62 | -h | --help) usage; exit 0 ;; |
| 63 | -d | --dmenu) dmenu=1 ;; |
| 64 | -p | --prompt) prompt=$2; shift ;; |
| 65 | --prompt=*) prompt=${1#*=} ;; |
| 66 | -l | --lines) lines=$2; shift ;; |
| 67 | --lines=*) lines=${1#*=} ;; |
| 68 | --placeholder) placeholder=$2; shift ;; |
| 69 | --placeholder=*) placeholder=${1#*=} ;; |
| 70 | --password | --password=*) password=1 ;; |
| 71 | --index) index=1 ;; |
| 72 | # ignored flags that take a separate value |
| 73 | -fn | -f | --font | -w | --width | --cache | --with-nth | --nth-delimiter | -a | --anchor | -o | --output) shift ;; |
| 74 | *) ;; |
| 75 | esac |
| 76 | shift |
| 77 | done |
| 78 | |
| 79 | pid=$(pgrep -nf 'quickshell.*/aurora$|qs -c aurora$') |
| 80 | [ -n "$pid" ] || { echo "aurora-run: aurora is not running" >&2; exit 2; } |
| 81 | |
| 82 | if [ "$dmenu" = 0 ]; then |
| 83 | exec qs -c aurora ipc call shell run |
| 84 | fi |
| 85 | |
| 86 | # private dir on tmpfs: items, opts and the reply fifo (a password only ever passes through the fifo) |
| 87 | dir=$(mktemp -d "${XDG_RUNTIME_DIR:-/tmp}/aurora-run.XXXXXX") || exit 2 |
| 88 | trap 'rm -rf "$dir"' EXIT |
| 89 | [ -t 0 ] || cat > "$dir/items" |
| 90 | printf 'prompt=%s\nplaceholder=%s\nlines=%s\npassword=%s\nindex=%s\n' \ |
| 91 | "${prompt//$'\n'/ }" "${placeholder//$'\n'/ }" "$lines" "$password" "$index" > "$dir/opts" |
| 92 | mkfifo "$dir/reply" |
| 93 | exec 3<> "$dir/reply" # read-write: never blocks aurora's writer, and lets us time out below |
| 94 | |
| 95 | err=$(qs -c aurora ipc call shell dmenu "$dir" 2>&1) |
| 96 | [ -z "$err" ] || { echo "aurora-run: $err" >&2; exit 2; } |
| 97 | |
| 98 | # reply is "<0|1>\n<value>\0"; give up if aurora goes away while we wait |
| 99 | until IFS= read -r -d '' -t 1 -u 3 reply; do |
| 100 | kill -0 "$pid" 2>/dev/null || { echo "aurora-run: aurora exited" >&2; exit 2; } |
| 101 | done |
| 102 | [ "${reply%%$'\n'*}" = 0 ] || exit 1 |
| 103 | printf '%s\n' "${reply#*$'\n'}" |