#!/bin/bash # local is well supported # shellcheck disable=3043 set -eu # pick up configuration FUZL_PROMPT=${FUZL_PROMPT:-fuzl} FUZL_ICON=${FUZL_ICON:-󰈲} fuzl_try() { [ "$1" == "--" ] && shift 1 if ! { stderr=$( set +x eval "$*" 2>&1 1>&3 ); } 3>&1; then fuzl_notification "$* failed :(" "${stderr:--}" -c error exit 1 fi } export FUZL_MENU_FILTER=filter export FUZL_MENU_PASSWORD=passw export FUZL_MENU_MESSAGE=msg export FUZL_MENU_INPUT=input # Shows a menu fuzl_menu() { local form="$1" shift 1 local prompt options_list maxw # If a prompt_icon is provided, prepend it. prompt="$FUZL_PROMPT " [ -n "$FUZL_ICON" ] && prompt="$FUZL_ICON $FUZL_PROMPT " options_list=$(cat) maxw=$(echo -e "$prompt\n$options_list" | wc -L) [ "$maxw" -lt 15 ] && maxw=15 [ "$maxw" -gt 150 ] && maxw=100 case "$form" in "$FUZL_MENU_FILTER") # Selection menu with a list of options passed via STDIN echo -ne "$options_list" | fuzzel -d -w "$maxw" -p "$prompt" "$@" ;; "$FUZL_MENU_PASSWORD") # Password input menu (minimalist) echo -n | fuzzel -d -w "$maxw" -p "$prompt" --password ;; "$FUZL_MENU_MESSAGE") # Message box menu (no input bar) echo -ne "$options_list" | fuzzel -d -w "$maxw" -p "$prompt" "$@" ;; "$FUZL_MENU_INPUT") # Text input menu (no list view) echo -n | fuzzel -d -p "$prompt" "$@" --lines 0 ;; esac } FUZL_NOTIFICATION_ID= fuzl_notification() { local summary="${1:?missing summary}" local body="${2:?missing body}" shift 2 FUZL_NOTIFICATION_ID=$( fyi "$@" -p -a "${FUZL_PROMPT}" "${FUZL_PROMPT}: $summary" "$body" | cut -d= -f2 ) } fuzl_notification_cancel() { fyi --close "$FUZL_NOTIFICATION_ID" || true FUZL_NOTIFICATION_ID= } FUZL_LOADING_PID= fuzl_loading() { local summary="${1:?missing summary}" echo -e "..." | FUZL_PROMPT="$summary" fuzl_menu $FUZL_MENU_MESSAGE & FUZL_LOADING_PID=$! } fuzl_loading_cancel() { local pgid pgid="$(ps -o pgid= "$FUZL_LOADING_PID" || return)" kill -- -"$pgid" || true FUZL_LOADING_PID= } FUZL_ACTIONS=() fuzl_action_add() { local action="${1:?}" icon="${2:?}" shift 2 # prevent multiple occurences printf '%s\n' "${FUZL_ACTIONS[@]}" | grep -q "^$action" && return FUZL_ACTIONS+=("${action}\t${icon}\t${*}") } fuzl_action_menu() { local action action=$(printf '%s\n' "${FUZL_ACTIONS[@]}" | FUZL_PROMPT="$FUZL_PROMPT: $*" fuzl_menu $FUZL_MENU_FILTER --with-nth='{2} {3..}' --accept-nth=1) # reset actions FUZL_ACTIONS=() test -n "$action" || return eval "${FUZL_PROMPT}_${action}" "'$*'" } # setup common debug helper [ -z "${DEBUG:-}" ] || set -x