emojiSuccess=✅ emojiWarning=💡 emojiDanger=🔥 emojiInfo=🔹 fontBlack=$'\033[0;30m' fontRed=$'\033[0;91m' fontGreen=$'\033[0;92m' fontYellow=$'\033[0;93m' fontBlue=$'\033[0;94m' fontMagenta=$'\033[0;95m' fontCyan=$'\033[0;96m' fontWhite=$'\033[0;97m' fontGray=$'\033[0;90m' fontBold=$'\033[1m' fontDim=$'\033[2m' fontULine=$'\033[4m' fontReset=$'\033[0m' labelDone="${fontGreen}done$fontReset" labelPass="${fontGreen}pass$fontReset" labelFail="${fontRed}fail$fontReset" labelOn="${fontGreen}on$fontReset" labelOff="${fontRed}off$fontReset" labelNull="${fontGray}null$fontReset" labelUnknown="${fontGray}unknown$fontReset" labelRunning="${fontGreen}running$fontReset" labelWarning="${fontYellow}warning$fontReset" labelDanger="${fontRed}danger$fontReset" printWidth=80 printFile="" # Strip ANSI escape sequences from a string. # $1 (string): input string to strip. function strStripAnsi() { sed -r 's/\x1B\[[0-9;]*[A-Za-z]//g' <<<"$1" # LC_ALL=C sed -E $'s/\x1B\\[[0-?]*[ -/]*[@-~]//g' <<<"${1-}" } # Write formatted output to stdout, the log file, and the print file (if configured). # $1 (text): text to write (printf %b formatting applied). function printWrite() { local plain logPath printPath printf '%b' "$@" # Log file [[ -n "${logFile:-}" ]] && { logPath=$(dirname -- "$printFile") [[ -d "$logPath" ]] || mkdir -p -- "$logPath" || return 0 printf '%s' "$@" | LC_ALL=C sed -E $'s/\x1B\\[[0-?]*[ -/]*[@-~]//g' >> "$logFile" } # Print file [[ -n "${printFile:-}" ]] || return 0 printPath=$(dirname -- "$printFile") [[ -d "$printPath" ]] || mkdir -p -- "$printPath" || return 0 printf '%s' "$@" | LC_ALL=C sed -E $'s/\x1B\\[[0-?]*[ -/]*[@-~]//g' >> "$printFile" } # Print a line padded to a fixed width with a filler character between prefix and suffix. # $1 (width): target line width in columns (0 or negative offsets from terminal width). # [$2] (filler): character used for padding (defaults to space). # [$3] (prefix): text printed before the fill area. # [$4] (suffix): text printed after the fill area. function printFill() { local term base plainBase baseLen fillLen local width="${1:-0}" local filler="${2:-}" local prefix="${3:-}" local suffix="${4:-}" shift 4 [[ -n "$filler" ]] || filler=" " term=$(tput cols 2>/dev/null || echo 80) (( width <= 0 )) && width=$((term + width)) (( width <= 0 )) && width=0 base="$prefix$suffix" plainBase=$(strStripAnsi "$base") baseLen=${#plainBase} if (( baseLen >= width )); then # printf '%s\n' "$base" printWrite "$base"$'\n' return 0 fi fillLen=$((width - baseLen)) printf -v fill '%*s' "$fillLen" '' fill="${fill// /$filler}" printWrite "$prefix$fill$suffix$*"$'\n' } # Print a dot-filled line with a label on the left and a value on the right. # [$1] (width): line width (defaults to 60). # [$2] (label): left-side label text. # [$3] (value): right-side value text. function printDot() { printFill "${1:-$printWidth}" "." "${2:-} $fontGray" "$fontReset ${3:-}" "${@:4}" } function printDotText() { printDot "$printWidth" "$@" } # Print a dot-filled line with a label on the left and no right-side value (fixed layout). # [$1] (width): line width (defaults to 60). # [$2] (label): left-side label text. function printDotFix() { printFill "${1:-$printWidth}" "." "${2:-} $fontGray" "$fontReset " "${@:3}" } # Print a horizontal rule or a blank line. # [$1] (filler): character to repeat (empty prints a blank line). # [$2] (width): line width (defaults to terminal width). # [$3] (prefix): text before the fill. # [$4] (suffix): text after the fill. function printRow() { local filler="${1:-}" local width="${2:-0}" local prefix="${3:-}" local suffix="${4:-}" if [[ "$filler" == '' && "$width" = 0 ]]; then printWrite $'\n' else printFill "$width" "$filler" "$prefix" "$suffix" fi } # Print a plain text line followed by a newline. # $1 (text): text to print. function printText() { printWrite "$@"$'\n' } # Print a success message in green with a success emoji. # $1 (message): message text. function printSuccess() { printWrite "$emojiSuccess$fontGreen$@$fontReset"$'\n' } # Print a danger/error message in red with a danger emoji. # $1 (message): message text. function printDanger() { printWrite "$emojiDanger$fontRed$@$fontReset"$'\n' } # Print a warning message in yellow with a warning emoji. # $1 (message): message text. function printWarning() { printWrite "$emojiWarning$fontYellow$@$fontReset"$'\n' } # Print an informational message in blue with an info emoji. # $1 (message): message text. function printInfo() { printWrite "$emojiInfo$fontBlue$@$fontReset"$'\n' } # Print a section title preceded by a blank line, optionally with a custom color. # $1 (title): title text. # [$2] (color): ANSI color code (defaults to fontBlue). function printTitle() { local fontColor=${2:-$fontBlue} printWrite $'\n'"$fontColor$1$fontReset"$'\n' } # Print a decorative section header box with a title. # $1 (title): section title text. # [$2] (color): ANSI color code (defaults to fontBlue). function printSection() { local fontColor=${2:-$fontBlue} printRow printFill "$printWidth" '─' " ${fontColor}┌─[ $1 ]" "┐ $fontReset" } # Print a start marker with the current app date and time. function printStart() { printDotText "Start" "$appDate ${appTime//-/:}" printRow } # Print a finish marker with the current timestamp and total elapsed execution time. function printFinish() { local label label=$(timeDiff "$appDate ${appTime//-/:}" "$(date +%Y-%m-%d) $(date +%H:%M:%S)") printRow printDotText "Finish" "$(date +%Y-%m-%d) $(date +%H:%M:%S)" printDotText "Execution time" "${label}s" } # Print the application header banner to stdout and write a separator to the log file. function printHeader() { local label tmpPath fillLen fill label="$appName $appVersion | $appDate $appTime" printf "\e[48;5;74m %-*s \e[0m\n" $(( printWidth - 2 )) "$label" [[ -n "${logFile:-}" ]] || return 0 tmpPath=$(dirname -- "$logFile") [[ -d "$tmpPath" ]] || mkdir -p -- "$tmpPath" || return 0 fillLen=$(($printWidth - 5 - ${#label})) printf -v fill '%*s' "$fillLen" '' fill="${fill// /═}" printf "[ %s ]\n" "$label $fill" >> "$logFile" } # Print a goodbye footer with total elapsed execution time to stdout and the log file. function printFooter() { local label label=$(timeDiff "$appDate ${appTime//-/:}" "$(date +%Y-%m-%d) $(date +%H:%M:%S)") printf '\n%b\n' "Bye bye | Time: ${label}s" printf '\n%b\n' "Bye bye | Time: ${label}s" >> "$logFile" }