graph length rounded to nearest integer
[barcat.git] / graph
diff --git a/graph b/graph
index 309510615e9edbb3b573102e2fb280fb4557c3bf..1a70964c320bc2b66fc0abb8ca09112a0e675656 100755 (executable)
--- a/graph
+++ b/graph
@@ -17,6 +17,7 @@ my %opt;
 GetOptions(\%opt,
        'color|c!',
        'C' => sub { $opt{color} = 0 },
 GetOptions(\%opt,
        'color|c!',
        'C' => sub { $opt{color} = 0 },
+       'field|f=s',
        'interval|t:i',
        'trim|length|l=s' => sub {
                my ($optname, $optval) = @_;
        'interval|t:i',
        'trim|length|l=s' => sub {
                my ($optname, $optval) = @_;
@@ -27,6 +28,7 @@ GetOptions(\%opt,
                );
                $opt{trim} = $optval;
        },
                );
                $opt{trim} = $optval;
        },
+       'value-length=i',
        'markers|m=s',
        'unmodified|u!',
        'width|w=i',
        'markers|m=s',
        'unmodified|u!',
        'width|w=i',
@@ -50,10 +52,13 @@ if (defined $opt{interval}) {
 $SIG{INT} = 'IGNORE';  # continue after assumed eof
 
 my (@lines, @values);
 $SIG{INT} = 'IGNORE';  # continue after assumed eof
 
 my (@lines, @values);
+my $anchor = !defined $opt{field} ? qr/\A/ :
+       $opt{field} =~ /^[0-9]+$/ ? qr/(?:\S*\h+){$opt{field}}\K/ :
+       $opt{field};
 while (readline) {
        s/\r?\n\z//;
        s/^\h*// unless $opt{unmodified};
 while (readline) {
        s/\r?\n\z//;
        s/^\h*// unless $opt{unmodified};
-       push @values, s/^ ( \h* -? [0-9]* \.? [0-9]+ |)/\n/x && $1;
+       push @values, s/$anchor ( \h* -? [0-9]* \.? [0-9]+ |)/\n/x && $1;
        if (defined $opt{trim}) {
                my $trimpos = abs $opt{trim};
                if ($trimpos <= 1) {
        if (defined $opt{trim}) {
                my $trimpos = abs $opt{trim};
                if ($trimpos <= 1) {
@@ -76,7 +81,7 @@ state $nr = 0;
 my @order  = sort { $b <=> $a } grep { length } @values;
 my $maxval = $order[0];
 my $minval = min $order[-1], 0;
 my @order  = sort { $b <=> $a } grep { length } @values;
 my $maxval = $order[0];
 my $minval = min $order[-1], 0;
-my $lenval = max map { length } @order;
+my $lenval = $opt{'value-length'} // max map { length } @order;
 my $len    = defined $opt{trim} && $opt{trim} <= 0 ? -$opt{trim} + 1 :
        max map { length $values[$_] && length $lines[$_] } 0 .. $#lines;  # left padding
 my $size   = ($maxval - $minval) &&
 my $len    = defined $opt{trim} && $opt{trim} <= 0 ? -$opt{trim} + 1 :
        max map { length $values[$_] && length $lines[$_] } 0 .. $#lines;  # left padding
 my $size   = ($maxval - $minval) &&
@@ -116,9 +121,9 @@ while ($nr <= $#lines) {
                $val = sprintf "%*s", $lenval, $val;
                $val = "\e[${color}m$val\e[0m" if $color;
        }
                $val = sprintf "%*s", $lenval, $val;
                $val = "\e[${color}m$val\e[0m" if $color;
        }
-       $lines[$nr] =~ s/\n/$val/;
-       printf '%-*s', $len + length($val), $lines[$nr];
-       print $barmark[$_] // '-' for 1 .. $size && (($values[$nr] || 0) - $minval) * $size;
+       my $line = $lines[$nr] =~ s/\n/$val/r;
+       printf '%-*s', $len + length($val), $line;
+       print $barmark[$_] // '-' for 1 .. $size && (($values[$nr] || 0) - $minval) * $size + .5;
        say '';
        $nr++;
 }
        say '';
        $nr++;
 }
@@ -138,7 +143,9 @@ B<graph> [<options>] [<input>]
 
 =head1 DESCRIPTION
 
 
 =head1 DESCRIPTION
 
-Each line starting with a number is given a bar to visualise relative sizes.
+Visualizes relative sizes of values read from input (file(s) or STDIN).
+Contents are concatenated similar to I<cat>,
+but numbers are reformatted and a bar graph is appended to each line.
 
 =head1 OPTIONS
 
 
 =head1 OPTIONS
 
@@ -150,6 +157,18 @@ Force colored output of values and bar markers.
 Defaults on if output is a tty,
 disabled otherwise such as when piped or redirected.
 
 Defaults on if output is a tty,
 disabled otherwise such as when piped or redirected.
 
+=item -f, --field=(<number>|<regexp>)
+
+Compare values after a given number of whitespace separators,
+or matching a regular expression.
+
+Unspecified or I<-f0> means values are at the start of each line.
+With I<-f1> the second word is taken instead.
+A string can indicate the starting position of a value
+(such as I<-f:> if preceded by colons),
+or capture the numbers itself,
+for example I<-f'(\d+)'> for the first digits anywhere.
+
 =item -t, --interval[=<seconds>]
 
 Interval time to output partial progress.
 =item -t, --interval[=<seconds>]
 
 Interval time to output partial progress.
@@ -202,6 +221,10 @@ or 68% of all entries.
 Do not strip leading whitespace.
 Keep original value alignment, which may be significant in some programs.
 
 Do not strip leading whitespace.
 Keep original value alignment, which may be significant in some programs.
 
+=item --value-length=<size>
+
+Reserved space for numbers.
+
 =item -w, --width=<columns>
 
 Override the maximum number of columns to use.
 =item -w, --width=<columns>
 
 Override the maximum number of columns to use.
@@ -242,13 +265,13 @@ Exchange rate USD/EUR history from CSV download provided by ECB:
 
     curl https://sdw.ecb.europa.eu/export.do \
          -Gd 'node=SEARCHRESULTS&q=EXR.D.USD.EUR.SP00.A&exportType=csv' |
 
     curl https://sdw.ecb.europa.eu/export.do \
          -Gd 'node=SEARCHRESULTS&q=EXR.D.USD.EUR.SP00.A&exportType=csv' |
-    awk -F, '{RS="\r\n"} /^[12]/{print $2,$1}' | graph
+    grep '^[12]' | graph -f',\K' --value-length=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"]' - |
 
 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"]' - |
-    awk -F'<[^>]+>' 'BEGIN {RS="</wb:value>"} {print $4,$2}' | graph
+    sed -r 's,</wb:value>,\n,g; s,(<[^>]+>)+, ,g' | graph -f1
 
 Movies per year from prepared JSON data:
 
 
 Movies per year from prepared JSON data:
 
@@ -270,8 +293,7 @@ Or the most frequent authors:
 
 Latency history:
 
 
 Latency history:
 
-    ping google.com |
-    perl -pe '$|=1; print s/ time=(.*)// ? "$1 for " : "> "' | graph -t
+    ping google.com | graph -f'time=\K' -t
 
 =head1 AUTHOR
 
 
 =head1 AUTHOR