color headers
[barcat.git] / barcat
diff --git a/barcat b/barcat
index 1818493a8af4603898a2e4b7f1265c6bcfda948d..fd110c5d14f127da94c86a8828c54965eef15a24 100755 (executable)
--- a/barcat
+++ b/barcat
@@ -6,7 +6,7 @@ use List::Util qw( min max sum );
 use open qw( :std :utf8 );
 use experimental qw( lexical_subs );
 
 use open qw( :std :utf8 );
 use experimental qw( lexical_subs );
 
-our $VERSION = '1.05';
+our $VERSION = '1.06';
 
 use Getopt::Long '2.33', qw( :config gnu_getopt );
 my %opt;
 
 use Getopt::Long '2.33', qw( :config gnu_getopt );
 my %opt;
@@ -42,13 +42,22 @@ GetOptions(\%opt,
                        " (range expected)\n"
                );
        },
                        " (range expected)\n"
                );
        },
+       'header!',
        'markers|m=s',
        'markers|m=s',
+       'graph-format=s' => sub {
+               $opt{'graph-format'} = substr $_[1], 0, 1;
+       },
        'spark:s' => sub {
                $opt{spark} = [split //, $_[1] || '⎽▁▂▃▄▅▆▇█'];
        },
        'stat|s!',
        'spark:s' => sub {
                $opt{spark} = [split //, $_[1] || '⎽▁▂▃▄▅▆▇█'];
        },
        'stat|s!',
+       'signal-stat=s',
        'unmodified|u!',
        'width|w=i',
        'unmodified|u!',
        'width|w=i',
+       'version' => sub {
+               say "barcat version $VERSION";
+               exit;
+       },
        'usage|h' => sub {
                local $/;
                my $pod = readline *DATA;
        'usage|h' => sub {
                local $/;
                my $pod = readline *DATA;
@@ -75,21 +84,26 @@ GetOptions(\%opt,
 
 $opt{width} ||= $ENV{COLUMNS} || 80;
 $opt{color} //= -t *STDOUT;  # enable on tty
 
 $opt{width} ||= $ENV{COLUMNS} || 80;
 $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{anchor} //= qr/\A/;
 $opt{'value-length'} = 6 if $opt{units};
 $opt{'value-length'} = 1 if $opt{unmodified};
 $opt{trim}   *= $opt{width} / 100 if $opt{trimpct};
 $opt{units}   = [split //, ' kMGTPEZYyzafpnμm'] if $opt{'human-readable'};
 $opt{anchor} //= qr/\A/;
 $opt{'value-length'} = 6 if $opt{units};
 $opt{'value-length'} = 1 if $opt{unmodified};
+$opt{'signal-stat'} //= exists $SIG{INFO} ? 'INFO' : 'QUIT';
 
 my (@lines, @values, @order);
 
 
 my (@lines, @values, @order);
 
+$SIG{$_} = \&show_stat for $opt{'signal-stat'} || ();
+$SIG{ALRM} = sub {
+       show_lines();
+       alarm $opt{interval} if defined $opt{interval} and $opt{interval} > 0;
+};
+$SIG{INT} = \&show_exit;
+
 if (defined $opt{interval}) {
        $opt{interval} ||= 1;
 if (defined $opt{interval}) {
        $opt{interval} ||= 1;
-       $SIG{ALRM} = sub {
-               show_lines();
-               alarm $opt{interval};
-       };
-       alarm $opt{interval};
+       alarm $opt{interval} if $opt{interval} > 0;
 
        eval {
                require Tie::Array::Sorted;
 
        eval {
                require Tie::Array::Sorted;
@@ -97,11 +111,6 @@ if (defined $opt{interval}) {
        } or warn $@, "Expect slowdown with large datasets!\n";
 }
 
        } or warn $@, "Expect slowdown with large datasets!\n";
 }
 
-$SIG{INT} = sub {
-       $SIG{INT} = 'DEFAULT';  # reset for subsequent attempts
-       'IGNORE' # continue after assumed eof
-};
-
 my $valmatch = qr/$opt{anchor} ( \h* -? [0-9]* \.? [0-9]+ (?: e[+-]?[0-9]+ )? |)/x;
 while (readline) {
        s/\r?\n\z//;
 my $valmatch = qr/$opt{anchor} ( \h* -? [0-9]* \.? [0-9]+ (?: e[+-]?[0-9]+ )? |)/x;
 while (readline) {
        s/\r?\n\z//;
@@ -119,6 +128,8 @@ while (readline) {
                }
        }
        push @lines, $_;
                }
        }
        push @lines, $_;
+       show_lines() if defined $opt{interval} and $opt{interval} < 0
+               and $. % $opt{interval} == 0;
 }
 
 $SIG{INT} = 'DEFAULT';
 }
 
 $SIG{INT} = 'DEFAULT';
@@ -182,6 +193,14 @@ sub sival {
        );
 }
 
        );
 }
 
+say(
+       color(31), sprintf('%*s', $lenval, $minval),
+       color(90), '-', color(36), '+',
+       color(32), sprintf('%*s', $size * ($maxval - $minval) - 3, $maxval),
+       color(90), '-', color(36), '+',
+       color(0),
+) if $opt{header};
+
 while ($nr <= $#lines) {
        $nr >= $opt{hidemax} and last if defined $opt{hidemax};
        my $val = $values[$nr];
 while ($nr <= $#lines) {
        $nr >= $opt{hidemax} and last if defined $opt{hidemax};
        my $val = $values[$nr];
@@ -201,7 +220,7 @@ while ($nr <= $#lines) {
        }
        my $line = $lines[$nr] =~ s/\n/$val/r;
        printf '%-*s', $len + length($val), $line;
        }
        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;
+       print $barmark[$_] // $opt{'graph-format'} for 1 .. $size && (($values[$nr] || 0) - $minval) * $size + .5;
        say '';
 }
 continue {
        say '';
 }
 continue {
@@ -210,9 +229,8 @@ continue {
 say '' if $opt{spark};
 
 }
 say '' if $opt{spark};
 
 }
-show_lines();
 
 
-if ($opt{stat}) {
+sub show_stat {
        if ($opt{hidemin} or $opt{hidemax}) {
                $opt{hidemin} ||= 1;
                $opt{hidemax} ||= @lines;
        if ($opt{hidemin} or $opt{hidemax}) {
                $opt{hidemin} ||= 1;
                $opt{hidemax} ||= @lines;
@@ -231,6 +249,15 @@ if ($opt{stat}) {
        say '';
 }
 
        say '';
 }
 
+sub show_exit {
+       show_lines();
+       show_stat() if $opt{stat};
+       exit 130 if @_;  # 0x80+signo
+       exit;
+}
+
+show_exit();
+
 __END__
 =encoding utf8
 
 __END__
 =encoding utf8
 
@@ -283,9 +310,10 @@ turning long numbers like I<12356789> into I<12.4M>.
 Also changes an exponent I<1.602176634e-19> to I<160.2z>.
 Short integers are aligned but kept without decimal point.
 
 Also changes an exponent I<1.602176634e-19> to I<160.2z>.
 Short integers are aligned but kept without decimal point.
 
-=item -t, --interval[=<seconds>]
+=item -t, --interval[=(<seconds>|-<lines>)]
 
 
-Interval time to output partial progress.
+Output partial progress every given number of seconds or input lines.
+An update can also be forced by sending a I<SIGALRM> alarm signal.
 
 =item -l, --length=[-]<size>[%]
 
 
 =item -l, --length=[-]<size>[%]
 
@@ -303,6 +331,11 @@ Stop output after a number of lines.
 All input is still counted and analyzed for statistics,
 but disregarded for padding and bar size.
 
 All input is still counted and analyzed for statistics,
 but disregarded for padding and bar size.
 
+=item --graph-format=<character>
+
+Glyph to repeat for the graph line.
+Defaults to a dash C<->.
+
 =item -m, --markers=
 
 Statistical positions to indicate on bars.
 =item -m, --markers=
 
 Statistical positions to indicate on bars.