#!/usr/bin/env bash set -e # Just stream the TAP output (sans extended syntax) if tput is missing command -v tput >/dev/null || exec grep -v "^begin " header_pattern='[0-9]+\.\.[0-9]+' IFS= read -r header if [[ "$header" =~ $header_pattern ]]; then count="${header:3}" index=0 failures=0 skipped=0 name="" count_column_width=$(( ${#count} * 2 + 2 )) else # If the first line isn't a TAP plan, print it and pass the rest through printf "%s\n" "$header" exec cat fi update_screen_width() { screen_width="$(tput cols)" count_column_left=$(( $screen_width - $count_column_width )) } trap update_screen_width WINCH update_screen_width begin() { go_to_column 0 printf_with_truncation $(( $count_column_left - 1 )) " %s" "$name" clear_to_end_of_line go_to_column $count_column_left printf "%${#count}s/${count}" "$index" go_to_column 1 } pass() { go_to_column 0 printf " ✓ %s" "$name" advance } skip() { local reason="$1" [ -z "$reason" ] || reason=": $reason" go_to_column 0 printf " - %s (skipped%s)" "$name" "$reason" advance } fail() { go_to_column 0 set_color 1 bold printf " ✗ %s" "$name" advance } log() { set_color 1 printf " %s\n" "$1" clear_color } todone() { local reason="$1" [ -z "$reason" ] || reason=": $reason" go_to_column 0 printf " ✓ %s ✭ DONE%s" "$name" "$reason" advance } summary() { printf "\n%d test%s" "$count" "$(plural "$count")" printf ", %d failure%s" "$failures" "$(plural "$failures")" if [ "$skipped" -gt 0 ]; then printf ", %d skipped" "$skipped" fi printf "\n" } printf_with_truncation() { local width="$1" shift local string="$(printf "$@")" if [ "${#string}" -gt "$width" ]; then printf "%s..." "${string:0:$(( $width - 4 ))}" else printf "%s" "$string" fi } go_to_column() { local column="$1" printf "\x1B[%dG" $(( $column + 1 )) } clear_to_end_of_line() { printf "\x1B[K" } advance() { clear_to_end_of_line echo clear_color } set_color() { local color="$1" local weight="$2" printf "\x1B[%d;%dm" $(( 30 + $color )) "$( [ "$weight" = "bold" ] && echo 1 || echo 22 )" } clear_color() { printf "\x1B[0m" } plural() { [ "$1" -eq 1 ] || echo "s" } _buffer="" buffer() { _buffer="${_buffer}$("$@")" } flush() { printf "%s" "$_buffer" _buffer="" } finish() { flush printf "\n" } trap finish EXIT while IFS= read -r line; do case "$line" in "begin "* ) let index+=1 name="${line#* $index }" buffer begin flush ;; "ok "* ) skip_expr="ok $index # skip (\(([^)]*)\))?" todo_expr="ok $index .*# todo([[:space:]]+(.+))?" if [[ "$line" =~ $skip_expr ]]; then let skipped+=1 buffer skip "${BASH_REMATCH[2]}" elif [[ "$line" =~ $todo_expr ]]; then buffer todone "${BASH_REMATCH[2]}" else buffer pass fi ;; "not ok "* ) todo_expr="ok $index .*# todo([[:space:]]+(.+))?" if [[ "$line" =~ $todo_expr ]]; then buffer pass else let failures+=1 buffer fail fi ;; "# "* ) buffer log "${line:2}" ;; esac done buffer summary