length padding on formatted values
[barcat.git] / barcat
diff --git a/barcat b/barcat
index 5181143fe9bdd92d1544dc49b69f07e52ddaa754..061b256a10b2cdeb997f7ecac8d56c8cad3ca6ef 100755 (executable)
--- a/barcat
+++ b/barcat
@@ -20,11 +20,14 @@ GetOptions(\%opt,
                eval {
                        local $_ = $_[1];
                        s/\A[0-9]+\z/(?:\\S*\\h+){$_}\\K/;
-                       s/\A[+]([0-9]*)\z/(?:\\d+\\D+\\b){$1}\\K \\s* (?=\\d)/;
+                       s{\A[+]([0-9]*)\z}{
+                               (!!$1 && '(?:\d+\D+\b){'.$1.'}\K') . '\s* (?=\d)'
+                       }e;
                        $opt{anchor} = qr/$_/;
                } or die $@ =~ s/(?:\ at\ \N+)?\Z/ for option $_[0]/r;
        },
        'human-readable|H!',
+       'sexagesimal!',
        'interval|t:i',
        'trim|length|l=s' => sub {
                my ($optname, $optval) = @_;
@@ -113,7 +116,7 @@ $opt{trim}   *= $opt{width} / 100 if $opt{trimpct};
 $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'} = 4 if $opt{units};
 $opt{'value-length'} = 1 if $opt{unmodified};
 $opt{'signal-stat'} //= exists $SIG{INFO} ? 'INFO' : 'QUIT';
 $opt{markers} //= '=avg >31.73v <68.27v +50v |0';
@@ -127,7 +130,10 @@ $opt{input} = (@ARGV && $ARGV[0] =~ m/\A[-0-9]/) ? \@ARGV : undef
 
 $opt{'sum-format'} = sub { sprintf '%.8g', $_[0] };
 $opt{'calc-format'} = sub { sprintf '%*.*f', 0, 2, $_[0] };
-$opt{'value-format'} = $opt{units} && sub {
+$opt{'value-format'} = $opt{sexagesimal} ? sub {
+       my $s = abs($_[0]) + .5;
+       sprintf('%s%d:%02d:%02d', $_[0] < 0 && '-', $s/3600, $s/60%60, $s%60);
+} : $opt{units} && sub {
        my $unit = (
                log(abs $_[0] || 1) / log(10)
                - 3 * (abs($_[0]) < .9995)   # shift to smaller unit if below 1
@@ -307,8 +313,9 @@ while ($nr <= $limit) {
        print $indicator if defined $indicator;
 
        if (length $val) {
-               $val = $opt{'value-format'} ? $opt{'value-format'}->($val) :
-                       sprintf "%*s", $lenval, $val;
+               $val = sprintf("%*s", $lenval,
+                       $opt{'value-format'} ? $opt{'value-format'}->($val) : $val
+               );
                color($color) for $val;
        }
        my $line = $lines[$nr] =~ s/\n/$val/r;
@@ -378,6 +385,7 @@ Options:
       --header             Prepend a chart axis with minimum and maximum
                            values labeled
   -H, --human-readable     Format values using SI unit prefixes
+      --sexagesimal        Convert seconds to HH:MM:SS time format
   -t, --interval[=(N|-LINES)]
                            Output partial progress every given number of
                            seconds or input lines
@@ -465,6 +473,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.
 
+=item --sexagesimal
+
+Convert seconds to HH:MM:SS time format.
+
 =item -t, --interval[=(<seconds> | -<lines>)]
 
 Output partial progress every given number of seconds or input lines.
@@ -605,7 +617,17 @@ Compare file sizes (with human-readable numbers):
 
 Same from formatted results, selecting the first numeric value:
 
-    tree -s --noreport | barcat -H -f+0
+    tree -s --noreport | barcat -H -f+
+
+Compare media metadata, like image size or play time:
+
+    exiftool -T -p '$megapixels ($imagesize) $filename' * | barcat
+
+    exiftool -T -p '$duration# $avgbitrate# $filename' * | barcat --sexagesimal
+
+    find -type f -print0 | xargs -0 -L1 \
+    ffprobe -show_format -of json -v error |
+    jq -r '.format|.duration+" "+.bit_rate+" "+.filename' | barcat --sex
 
 Memory usage of user processes with long names truncated: