static usage text, generation code into reformat-podusage script
[barcat.git] / barcat
diff --git a/barcat b/barcat
index 82f0fffd51870985cf19a30503e9e4dcb24535f6..ce3f788ec111f137efb183f86ae3a9886cd3b79a 100755 (executable)
--- a/barcat
+++ b/barcat
@@ -39,8 +39,9 @@ GetOptions(\%opt,
        'limit|L:s' => sub {
                my ($optname, $optval) = @_;
                $optval ||= 0;
+               $optval =~ /\A-[0-9]+\z/ and $optval .= '-';  # tail shorthand
                ($opt{hidemin}, $opt{hidemax}) =
-               $optval =~ m/\A (?: ([0-9]+)? - )? ([0-9]+)? \z/ or die(
+               $optval =~ m/\A (?: (-? [0-9]+)? - )? ([0-9]+)? \z/ or die(
                        "Value \"$optval\" invalid for option limit",
                        " (range expected)\n"
                );
@@ -81,33 +82,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 <variable> indicators
-               $pod =~ s/\Q>.../s>/g;
-               $pod =~ s/<(?:number|count|seconds)>/N/g;
-               $pod =~ s/<character(s?)>/\Uchar$1/g;
-               $pod =~ s/\Q | /|/g;
-               $pod =~ s/(?<!\w)<([a-z]+)>/\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 {
@@ -205,13 +180,24 @@ sub color {
 
 sub show_lines {
 
-state $nr = $opt{hidemin};
-@lines or return;
+state $nr =
+       $opt{hidemin} < 0 ? @lines + $opt{hidemin} + 1 :
+       $opt{hidemin};
 @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;
@@ -274,8 +260,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 :
@@ -316,9 +301,15 @@ say $opt{palette} ? color(0) : '' if $opt{spark};
 
 sub show_stat {
        if ($opt{hidemin} or $opt{hidemax}) {
-               printf '%.8g of ', $opt{'sum-format'}->(sum(grep { length }
-                       @values[$opt{hidemin} .. ($opt{hidemax} || @lines) - 1]
-               ) // 0);
+               my $linemin = $opt{hidemin};
+               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
+               );
        }
        if (@order) {
                my $total = sum @order;
@@ -345,6 +336,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
@@ -422,9 +444,13 @@ unless C<--length=0>.
 Prepend a dash (i.e. make negative) to enforce padding
 regardless of encountered contents.
 
-=item -L, --limit[=(<count> | <start>-[<end>])]
+=item -L, --limit[=(<count> | -<last> | <start>-[<end>])]
 
 Stop output after a number of lines.
+A single value indicates the last line number (like C<head>),
+or first line counting from the bottom if negative (like C<tail>).
+A specific range can be given by two values.
+
 All input is still counted and analyzed for statistics,
 but disregarded for padding and bar size.