#!/usr/bin/env bash # # ANSI code generator # # © Copyright 2015 Tyler Akins # Licensed under the MIT license with an additional non-advertising clause # See http://github.com/fidian/ansi ansi::addCode() { local N if [[ "$1" == *=* ]]; then N="${1#*=}" N="${N//,/;}" else N="" fi OUTPUT="$OUTPUT$CSI$N$2" } ansi::addColor() { OUTPUT="$OUTPUT$CSI${1}m" if [ ! -z "$2" ]; then SUFFIX="$CSI${2}m$SUFFIX" fi } ansi::colorTable() { local FNB_LOWER FNB_UPPER PADDED FNB_LOWER="$(ansi::colorize 2 22 f)n$(ansi::colorize 1 22 b)" FNB_UPPER="$(ansi::colorize 2 22 F)N$(ansi::colorize 1 22 B)" printf 'bold %s ' "$(ansi::colorize 1 22 Sample)" printf 'faint %s ' "$(ansi::colorize 2 22 Sample)" printf 'italic %s\n' "$(ansi::colorize 3 23 Sample)" printf 'underline %s ' "$(ansi::colorize 4 24 Sample)" printf 'blink %s ' "$(ansi::colorize 5 25 Sample)" printf 'inverse %s\n' "$(ansi::colorize 7 27 Sample)" printf 'invisible %s\n' "$(ansi::colorize 8 28 Sample)" printf 'strike %s ' "$(ansi::colorize 9 29 Sample)" printf 'fraktur %s ' "$(ansi::colorize 20 23 Sample)" printf 'double-underline%s\n' "$(ansi::colorize 21 24 Sample)" printf 'frame %s ' "$(ansi::colorize 51 54 Sample)" printf 'encircle %s ' "$(ansi::colorize 52 54 Sample)" printf 'overline%s\n' "$(ansi::colorize 53 55 Sample)" printf '\n' printf ' black red green yellow blue magenta cyan white\n' for BG in 40:black 41:red 42:green 43:yellow 44:blue 45:magenta 46:cyan 47:white xx:no-bg; do PADDED="bg-${BG:3} " PADDED="${PADDED:0:13}" printf '%s' "$PADDED" BG=${BG:0:2} if [[ "$BG" == "xx" ]]; then BG="" fi for FG in 30 31 32 33 34 35 36 37; do printf '%s%s;%sm' "$CSI" "$BG" "${FG}" printf '%s' "$FNB_LOWER" printf '%s%sm' "$CSI" "$(( FG + 60 ))" printf '%s' "$FNB_UPPER" printf '%s0m ' "${CSI}" done printf '\n' if [[ -n "$BG" ]]; then printf ' +intense ' for FG in 30 31 32 33 34 35 36 37; do printf '%s%s;%sm' "$CSI" "$(( BG + 60 ))" "${FG}" printf '%s' "$FNB_LOWER" printf '%s%sm' "$CSI" "$(( FG + 60 ))" printf '%s' "$FNB_UPPER" printf '%s0m ' "${CSI}" done printf '\n' fi done printf '\n' printf 'Legend:\n' printf ' Normal color: f = faint, n = normal, b = bold.\n' printf ' Intense color: F = faint, N = normal, B = bold.\n' } ansi::colorize() { printf '%s%sm%s%s%sm' "$CSI" "$1" "$3" "$CSI" "$2" } ansi::isAnsiSupported() { local cont c str if ! test -t 1; then # stdout is not a terminal return 1 fi if hash tput &> /dev/null; then if [[ "$(tput colors)" -lt 8 ]]; then return 1 fi return 0 fi # Query the console and see if we get ANSI codes back. # CSI 0 c == CSI c == Primary Device Attributes. # Idea: CSI c # Response = CSI ? 6 [234] ; 2 2 c # The "22" means ANSI color, but terminals don't need to send that back. printf "%s0c" "$CSI" str= cont=true while $cont && read -n 1 -s -t 0.1 c; do if [[ -n "$c" ]]; then str+=$c else cont=false fi done set | grep ^str= # If we get anything back, the terminal is consuming the color codes and # will probably do its best. Let's assume there's color. [[ "$str" == "$CSI?6"[234]";"* ]] } ansi::report() { local BUFF C REPORT="" printf "%s%s" "$CSI" "$1" read -r -N ${#2} -s -t 1 BUFF if [ "$BUFF" != "$2" ]; then return 1 fi read -r -N ${#3} -s -t 1 BUFF while [ "$BUFF" != "$3" ]; do REPORT="$REPORT${BUFF:0:1}" read -r -N 1 -s -t 1 C || exit 1 BUFF="${BUFF:1}$C" done } ansi::showHelp() { cat <