5 use List::Util qw( min max sum );
6 use open qw( :std :utf8 );
10 use Getopt::Long '2.33', qw( :config gnu_getopt );
13 Pod::Usage::pod2usage(-exitval => 0, -perldocopt => '-oman', @_);
21 'usage|h' => sub { podexit() },
22 'help' => sub { podexit(-verbose => 2) },
23 ) or exit 64; # EX_USAGE
25 $opt{width} ||= $ENV{COLUMNS} || 80;
26 $opt{color} //= -t *STDOUT; # enable on tty
28 if (defined $opt{follow}) {
37 $SIG{INT} = 'IGNORE'; # continue after assumed eof
42 push @values, s/^\h* ( -? [0-9]* (?:\.[0-9]+)? )//x && $1;
43 if (defined $opt{trim}) {
44 my $trimpos = abs $opt{trim};
48 elsif (length > $trimpos) {
49 substr($_, $trimpos - 1) = '…';
56 $SIG{INT} = 'DEFAULT';
62 my @order = sort { $b <=> $a } grep { length } @values;
63 my $maxval = $order[0];
64 my $minval = min $order[-1], 0;
65 my $lenval = max map { length } @order;
66 my $len = defined $opt{trim} && $opt{trim} <= 0 ? -$opt{trim} + 1 :
67 1 + max map { length } @lines; # left padding
68 my $size = ($maxval - $minval) &&
69 ($opt{width} - $lenval - $len) / ($maxval - $minval); # bar multiplication
72 if ($opt{markers} // 1 and $size > 0) {
73 my sub orderpos { (($order[$_[0]] + $order[$_[0] + .5]) / 2 - $minval) * $size }
74 $barmark[ (sum(@order) / @order - $minval) * $size ] = '='; # average
75 $barmark[ orderpos($#order * .31731) ] = '>';
76 $barmark[ orderpos($#order * .68269) ] = '<';
77 $barmark[ orderpos($#order / 2) ] = '+'; # mean
78 $barmark[ -$minval * $size ] = '|' if $minval < 0; # zero
79 defined and $opt{color} and $_ = "\e[36m$_\e[0m" for @barmark;
81 state $lastmax = $maxval;
82 if ($maxval > $lastmax) {
83 print ' ' x ($lenval + $len);
84 printf "\e[90m" if $opt{color};
86 ($lastmax - $minval) * $size + .5,
87 '-' x (($values[$nr - 1] - $minval) * $size);
88 print "\e[92m" if $opt{color};
89 say '+' x (($maxval - $lastmax - $minval) * $size + .5);
90 print "\e[0m" if $opt{color};
95 while ($nr <= $#lines) {
96 my $val = $values[$nr];
98 my $color = !$opt{color} ? 0 :
99 $val == $order[0] ? 32 : # max
100 $val == $order[-1] ? 31 : # min
102 printf "\e[%sm", $color if $color;
103 printf "%*s", $lenval, $val;
104 print "\e[0m" if $color;
106 printf '%-*s', $len, $lines[$nr];
107 print $barmark[$_] // '-' for 1 .. $size && (($val || 0) - $minval) * $size;
119 graph - append bar chart to input numbers
123 B<graph> [<options>] [<input>]
127 Each line starting with a number is given a bar to visualise relative sizes.
133 =item -c, --[no-]color
135 Force colored output of values and bar markers.
136 Defaults on if output is a tty,
137 disabled otherwise such as when piped or redirected.
139 =item -f, --follow[=<seconds>]
141 Interval to output partial progress.
143 =item -l, --length=[-]<size>
145 Trim line contents (between number and bars)
146 to a maximum number of characters.
147 The exceeding part is replaced by an abbreviation sign,
148 unless C<--length=0>.
150 Prepend a dash (i.e. make negative) to enforce padding
151 regardless of encountered contents.
155 Statistical positions to indicate on bars.
156 Cannot be customized yet,
157 only disabled by providing an empty argument.
159 Any value enables all marker characters:
166 the sum of all values divided by the number of counted lines.
171 the middle value or average between middle values.
175 Standard deviation left of the mean.
176 Only 16% of all values are lower.
180 Standard deviation right of the mean.
181 The part between B<< <--> >> encompass all I<normal> results,
182 or 68% of all entries.
186 =item -w, --width=<columns>
188 Override the maximum number of columns to use.
189 Appended graphics will extend to fill up the entire screen.
195 Commonly used after counting, such as users on the current server:
197 users | sed 's/ /\n/g' | sort | uniq -c | graph
199 Letter frequencies in text files:
201 cat /usr/share/games/fortunes/*.u8 |
202 perl -CO -nE 'say for grep length, split /\PL*/, uc' |
203 sort | uniq -c | graph
205 Memory usage of user processes:
207 ps xo %mem,pid,cmd | graph -l40
209 Sizes (in megabytes) of all root files and directories:
213 Number of HTTP requests per day:
215 cat log/access.log | cut -d\ -f4 | cut -d: -f1 | uniq -c | graph
217 Any kind of database query with leading counts:
219 echo 'SELECT count(*),schemaname FROM pg_tables GROUP BY 2' |
222 Git statistics, such commit count by year:
224 git log --pretty=%ci | cut -b-4 | uniq -c | graph
226 Or the most frequent authors:
228 git shortlog -sn | graph | head -3
233 perl -pe '$|=1; print s/ time=(.*)// ? "$1 for " : "> "' | graph -f
237 Mischa POSLAWSKY <perl@shiar.org>