human-readable (-H) option to abbreviate numbers
[barcat.git] / barcat
diff --git a/barcat b/barcat
index d12baf6a3cad2b8e7cab1f56c99e616301145052..db630abb6ba6d92bf0ef0d2043c61e97a840f379 100755 (executable)
--- a/barcat
+++ b/barcat
@@ -18,6 +18,7 @@ GetOptions(\%opt,
        'color|c!',
        'C' => sub { $opt{color} = 0 },
        'field|f=s',
+       'human-readable|H!',
        'interval|t:i',
        'trim|length|l=s' => sub {
                my ($optname, $optval) = @_;
@@ -29,7 +30,17 @@ GetOptions(\%opt,
                $opt{trim} = $optval;
        },
        'value-length=i',
-       'hidemax|limit|L=i',
+       'hidemin=i',
+       'hidemax=i',
+       'limit|L=s' => sub {
+               my ($optname, $optval) = @_;
+               $optval ||= 0;
+               ($opt{hidemin}, $opt{hidemax}) =
+               $optval =~ m/\A (?: ([0-9]+)? - )? ([0-9]+)? \z/x or die(
+                       "Value \"$optval\" invalid for option limit",
+                       " (range expected)\n"
+               );
+       },
        'markers|m=s',
        'unmodified|u!',
        'width|w=i',
@@ -40,6 +51,7 @@ GetOptions(\%opt,
 $opt{width} ||= $ENV{COLUMNS} || 80;
 $opt{color} //= -t *STDOUT;  # enable on tty
 $opt{trim}   *= $opt{width} / 100 if $opt{trimpct};
+$opt{units}   = $opt{'human-readable'} && ['', qw( k M G T <> n μ m )];
 
 if (defined $opt{interval}) {
        $opt{interval} ||= 1;
@@ -76,7 +88,7 @@ $SIG{INT} = 'DEFAULT';
 
 sub show_lines {
 
-state $nr = 0;
+state $nr = $opt{hidemin} ? $opt{hidemin} - 1 : 0;
 @lines and @lines > $nr or return;
 
 my @order  = sort { $b <=> $a } grep { length } @values;
@@ -121,6 +133,8 @@ while ($nr <= $#lines) {
                        $val == $order[0] ? 32 : # max
                        $val == $order[-1] ? 31 : # min
                        90;
+               $val = sprintf "%3.1f%1s", $val / 1000**$_, $opt{units}->[$_]
+                       for $opt{units} ? int(log($val) / log(1000)) : ();
                $val = sprintf "%*s", $lenval, $val;
                $val = "\e[${color}m$val\e[0m" if $color;
        }
@@ -173,6 +187,11 @@ A string can indicate the starting position of a value
 or capture the numbers itself,
 for example I<-f'(\d+)'> for the first digits anywhere.
 
+=item -H, --human-readable
+
+Format values using SI unit prefixes,
+turning long numbers like I<12356789> into I<12.4M>.
+
 =item -t, --interval[=<seconds>]
 
 Interval time to output partial progress.
@@ -187,7 +206,7 @@ unless C<--length=0>.
 Prepend a dash (i.e. make negative) to enforce padding
 regardless of encountered contents.
 
-=item -L, --limit=<count>
+=item -L, --limit=(<count>|<start>-[<end>])
 
 Stop output after a number of lines.
 All input is still counted and analyzed for statistics,
@@ -281,7 +300,7 @@ Total population history from the World Bank dataset (XML):
 
     curl http://api.worldbank.org/v2/country/1W/indicator/SP.POP.TOTL |
     xmllint --xpath '//*[local-name()="date" or local-name()="value"]' - |
-    sed -r 's,</wb:value>,\n,g; s,(<[^>]+>)+, ,g' | barcat -f1
+    sed -r 's,</wb:value>,\n,g; s,(<[^>]+>)+, ,g' | barcat -f1 -H
 
 Movies per year from prepared JSON data: