/
color.sh
149 lines (140 loc) · 4.8 KB
/
color.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# @package: cli/color
# Routines for printing text in color using ANSI escape codes
_bb_onfirstload "bb_cli_color" || return
################################################################################
# Globals
################################################################################
declare -Ag __bb_cli_color_code
__bb_cli_color_code['black']=0
__bb_cli_color_code['red']=1
__bb_cli_color_code['green']=2
__bb_cli_color_code['yellow']=3
__bb_cli_color_code['blue']=4
__bb_cli_color_code['magenta']=5
__bb_cli_color_code['cyan']=6
__bb_cli_color_code['bright_gray']=7
__bb_cli_color_code['dark_white']=7
__bb_cli_color_code['gray']=60
__bb_cli_color_code['bright_black']=60
__bb_cli_color_code['bright_red']=61
__bb_cli_color_code['bright_green']=62
__bb_cli_color_code['bright_yellow']=63
__bb_cli_color_code['bright_blue']=64
__bb_cli_color_code['bright_magenta']=65
__bb_cli_color_code['bright_cyan']=66
__bb_cli_color_code['bright_white']=67
__bb_cli_color_code['white']=67
__bb_cli_color_reset='\e[0m'
################################################################################
# Functions
################################################################################
# function: bb_colorize COLORSTR TEXT
# Prints the given text in color if outputting to a terminal
# @arguments:
# - COLORSTR: FGCOLOR[_on_[BGCOLOR]] (e.g. red, bright_red, white_on_blue)
# - TEXT: text to be printed in color
# @returns: 0 if text was printed in color, 1 otherwise
# @notes:
# Supported colors:
# - black
# - red
# - green
# - yellow
# - blue
# - magenta
# - cyan
# - bright_gray (dark_white)
# - gray (bright_black)
# - bright_red
# - bright_green
# - bright_yellow
# - bright_blue
# - bright_magenta
# - bright_cyan
# - white (bright_white)
#
# This does not print a new line at the end of TEXT
function bb_colorize () {
local colorstr="$1"
local text="$2"
local rc=$__bb_true
# Check if this is a terminal, return otherwise
if ! [[ -t 1 ]] && [[ -z "${__bb_cli_color_rawcolor+set}" ]]; then
printf -- "$text"
return "$__bb_false"
fi
local fgcolor="${colorstr%%_on_*}"
local colorcode
local prefix=''
if [[ "$colorstr" != "$fgcolor" ]]; then
local bgcolor="${colorstr#*_on_}"
colorcode=${__bb_cli_color_code["$bgcolor"]}
if [[ -z "$colorcode" ]]; then
printf -- "$text"
return "$__bb_false"
fi
(( colorcode += 40 ))
prefix+="${__bb_cli_color_escapeprompt+\[}\e[${colorcode}m${__bb_cli_color_escapeprompt+\]}"
fi
colorcode=${__bb_cli_color_code["$fgcolor"]}
if [[ -z "$colorcode" ]]; then
printf -- "$text"
return "$__bb_false"
fi
(( colorcode += 30 ))
prefix+="${__bb_cli_color_escapeprompt+\[}\e[${colorcode}m${__bb_cli_color_escapeprompt+\]}"
local reset="${__bb_cli_color_escapeprompt+\[}$__bb_cli_color_reset${__bb_cli_color_escapeprompt+\]}"
printf -- '%b%s%b' "$prefix" "$text" "$reset"
return "$__bb_true"
}
# function: bb_rawcolor COLORSTR TEXT
# Like colorize but always uses prints in color
# @arguments:
# - COLORSTR: FGCOLOR[_on_[BGCOLOR]] (e.g. red, bright_red, white_on_blue)
# - TEXT: text to be printed in color
# @notes:
# Use this instead of colorize if you need to still print in color even if
# not connected to a terminal, e.g. when saving the output to a variable.
# See colorize for supported colors
function bb_rawcolor () {
__bb_cli_color_rawcolor=1
bb_colorize "$@"
unset __bb_cli_color_rawcolor
}
# function: bb_colorstrip TEXT
# Strips ANSI color codes from text colorized by colorize (or rawcolor)
# @arguments:
# - TEXT: text possibly with color escape codes to be removed
# @notes:
# This is only guaranteed to work on text generated by colorize
# and variants, not for any generic string with ANSI escape codes.
function bb_colorstrip () {
# Note: I went through multiple iterations of this but ran into
# version compatibility issues with pattern substitution, regex, and
# escape characters. This isn't elegant, but it should be portable!
local text="$1"
local stripped=""
local -i i
for (( i=0; i<${#text}-1; i++ )); do
local c1="${text:$i:1}"
local c2="${text:$i+1:1}"
case "$c1$c2" in
\\\[|\\\])
# Prompt non-printable region delimiters
(( i++ ))
;;
$'\e'[\[0])
# Beginning of an escape sequence
# Advance to terminating m character
for (( i+=2; i<${#text}-1; i++ )); do
[[ ${text:$i:1} == m ]] && break
done
;;
*)
stripped+="$c1"
;;
esac
done
[[ $i -eq ${#text}-1 ]] && stripped+="${text:$i:1}"
printf -- "%s" "$stripped"
}