X-Git-Url: http://git.shiar.nl/barcat.git/blobdiff_plain/d8b46e635b34f40972271b6bdf1ea2383e3bff2a..4855cd33928ac5c3003ad747048a7e5d5477bff8:/barcat diff --git a/barcat b/barcat index 5d0f85c..8e104c9 100755 --- a/barcat +++ b/barcat @@ -8,8 +8,10 @@ use re '/msx'; our $VERSION = '1.07'; -use Getopt::Long '2.33', qw( :config gnu_getopt ); my %opt; +if (@ARGV) { +require Getopt::Long; +Getopt::Long->import('2.33', qw( :config gnu_getopt )); GetOptions(\%opt, 'ascii|a!', 'color|c!', @@ -82,33 +84,7 @@ GetOptions(\%opt, exit; }, 'usage|h' => sub { - local $/ = undef; # slurp - my $pod = readline *DATA; - $pod =~ s/^=over\K/ 25/; # indent options list - $pod =~ s{ - ^=item \h \N*\n\n \N*\n \K # first line - (?: (?: ^=over .*? ^=back\n )? (?!=) \N*\n )* - }{\n}g; # abbreviate options - $pod =~ s/[.,](?=\n)//g; # trailing punctuation - $pod =~ s/^=item\ \K(?=--)/____/g; # align long options - # abbreviate indicators - $pod =~ s/\Q>.../s>/g; - $pod =~ s/<(?:number|count|seconds)>/N/g; - $pod =~ s//\Uchar$1/g; - $pod =~ s/\Q | /|/g; - $pod =~ s/(?/\U$1/g; # uppercase - - require Pod::Usage; - my $parser = Pod::Usage->new(USAGE_OPTIONS => { - -indent => 2, -width => 78, - }); - $parser->select('SYNOPSIS', 'OPTIONS'); - $parser->output_string(\my $contents); - $parser->parse_string_document($pod); - - $contents =~ s/\n(?=\n\h)//msg; # strip space between items - $contents =~ s/^\ \ \K____/ /g; # nbsp substitute - print $contents; + /^=/ ? last : print for readline *DATA; # text between __END__ and pod exit; }, 'help|?' => sub { @@ -118,6 +94,7 @@ GetOptions(\%opt, ); }, ) or exit 64; # EX_USAGE +} $opt{width} ||= $ENV{COLUMNS} || qx(tput cols) || 80 unless $opt{spark}; $opt{color} //= -t *STDOUT; # enable on tty @@ -138,12 +115,21 @@ $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 { - 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 $unit = ( + log(abs $_[0] || 1) / log(10) + - 3 * (abs($_[0]) < .9995) # shift to smaller unit if below 1 + + 1e-15 # float imprecision + ); + my $decimal = ($unit % 3) == ($unit < 0); + $unit -= log($decimal ? .995 : .9995) / log(10); # rounded + $decimal = ($unit % 3) == ($unit < 0); + $decimal &&= $_[0] !~ /^-?0*[0-9]{1,3}$/; # integer 0..999 + sprintf('%*.*f%1s', + 3 + ($_[0] < 0), # digits plus optional negative sign + $decimal, # tenths + $_[0] / 1000 ** int($unit/3), # number + $#{$opt{units}} * 1.5 < abs $unit ? sprintf('e%d', $unit) : + $opt{units}->[$unit/3] # suffix ); }; @@ -209,12 +195,21 @@ sub show_lines { state $nr = $opt{hidemin} < 0 ? @lines + $opt{hidemin} + 1 : $opt{hidemin}; -@lines or return; @lines > $nr or return; +my $limit = $#lines; +if (defined $opt{hidemax}) { + if ($opt{hidemin} and $opt{hidemin} < 0) { + $limit -= $opt{hidemax} - 1; + } + else { + $limit = $opt{hidemax} - 1; + } +} + @order = sort { $b <=> $a } @order unless tied @order; my $maxval = $opt{maxval} // ( - $opt{hidemax} ? max grep { length } @values[0 .. $opt{hidemax} - 1] : + $opt{hidemax} ? max grep { length } @values[$nr .. $limit] : $order[0] ) // 0; my $minval = $opt{minval} // min $order[-1] // (), 0; @@ -277,8 +272,7 @@ say( color(0), ) if $opt{header}; -while ($nr <= $#lines) { - $nr >= $opt{hidemax} and last if defined $opt{hidemax}; +while ($nr <= $limit) { my $val = $values[$nr]; my $rel = length $val && $range && ($val - $minval) / $range; my $color = !length $val || !$opt{palette} ? undef : @@ -304,6 +298,10 @@ while ($nr <= $#lines) { color($color) for $val; } my $line = $lines[$nr] =~ s/\n/$val/r; + if (not length $val) { + say $line; + next; + } printf '%-*s', $len + length($val), $line; print $barmark[$_] // $opt{'graph-format'} for 1 .. $size && (($values[$nr] || 0) - $minval) * $size + .5; @@ -320,8 +318,11 @@ say $opt{palette} ? color(0) : '' if $opt{spark}; sub show_stat { if ($opt{hidemin} or $opt{hidemax}) { my $linemin = $opt{hidemin}; - $linemin += @lines if $linemin < 0; my $linemax = ($opt{hidemax} || @lines) - 1; + if ($linemin < 0) { + $linemin += @lines; + $linemax = @lines - $linemax; + } printf '%.8g of ', $opt{'sum-format'}->( sum(grep {length} @values[$linemin .. $linemax]) // 0 ); @@ -351,6 +352,37 @@ sub show_exit { show_exit(); __END__ +Usage: + barcat [OPTIONS] [FILES|NUMBERS] + +Options: + -a, --[no-]ascii Restrict user interface to ASCII characters + -c, --[no-]color Force colored output of values and bar markers + -f, --field=(N|REGEXP) Compare values after a given number of whitespace + separators + --header Prepend a chart axis with minimum and maximum + values labeled + -H, --human-readable Format values using SI unit prefixes + -t, --interval[=(N|-LINES)] + Output partial progress every given number of + seconds or input lines + -l, --length=[-]SIZE[%] Trim line contents (between number and bars) + -L, --limit[=(N|-LAST|START-[END])] + Stop output after a number of lines + --graph-format=CHAR Glyph to repeat for the graph line + -m, --markers=FORMAT Statistical positions to indicate on bars + --min=N, --max=N Bars extend from 0 or the minimum value if lower + --palette=(PRESET|COLORS) + Override colors of parsed numbers + --spark[=CHARS] Replace lines by sparklines + -s, --stat Total statistics after all data + -u, --unmodified Do not reformat values, keeping leading whitespace + --value-length=SIZE Reserved space for numbers + -w, --width=COLUMNS Override the maximum number of columns to use + -h, --usage Overview of available options + --help Full documentation + --version Version information + =encoding utf8 =head1 NAME