apply value formatting to statistics
[barcat.git] / barcat
diff --git a/barcat b/barcat
index 0ab19d9c1159eb7349cf005cd52f0d6ebfc38e22..82f0fffd51870985cf19a30503e9e4dcb24535f6 100755 (executable)
--- a/barcat
+++ b/barcat
@@ -11,6 +11,7 @@ our $VERSION = '1.07';
 use Getopt::Long '2.33', qw( :config gnu_getopt );
 my %opt;
 GetOptions(\%opt,
+       'ascii|a!',
        'color|c!',
        'C' => sub { $opt{color} = 0 },
        'field|f=s' => sub {
@@ -50,7 +51,9 @@ GetOptions(\%opt,
                $opt{'graph-format'} = substr $_[1], 0, 1;
        },
        'spark:s' => sub {
-               $opt{spark} = [split //, $_[1] || ' ▁▂▃▄▅▆▇█'];
+               $opt{spark} = [split //,
+                       $_[1] || ($opt{ascii} ? ' ..oOO' : ' ▁▂▃▄▅▆▇█')
+               ];
        },
        'palette=s' => sub {
                $opt{palette} = {
@@ -119,7 +122,8 @@ $opt{width} ||= $ENV{COLUMNS} || qx(tput cols) || 80 unless $opt{spark};
 $opt{color} //= -t *STDOUT;  # enable on tty
 $opt{'graph-format'} //= '-';
 $opt{trim}   *= $opt{width} / 100 if $opt{trimpct};
-$opt{units}   = [split //, ' kMGTPEZYyzafpnμm'] if $opt{'human-readable'};
+$opt{units}   = [split //, ' kMGTPEZYyzafpn'.($opt{ascii} ? 'u' : 'μ').'m']
+       if $opt{'human-readable'};
 $opt{anchor} //= qr/\A/;
 $opt{'value-length'} = 6 if $opt{units};
 $opt{'value-length'} = 1 if $opt{unmodified};
@@ -130,6 +134,19 @@ $opt{hidemin} = ($opt{hidemin} || 1) - 1;
 $opt{input} = (@ARGV && $ARGV[0] =~ m/\A[-0-9]/) ? \@ARGV : undef
        and undef $opt{interval};
 
+$opt{'sum-format'} = sub { sprintf '%.8g', $_[0] };
+$opt{'calc-format'} = sub { sprintf '%*.*f', 0, 2, $_[0] };
+$opt{'value-format'} = $opt{units} && sub {
+       my $unit = int(log(abs $_[0] || 1) / log(10) - 3*($_[0] < 1) + 1e-15);
+       my $float = $_[0] !~ /^0*[-0-9]{1,3}$/;
+       sprintf('%3.*f%1s',
+               $float && ($unit % 3) == ($unit < 0),  # tenths
+               $_[0] / 1000 ** int($unit/3),   # number
+               $#{$opt{units}} * 1.5 < abs $unit ? "e$unit" : $opt{units}->[$unit/3]
+       );
+};
+
+
 my (@lines, @values, @order);
 
 $SIG{$_} = \&show_stat for $opt{'signal-stat'} || ();
@@ -166,7 +183,7 @@ while (defined ($_ = $opt{input} ? shift @{ $opt{input} } : readline)) {
                }
                elsif (length > $trimpos) {
                        # cut and replace (intentional lvalue for speed, contrary to PBP)
-                       substr($_, $trimpos - 1) = '…';
+                       substr($_, $trimpos - 1) = $opt{ascii} ? '>' : '…';
                }
        }
        push @lines, $_;
@@ -186,16 +203,6 @@ sub color {
        $_ = color(@_) . $_ . color(0) if defined;
 }
 
-sub sival {
-       my $unit = int(log(abs $_[0] || 1) / log(10) - 3*($_[0] < 1) + 1e-15);
-       my $float = $_[0] !~ /\A0*[-0-9]{1,3}\z/;
-       return sprintf('%3.*f%1s',
-               $float && ($unit % 3) == ($unit < 0),  # tenths
-               $_[0] / 1000 ** int($unit/3),   # number
-               $#{$opt{units}} * 1.5 < abs $unit ? "e$unit" : $opt{units}->[$unit/3]
-       );
-}
-
 sub show_lines {
 
 state $nr = $opt{hidemin};
@@ -289,7 +296,8 @@ while ($nr <= $#lines) {
        }
 
        if (length $val) {
-               $val = $opt{units} ? sival($val) : sprintf "%*s", $lenval, $val;
+               $val = $opt{'value-format'} ? $opt{'value-format'}->($val) :
+                       sprintf "%*s", $lenval, $val;
                color($color) for $val;
        }
        my $line = $lines[$nr] =~ s/\n/$val/r;
@@ -308,19 +316,19 @@ say $opt{palette} ? color(0) : '' if $opt{spark};
 
 sub show_stat {
        if ($opt{hidemin} or $opt{hidemax}) {
-               printf '%.8g of ', sum(grep { length }
+               printf '%.8g of ', $opt{'sum-format'}->(sum(grep { length }
                        @values[$opt{hidemin} .. ($opt{hidemax} || @lines) - 1]
-               ) // 0;
+               ) // 0);
        }
        if (@order) {
                my $total = sum @order;
-               printf '%s total', color(1) . sprintf('%.8g', $total) . color(0);
+               printf '%s total', color(1) . $opt{'sum-format'}->($total) . color(0);
                printf ' in %d values', scalar @order;
                printf ' over %d lines', scalar @lines if @order != @lines;
                printf(' (%s min, %s avg, %s max)',
-                       color(31) . $order[-1] . color(0),
-                       color(36) . (sprintf '%*.*f', 0, 2, $total / @order) . color(0),
-                       color(32) . $order[0] . color(0),
+                       color(31) . ($opt{'value-format'} || sub {$_[0]})->($order[-1]) . color(0),
+                       color(36) . ($opt{'value-format'} || $opt{'calc-format'})->($total / @order) . color(0),
+                       color(32) . ($opt{'value-format'} || sub {$_[0]})->($order[0]) . color(0),
                );
        }
        say '';
@@ -364,6 +372,12 @@ you'll need a larger animal like I<gnuplot>.
 
 =over
 
+=item -a, --[no-]ascii
+
+Restrict user interface to ASCII characters,
+replacing default UTF-8 by their closest approximation.
+Input is always interpreted as UTF-8 and shown as is.
+
 =item -c, --[no-]color
 
 Force colored output of values and bar markers.