Skip to content
Newer
Older
100755 179 lines (155 sloc) 3.58 KB
4155609 @nrr Make the spark script work on systems like NetBSD where bash lives so…
nrr authored
1 #!/usr/bin/env bash
8b17457 @holman ▁▂▃▅▂▇
holman authored
2 #
3 # spark
4 # https://github.com/holman/spark
5 #
6 # Generates sparklines for a set of data.
7 #
8 # Here's a a good web-based sparkline generator that was a bit of inspiration
9 # for spark:
10 #
11 # https://datacollective.org/sparkblocks
12 #
13 # spark takes a comma-separated list of data and then prints a sparkline out of
14 # it.
15 #
16 # Examples:
17 #
18 # spark 1,5,22,13,53
19 # # => ▁▁▃▂▇
20 #
21 # spark 0,30,55,80,33,150
22 # # => ▁▂▃▅▂▇
23 #
24 # spark -h
25 # # => Prints the spark help text.
26 set -e
ccd59de @mjdominus -d flag to enable debugging mode
authored
27 debug='false'
810265a @mjdominus -z option puts spark baseline at 0 instead of at min
authored
28 zero_baseline='false'
8b17457 @holman ▁▂▃▅▂▇
holman authored
29
30 # Prints the help text for spark.
31 #
32 # Returns nothing.
33 help()
34 {
4ecdbe2 @rentalcustard Fix usage text formatting
rentalcustard authored
35 cat <<-EOF
1602499 @holman reformat help
holman authored
36
4ecdbe2 @rentalcustard Fix usage text formatting
rentalcustard authored
37 USAGE:
38 spark [comma,separated,value,list]
1602499 @holman reformat help
holman authored
39
4ecdbe2 @rentalcustard Fix usage text formatting
rentalcustard authored
40 EXAMPLES:
41 spark 1,5,22,13,53
42 ▁▁▃▂▇
43 spark 0,30,55,80,33,150
44 ▁▂▃▅▂▇
45 EOF
8b17457 @holman ▁▂▃▅▂▇
holman authored
46 }
47
48 # The actual fun characters we are generating in the sparkline.
d29b332 @mjdominus add full-height block
authored
49 ticks=(▁ ▂ ▃ ▄ ▅ ▆ ▇ █)
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
50 number_of_tiers=$(( ${#ticks[@]} - 1 ))
8b17457 @holman ▁▂▃▅▂▇
holman authored
51 # The numbers the user gave us.
52 numbers=()
53
54 # The sorted array of the numbers.
55 sorted=()
56
57 # This sets up our secondary array so we can actually generate the correct
58 # tick.
59 #
60 # Returns nothing.
61 setup_array() {
62 # 3,6,2 => 2,3,6
63 sorted=$(echo $1 | tr ',' '\n' | sort -k1,1n | paste -s -d',' -)
64
65 # convert comma-separated string to array
66 IFS=,
67 sorted=($sorted)
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
68
69 to_rational ${sorted[0]}
810265a @mjdominus -z option puts spark baseline at 0 instead of at min
authored
70 if $zero_baseline ; then
71 min_n=0
72 min_d=1
73 else
74 min_n=$n
75 min_d=$d
76 fi
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
77
78 to_rational ${sorted[${#sorted[@]} - 1]}
79 max_n=$n
80 max_d=$d
81
82 range_n=$(( max_n * min_d - min_n * max_d ))
83 range_d=$(( max_d * min_d ))
160842a @mjdominus handle special case where min=max
authored
84 if [[ $range_n = 0 ]] ; then
85 range_n=1
86 range_d=1
87 fi
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
88
8b17457 @holman ▁▂▃▅▂▇
holman authored
89 numbers=($1)
90 }
91
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
92 # given an input number which might be a decimal, convert it to
93 # a rational number; set n and d to its numerator and
94 # denominator. For example, 3.3 becomes n=33 and d=10;
95 # 17 becomes n=17 and d=1.
96 to_rational() {
97 # Crapulent bash can't handle decimal numbers, so we will convert
98 # the input number to a rational
99 if [[ $1 =~ (.*)\.(.*) ]] ; then
100 i_part=${BASH_REMATCH[1]}
101 f_part=${BASH_REMATCH[2]}
102 n="$i_part$f_part";
103 d=$(( 10 ** ${#f_part} ))
104 else
105 n=$1
106 d=1
107 fi
8b17457 @holman ▁▂▃▅▂▇
holman authored
108 }
109
110 # Determines what tick we should print for this number and prints it.
111 #
112 # Returns nothing.
113 print_tick()
114 {
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
115 # The following rigamarole calculates
116 # ($number - $min) / $tier_size
117 # using rational arithmetic. This is necessary because $((...)) only
118 # does integer calculations and because shelling out to bc or dc is
119 # slow and nonportable
120 to_rational $1
810265a @mjdominus -z option puts spark baseline at 0 instead of at min
authored
121
0cde7d0 @mjdominus Use rational arithmetic instead of bc
authored
122 tick_index_d=$(( range_n * d * min_d ))
123 tick_index_n=$(( ( n * min_d - min_n * d ) * number_of_tiers * range_d ))
124
125 # round to nearest integer: first add 1/2
126 tick_index_an=$(( tick_index_n * 2 + tick_index_d ))
127 tick_index_ad=$(( tick_index_d * 2 ))
128
129 # divide and truncate
130 tick_index=$(( tick_index_an / tick_index_ad ))
131
132 if $debug; then
133 echo "$number $tick_index_n / $tick_index_d = $tick_index"
ccd59de @mjdominus -d flag to enable debugging mode
authored
134 else
135 echo -n ${ticks[$tick_index]};
136 fi
d5afa01 @mjdominus fix arithmetic errors
authored
137 }
8b17457 @holman ▁▂▃▅▂▇
holman authored
138
d5afa01 @mjdominus fix arithmetic errors
authored
139 # Iterate over all of our data and print them out.
8b17457 @holman ▁▂▃▅▂▇
holman authored
140 #
141 # Returns nothing.
142 print_ticks()
143 {
144 for number in ${numbers[@]}
145 do
a179f1f @peff print sparks incrementally instead of building string
peff authored
146 print_tick $number
8b17457 @holman ▁▂▃▅▂▇
holman authored
147 done
a179f1f @peff print sparks incrementally instead of building string
peff authored
148 echo
8b17457 @holman ▁▂▃▅▂▇
holman authored
149 }
150
810265a @mjdominus -z option puts spark baseline at 0 instead of at min
authored
151 while getopts ":hdz" option; do
8b17457 @holman ▁▂▃▅▂▇
holman authored
152 case "$option" in
153 h) help && exit ;;
154 # [?]) echo "$OPTARG";;
810265a @mjdominus -z option puts spark baseline at 0 instead of at min
authored
155 d) debug='true'; shift $((OPTIND-1)) ;;
156 z) zero_baseline='true'; shift $((OPTIND-1)) ;;
8b17457 @holman ▁▂▃▅▂▇
holman authored
157 esac
158 done
159
160 # Accept input from $1 or from the pipeline.
7736c9e @patricklucas Change back to using 'test' for string equality
patricklucas authored
161 if test "$*" != ""
8b17457 @holman ▁▂▃▅▂▇
holman authored
162 then
b597103 @patricklucas Allow spaced input
patricklucas authored
163 data="$*"
8b17457 @holman ▁▂▃▅▂▇
holman authored
164 else
c4fde8a @holman don't hang on tty (closes #1)
holman authored
165 # check to see if stdin's a tty
166 if [ -t 0 ]; then
167 help
168 exit
169 fi
170
424194d @peff drop pointless loop
peff authored
171 read data
8b17457 @holman ▁▂▃▅▂▇
holman authored
172 fi
173
b597103 @patricklucas Allow spaced input
patricklucas authored
174 # Trim spaces to allow input like '1, 2, 3'
01520cb @gwern generalize to translating all whitespace, not one character (the space)
gwern authored
175 data=$(echo $data | tr -s '[:space:]' ',')
b597103 @patricklucas Allow spaced input
patricklucas authored
176
8b17457 @holman ▁▂▃▅▂▇
holman authored
177 setup_array $data
178 print_ticks $data
Something went wrong with that request. Please try again.