|
23 | 23 | # $ declare -A assoc=([foo]=1 [bar]=2) |
24 | 24 | # $ vardump assoc |
25 | 25 | # ( |
26 | | -#['foo']='1' |
27 | | -#['bar']='2' |
| 26 | +# ['foo']='1' |
| 27 | +# ['bar']='2' |
28 | 28 | # ) |
29 | 29 | # $ vardump -v assoc |
30 | 30 | # -------------------------- |
31 | 31 | # vardump: assoc |
32 | 32 | # attributes: (A)associative array |
33 | 33 | # length: 2 |
34 | 34 | # ( |
35 | | -#['foo']='1' |
36 | | -#['bar']='2' |
| 35 | +# ['foo']='1' |
| 36 | +# ['bar']='2' |
37 | 37 | # ) |
38 | 38 | # -------------------------- |
39 | 39 | # ``` |
|
43 | 43 | # -C [always|auto|never] when to colorize output, defaults to auto |
44 | 44 | # |
45 | 45 | vardump() { |
46 | | -# read arguments |
47 | | -local verbose=false |
48 | | -local whencolor='auto' |
49 | | -local OPTIND OPTARG opt |
50 | | -while getopts 'C:v' opt; do |
51 | | -case "$opt" in |
52 | | -C) whencolor=$OPTARG;; |
53 | | -v) verbose=true;; |
54 | | -*) return 1;; |
55 | | -esac |
56 | | -done |
57 | | -shift "$((OPTIND - 1))" |
58 | | - |
59 | | -# read variable name |
60 | | -local name=$1 |
61 | | - |
62 | | -if [[ -z $name ]]; then |
63 | | -echo 'vardump: name required as first argument' >&2 |
64 | | -return 1 |
65 | | -fi |
66 | | - |
67 | | -# optionally load colors |
68 | | -if [[ $whencolor == always ]] || [[ $whencolor == auto && -t 1 ]]; then |
69 | | -local color_green=$'\e[32m' |
70 | | -local color_magenta=$'\e[35m' |
71 | | -local color_rst=$'\e[0m' |
72 | | -local color_dim=$'\e[2m' |
73 | | -else |
74 | | -local color_green='' |
75 | | -local color_magenta='' |
76 | | -local color_rst='' |
77 | | -local color_dim='' |
78 | | -fi |
79 | | -local color_value=$color_green |
80 | | -local color_key=$color_magenta |
81 | | -local color_length=$color_magenta |
82 | | - |
83 | | -# optionally print header |
84 | | -if $verbose; then |
85 | | -echo "${color_dim}--------------------------${color_rst}" |
86 | | -echo "${color_dim}vardump: ${color_rst}$name" |
87 | | -fi |
88 | | - |
89 | | -# ensure the variable is defined |
90 | | -if ! declare -p "$name" &>/dev/null; then |
91 | | -echo "variable ${name@Q} not defined" >&2 |
92 | | -return 1 |
93 | | -fi |
94 | | - |
95 | | -# get the variable attributes - this will tell us what kind of variable |
96 | | -# it is. |
97 | | -# |
98 | | -# XXX dave says - is this ideal? when the variable is a nameref (using |
99 | | -# `declare -n` or `local -n`) it seems like this method follows the |
100 | | -# nameref, whereas parsing the output of `declare -p <name>` seems to |
101 | | -# correctly give `-n` as the set of arguments used. Perhaps just parse |
102 | | -# the output of `declare -p` from above here instead? |
103 | | -local attrs |
104 | | -IFS='' read -ra attrs <<< "${!name@a}" |
105 | | - |
106 | | -# parse the variable attributes and construct a human-readable string |
107 | | -local attributes=() |
108 | | -local attr |
109 | | -local typ='' |
110 | | -for attr in "${attrs[@]}"; do |
111 | | -local s='' |
112 | | -case "$attr" in |
113 | | -a) s='indexed array'; typ='a';; |
114 | | -A) s='associative array'; typ='A';; |
115 | | -r) s='read-only';; |
116 | | -i) s='integer';; |
117 | | -g) s='global';; |
118 | | -x) s='exported';; |
119 | | -*) s="unknown";; |
120 | | -esac |
121 | | -attributes+=("($attr)$s") |
122 | | -done |
123 | | - |
124 | | -# optionally print the attributes to the user |
125 | | -if $verbose; then |
126 | | -echo -n "${color_dim}attributes: ${color_rst}" |
127 | | -if [[ -n ${attributes[0]} ]]; then |
128 | | -# separate the list of attributes by a `/` character |
129 | | -( |
130 | | -IFS=/ |
131 | | -echo -n "${attributes[*]}" |
132 | | -) |
133 | | -else |
134 | | -echo -n '(none)' |
135 | | -fi |
136 | | -echo |
137 | | -fi |
138 | | - |
139 | | -# print the variable itself! we use $typ defined above to format it |
140 | | -# appropriately. |
141 | | -# |
142 | | -# we *pray* the user doesn't use this variable name in their own code or |
143 | | -# we'll hit a circular reference error (THAT WE CAN'T CATCH OURSELVES IN |
144 | | -# CODE - lame) |
145 | | -local -n __vardump_name="$name" |
146 | | - |
147 | | -if [[ $typ == 'a' || $typ == 'A' ]]; then |
148 | | -# print this as an array - indexed, sparse, associative, |
149 | | -# whatever |
150 | | -local key value |
151 | | - |
152 | | -# optionally print length |
153 | | -if $verbose; then |
154 | | -local length=${#__vardump_name[@]} |
155 | | -printf '%s %s\n' \ |
156 | | - "${color_dim}length:${color_rst}" \ |
157 | | - "${color_length}$length${color_rst}" |
158 | | -fi |
159 | | - |
160 | | -# loop keys and print the data itself |
161 | | -echo '(' |
162 | | -for key in "${!__vardump_name[@]}"; do |
163 | | -value=${__vardump_name[$key]} |
164 | | - |
165 | | -# safely quote the key name if it's an associative array |
166 | | -# (the user controls the key names in this case so we |
167 | | -# can't trust them to be safe) |
168 | | -if [[ $typ == 'A' ]]; then |
169 | | -key=${key@Q} |
170 | | -fi |
171 | | - |
172 | | -# always safely quote the value |
173 | | -value=${value@Q} |
174 | | - |
175 | | -printf '\t[%s]=%s\n' \ |
176 | | - "${color_key}$key${color_rst}" \ |
177 | | - "${color_value}$value${color_rst}" |
178 | | -done |
179 | | -echo ')' |
180 | | -else |
181 | | -# we are just a simple scalar value - print this as a regular, |
182 | | -# safely-quoted, value. |
183 | | -echo "${color_value}${__vardump_name@Q}${color_rst}" |
184 | | -fi |
185 | | - |
186 | | -# optionally print the trailer |
187 | | -if $verbose; then |
188 | | -echo "${color_dim}--------------------------${color_rst}" |
189 | | -fi |
190 | | - |
191 | | -return 0 |
| 46 | + # read arguments |
| 47 | + local verbose=false |
| 48 | + local whencolor='auto' |
| 49 | + local OPTIND OPTARG opt |
| 50 | + while getopts 'C:v' opt; do |
| 51 | + case "$opt" in |
| 52 | + C) whencolor=$OPTARG;; |
| 53 | + v) verbose=true;; |
| 54 | + *) return 1;; |
| 55 | + esac |
| 56 | + done |
| 57 | + shift "$((OPTIND - 1))" |
| 58 | + |
| 59 | + # read variable name |
| 60 | + local name=$1 |
| 61 | + |
| 62 | + if [[ -z $name ]]; then |
| 63 | + echo 'vardump: name required as first argument' >&2 |
| 64 | + return 1 |
| 65 | + fi |
| 66 | + |
| 67 | + # optionally load colors |
| 68 | + if [[ $whencolor == always ]] || [[ $whencolor == auto && -t 1 ]]; then |
| 69 | + local color_green=$'\e[32m' |
| 70 | + local color_magenta=$'\e[35m' |
| 71 | + local color_rst=$'\e[0m' |
| 72 | + local color_dim=$'\e[2m' |
| 73 | + else |
| 74 | + local color_green='' |
| 75 | + local color_magenta='' |
| 76 | + local color_rst='' |
| 77 | + local color_dim='' |
| 78 | + fi |
| 79 | + local color_value=$color_green |
| 80 | + local color_key=$color_magenta |
| 81 | + local color_length=$color_magenta |
| 82 | + |
| 83 | + # optionally print header |
| 84 | + if $verbose; then |
| 85 | + echo "${color_dim}--------------------------${color_rst}" |
| 86 | + echo "${color_dim}vardump: ${color_rst}$name" |
| 87 | + fi |
| 88 | + |
| 89 | + # ensure the variable is defined |
| 90 | + if ! declare -p "$name" &>/dev/null; then |
| 91 | + echo "variable ${name@Q} not defined" >&2 |
| 92 | + return 1 |
| 93 | + fi |
| 94 | + |
| 95 | + # get the variable attributes - this will tell us what kind of variable |
| 96 | + # it is. |
| 97 | + # |
| 98 | + # XXX dave says - is this ideal? when the variable is a nameref (using |
| 99 | + # `declare -n` or `local -n`) it seems like this method follows the |
| 100 | + # nameref, whereas parsing the output of `declare -p <name>` seems to |
| 101 | + # correctly give `-n` as the set of arguments used. Perhaps just parse |
| 102 | + # the output of `declare -p` from above here instead? |
| 103 | + local attrs |
| 104 | + IFS='' read -ra attrs <<< "${!name@a}" |
| 105 | + |
| 106 | + # parse the variable attributes and construct a human-readable string |
| 107 | + local attributes=() |
| 108 | + local attr |
| 109 | + local typ='' |
| 110 | + for attr in "${attrs[@]}"; do |
| 111 | + local s='' |
| 112 | + case "$attr" in |
| 113 | + a) s='indexed array'; typ='a';; |
| 114 | + A) s='associative array'; typ='A';; |
| 115 | + r) s='read-only';; |
| 116 | + i) s='integer';; |
| 117 | + g) s='global';; |
| 118 | + x) s='exported';; |
| 119 | + *) s="unknown";; |
| 120 | + esac |
| 121 | + attributes+=("($attr)$s") |
| 122 | + done |
| 123 | + |
| 124 | + # optionally print the attributes to the user |
| 125 | + if $verbose; then |
| 126 | + echo -n "${color_dim}attributes: ${color_rst}" |
| 127 | + if [[ -n ${attributes[0]} ]]; then |
| 128 | + # separate the list of attributes by a `/` character |
| 129 | + ( |
| 130 | + IFS=/ |
| 131 | + echo -n "${attributes[*]}" |
| 132 | + ) |
| 133 | + else |
| 134 | + echo -n '(none)' |
| 135 | + fi |
| 136 | + echo |
| 137 | + fi |
| 138 | + |
| 139 | + # print the variable itself! we use $typ defined above to format it |
| 140 | + # appropriately. |
| 141 | + # |
| 142 | + # we *pray* the user doesn't use this variable name in their own code or |
| 143 | + # we'll hit a circular reference error (THAT WE CAN'T CATCH OURSELVES IN |
| 144 | + # CODE - lame) |
| 145 | + local -n __vardump_name="$name" |
| 146 | + |
| 147 | + if [[ $typ == 'a' || $typ == 'A' ]]; then |
| 148 | + # print this as an array - indexed, sparse, associative, |
| 149 | + # whatever |
| 150 | + local key value |
| 151 | + |
| 152 | + # optionally print length |
| 153 | + if $verbose; then |
| 154 | + local length=${#__vardump_name[@]} |
| 155 | + printf '%s %s\n' \ |
| 156 | + "${color_dim}length:${color_rst}" \ |
| 157 | + "${color_length}$length${color_rst}" |
| 158 | + fi |
| 159 | + |
| 160 | + # loop keys and print the data itself |
| 161 | + echo '(' |
| 162 | + for key in "${!__vardump_name[@]}"; do |
| 163 | + value=${__vardump_name[$key]} |
| 164 | + |
| 165 | + # safely quote the key name if it's an associative array |
| 166 | + # (the user controls the key names in this case so we |
| 167 | + # can't trust them to be safe) |
| 168 | + if [[ $typ == 'A' ]]; then |
| 169 | + key=${key@Q} |
| 170 | + fi |
| 171 | + |
| 172 | + # always safely quote the value |
| 173 | + value=${value@Q} |
| 174 | + |
| 175 | + printf ' [%s]=%s\n' \ |
| 176 | + "${color_key}$key${color_rst}" \ |
| 177 | + "${color_value}$value${color_rst}" |
| 178 | + done |
| 179 | + echo ')' |
| 180 | + else |
| 181 | + # we are just a simple scalar value - print this as a regular, |
| 182 | + # safely-quoted, value. |
| 183 | + echo "${color_value}${__vardump_name@Q}${color_rst}" |
| 184 | + fi |
| 185 | + |
| 186 | + # optionally print the trailer |
| 187 | + if $verbose; then |
| 188 | + echo "${color_dim}--------------------------${color_rst}" |
| 189 | + fi |
| 190 | + |
| 191 | + return 0 |
192 | 192 |
|
193 | 193 | } |
194 | 194 |
|
195 | 195 | # if we are run directly (not-sourced) then run through some examples |
196 | 196 | if ! (return &>/dev/null); then |
197 | | -declare s='some string' |
198 | | -declare -r READ_ONLY='this cant be changed' |
199 | | -declare -i int_value=5 |
200 | | - |
201 | | -declare -a simple_array=(foo bar baz "$(tput setaf 1)red$(tput sgr0)") |
202 | | -declare -a sparse_array=([0]=hi [5]=bye [7]=ok) |
203 | | -declare -A assoc_array=([foo]=1 [bar]=2) |
204 | | - |
205 | | -echo 'simple vardump' |
206 | | -for var in s READ_ONLY int_value simple_array sparse_array assoc_array; do |
207 | | -vardump "$var" |
208 | | -done |
209 | | - |
210 | | -echo 'verbose vardump' |
211 | | -for var in s READ_ONLY int_value simple_array sparse_array assoc_array; do |
212 | | -vardump -v "$var" |
213 | | -echo |
214 | | -done |
| 197 | + declare s='some string' |
| 198 | + declare -r READ_ONLY='this cant be changed' |
| 199 | + declare -i int_value=5 |
| 200 | + |
| 201 | + declare -a simple_array=(foo bar baz "$(tput setaf 1)red$(tput sgr0)") |
| 202 | + declare -a sparse_array=([0]=hi [5]=bye [7]=ok) |
| 203 | + declare -A assoc_array=([foo]=1 [bar]=2) |
| 204 | + |
| 205 | + echo 'simple vardump' |
| 206 | + for var in s READ_ONLY int_value simple_array sparse_array assoc_array; do |
| 207 | + vardump "$var" |
| 208 | + done |
| 209 | + |
| 210 | + echo 'verbose vardump' |
| 211 | + for var in s READ_ONLY int_value simple_array sparse_array assoc_array; do |
| 212 | + vardump -v "$var" |
| 213 | + echo |
| 214 | + done |
215 | 215 | fi |
0 commit comments