99 lines
2.1 KiB
Bash
99 lines
2.1 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Spinner state
|
|
declare -A SPINNER_PIDS
|
|
declare -A SPINNER_MSGS
|
|
declare -A MSG_SHOWN
|
|
|
|
# Color definitions (adjust as needed)
|
|
RD='\033[0;31m'
|
|
GN='\033[0;32m'
|
|
YW='\033[0;33m'
|
|
CL='\033[0m'
|
|
CM='✔'
|
|
CROSS='✘'
|
|
|
|
# Trap cleanup
|
|
trap cleanup_spinners EXIT INT TERM HUP
|
|
|
|
# Hash function for message ID
|
|
msg_hash() {
|
|
local input="$1"
|
|
echo -n "$input" | sha1sum | awk '{print $1}'
|
|
}
|
|
|
|
# Start a spinner for a specific message
|
|
start_spinner_for_msg() {
|
|
local msg="$1"
|
|
local id
|
|
id=$(msg_hash "$msg")
|
|
|
|
[[ -n "${MSG_SHOWN["$id"]+x}" ]] && return
|
|
MSG_SHOWN["$id"]=1
|
|
SPINNER_MSGS["$id"]="$msg"
|
|
|
|
local frames=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
|
|
local interval=0.1
|
|
local spin_i=0
|
|
|
|
{
|
|
while true; do
|
|
printf "\r\e[2K%s %b" "${frames[spin_i]}" "${YW}${msg}${CL}" >&2
|
|
spin_i=$(((spin_i + 1) % ${#frames[@]}))
|
|
sleep "$interval"
|
|
done
|
|
} &
|
|
|
|
SPINNER_PIDS["$id"]=$!
|
|
disown "${SPINNER_PIDS["$id"]}"
|
|
}
|
|
|
|
# Stop the spinner for a specific message
|
|
stop_spinner_for_msg() {
|
|
local msg="$1"
|
|
local id
|
|
id=$(msg_hash "$msg")
|
|
|
|
if [[ -n "${SPINNER_PIDS["$id"]+x}" ]] && ps -p "${SPINNER_PIDS["$id"]}" >/dev/null 2>&1; then
|
|
kill "${SPINNER_PIDS["$id"]}" 2>/dev/null
|
|
wait "${SPINNER_PIDS["$id"]}" 2>/dev/null || true
|
|
fi
|
|
|
|
unset SPINNER_PIDS["$id"]
|
|
unset SPINNER_MSGS["$id"]
|
|
unset MSG_SHOWN["$id"]
|
|
}
|
|
|
|
# Cleanup all active spinners
|
|
cleanup_spinners() {
|
|
for id in "${!SPINNER_PIDS[@]}"; do
|
|
if ps -p "${SPINNER_PIDS[$id]}" >/dev/null 2>&1; then
|
|
kill "${SPINNER_PIDS[$id]}" 2>/dev/null
|
|
wait "${SPINNER_PIDS[$id]}" 2>/dev/null || true
|
|
fi
|
|
unset SPINNER_PIDS["$id"]
|
|
unset SPINNER_MSGS["$id"]
|
|
unset MSG_SHOWN["$id"]
|
|
done
|
|
}
|
|
|
|
# Show info message with spinner
|
|
msg_info() {
|
|
local msg="$1"
|
|
start_spinner_for_msg "$msg"
|
|
}
|
|
|
|
# End spinner and show success message
|
|
msg_ok() {
|
|
local msg="$1"
|
|
stop_spinner_for_msg "$msg"
|
|
printf "\r\e[2K%s %b\n" "${CM}" "${GN}${msg}${CL}" >&2
|
|
}
|
|
|
|
# End spinner and show error message
|
|
msg_error() {
|
|
local msg="$1"
|
|
stop_spinner_for_msg "$msg"
|
|
printf "\r\e[2K%s %b\n" "${CROSS}" "${RD}${msg}${CL}" >&2
|
|
}
|