#!perl

### code_after_shebang
# Note: This script is a CLI  for Riap function /App/td/td
# and generated automatically using Perinci::CmdLine::Gen version 0.39

# PERICMD_INLINE_SCRIPT: {"url":"/App/td/td","script_version":"0.08","include":null,"log":null,"code_after_shebang":"...","skip_format":0,"script_name":"td","script_summary":null,"shebang":"perl","subcommands":null}

# This script is generated by Perinci::CmdLine::Inline version 0.40 on Sun Jan  1 13:05:06 2017.
# You probably should not manually edit this file.

our $DATE = '2017-01-01'; # DATE
our $VERSION = '0.08'; # VERSION
# PODNAME: td
# ABSTRACT: Manipulate table data

# BEGIN DATAPACK CODE
{
    my $toc;
    my $data_linepos = 1;
    unshift @INC, sub {
        $toc ||= do {

            my $fh = \*DATA;

        my $header_line;
        my $header_found;
        while (1) {
            my $header_line = <$fh>;
            defined($header_line)
                or die "Unexpected end of data section while reading header line";
            chomp($header_line);
            if ($header_line eq 'Data::Section::Seekable v1') {
                $header_found++;
                last;
            }
        }
        die "Can't find header 'Data::Section::Seekable v1'"
            unless $header_found;

        my %toc;
        my $i = 0;
        while (1) {
            $i++;
            my $toc_line = <$fh>;
            defined($toc_line)
                or die "Unexpected end of data section while reading TOC line #$i";
            chomp($toc_line);
            $toc_line =~ /\S/ or last;
            $toc_line =~ /^([^,]+),(\d+),(\d+)(?:,(.*))?$/
                or die "Invalid TOC line #$i in data section: $toc_line";
            $toc{$1} = [$2, $3, $4];
        }
        my $pos = tell $fh;
        $toc{$_}[0] += $pos for keys %toc;


            # calculate the line number of data section
            my $data_pos = tell(DATA);
            seek DATA, 0, 0;
            my $pos = 0;
            while (1) {
                my $line = <DATA>;
                $pos += length($line);
                $data_linepos++;
                last if $pos >= $data_pos;
            }
            seek DATA, $data_pos, 0;

            \%toc;
        };
        if ($toc->{$_[1]}) {
            seek DATA, $toc->{$_[1]}[0], 0;
            read DATA, my($content), $toc->{$_[1]}[1];
            my ($order, $lineoffset) = split(';', $toc->{$_[1]}[2]);
            $content =~ s/^#//gm;
            $content = "# line ".($data_linepos + $order+1 + $lineoffset)." \"".__FILE__."\"\n" . $content;
            open my $fh, '<', \$content
                or die "DataPacker error loading $_[1]: $!";
            return $fh;
        }
        return;
    };
}
# END DATAPACK CODE

package main;
use 5.010001;
use strict;
#use warnings;

### declare global variables

my $_pci_r = {naked_res=>0};
my %_pci_args;

### declare subroutines

sub _pci_err {
    my $res = shift;
    print STDERR "ERROR $res->[0]: $res->[1]\n";
    exit $res->[0]-300;
}

sub _pci_json {
    state $json = do {
        if    (eval { require JSON::XS; 1 }) { JSON::XS->new->canonical(1)->allow_nonref }
        elsif (eval { require JSON::PP; 1 }) { JSON::PP->new->canonical(1)->allow_nonref }
        else { require JSON::Tiny::Subclassable; JSON::Tiny::Subclassable->new }
    };
    $json;
}

### parse cmdline options

{
require Getopt::Long::EvenLess;
my %mentioned_args;
my $go_spec = {
    'action=s' => sub {
        $_pci_args{'action'} = $_[1];
    },
    'argv-json=s' => sub {
        $_pci_args{'argv'} = _pci_json()->decode($_[1]);
    },
    'argv=s@' => sub {
        if ($mentioned_args{'argv'}++) { push @{ $_pci_args{'argv'} }, $_[1] } else { $_pci_args{'argv'} = [$_[1]] }
    },
    'format=s' => sub {
        $_pci_r->{format} = $_[1];
    },
    'help|h|?' => sub {
        print "td - Manipulate table data\n\nUsage:\n  td --help (or -h, -?)\n  td --version (or -v)\n  td [options] <action> [argv] ...\n\n*td* receives table data from standard input and performs an action on it. It\nhas functionality similar to some Unix commands like *head*, *tail*, *wc*,\n*cut*, *sort* except that it operates on table rows/columns instead of\nlines/characters. This is convenient to use with CLI scripts that output table\ndata.\n\nA _table data_ is JSON-encoded data in the form of either: `hos` (hash of\nscalars, which is viewed as a two-column table where the columns are `key` and\n`value`), `aos` (array of scalars, which is viewed as a 1-column array where the\ncolumn is `elem`), `aoaos` (array of arrays of scalars), or `aohos` (array of\nhashes of scalars).\n\nThe input can also be an _enveloped_ table data, where the envelope is an array:\n`[status, message, content, meta]` and `content` is the actual table data. This\nkind of data is produced by `Perinci::CmdLine`-based scripts and can contain\nmore detailed table specification in the `meta` hash, which `td` can parse.\n\nFirst you might want to use the `info` action to see if the input is a table\ndata:\n\n    % osnames -l --json | td info\n\nIf input is not valid JSON, a JSON parse error will be displayed. If input is\nvalid JSON but not a table data, another error will be displayed. Otherwise,\ninformation about the table will be displayed (form, number of columns, column\nnames, number of rows, and so on).\n\nNext, you can use these actions:\n\n    # count number of rows (equivalent to \"wc -l\" Unix command)\n    % osnames -l --json | td rowcount\n\n    # append a row containing rowcount\n    % osnames -l --json | td rowcount-row\n\n    # append a row containing column names\n    % lcpan related-mods Perinci::CmdLine | td colnames-row\n\n    # count number of columns\n    % osnames -l --json | td colcount\n\n    # select some columns\n    % osnames -l --json | td select value description\n\n    # only show first 5 rows\n    % osnames -l --json | td head -n5\n\n    # only show last 5 rows\n    % osnames -l --json | td tail -n5\n\n    # sort by column(s) (add \"-\" prefix to for descending order)\n    % osnames -l --json | td sort value tags\n    % osnames -l --json | td sort -- -value\n\n    # return sum of all numeric columns\n    % list-files -l --json | td sum\n\n    # append a sum row\n    % list-files -l --json | td sum-row\n\n    # return average of all numeric columns\n    % list-files -l --json | td avg\n\n    # append an average row\n    % list-files -l --json | td avg-row\n\n    # add a row number column (1, 2, 3, ...)\n    % list-files -l --json | td rownum-col\n\nMain options:\n  --action=s*    Action to perform on input table (=arg[0])\n  --argv=s\@      Arguments (=arg[1-]) [[]]\n  --lines=i, -n  \n\nOutput options:\n  --format=s  Choose output format, e.g. json, text\n  --json      Set output format to json\n\nOther options:\n  --help, -h, -?                 Display help message and exit\n  --naked-res                    When outputing as JSON, strip result envelope\n  --no-naked-res, --nonaked-res  When outputing as JSON, don't strip result envelope\n  --version, -v                  Display program's version and exit\n"; exit 0;
    },
    'json' => sub {
        $_pci_r->{format} = (-t STDOUT) ? "json-pretty" : "json";
    },
    'lines=i' => sub {
        $_pci_args{'lines'} = $_[1];
    },
    'n=i' => sub {
        $_pci_args{'lines'} = $_[1];
    },
    'naked-res' => sub {
        $_pci_r->{naked_res} = 1;
    },
    'no-naked-res|nonaked-res' => sub {
        $_pci_r->{naked_res} = 0;
    },
    'version|v' => sub {
        no warnings 'once';
        require App::td;
        print "td version ", "0.08", ($App::td::DATE ? " ($App::td::DATE)" : ''), "\n";
        print "  Generated by Perinci::CmdLine::Inline version 0.40 (2016-12-28)\n";
        exit 0;
    },
};
my $res = Getopt::Long::EvenLess::GetOptions(%$go_spec);
_pci_err([500, "GetOptions failed"]) unless $res;
require Local::_pci_check_args; $res = _pci_check_args(\%_pci_args);
_pci_err($res) if $res->[0] != 200;
$_pci_r->{args} = \%_pci_args;
}

### call function

{
require App::td;
eval { $_pci_r->{res} = App::td::td(%_pci_args) };
if ($@) { $_pci_r->{res} = [500, "Function died: $@"] }
}

### format & display result

{
my $fres;
my $save_res; if (exists $_pci_r->{res}[3]{"cmdline.result"}) { $save_res = $_pci_r->{res}[2]; $_pci_r->{res}[2] = $_pci_r->{res}[3]{"cmdline.result"} }
my $is_success = $_pci_r->{res}[0] =~ /\A2/ || $_pci_r->{res}[0] == 304;
my $is_stream = $_pci_r->{res}[3]{stream} // undef // 0;
if ($is_success && (0 || $_pci_r->{res}[3]{"cmdline.skip_format"})) { $fres = $_pci_r->{res}[2] }
elsif ($is_success && $is_stream) {}
else { require Local::_pci_clean_json; require Perinci::Result::Format::Lite; $is_stream=0; _pci_clean_json($_pci_r->{res}); $fres = Perinci::Result::Format::Lite::format($_pci_r->{res}, ($_pci_r->{format} // $_pci_r->{res}[3]{"cmdline.default_format"} // "text"), $_pci_r->{naked_res}, 0) }

my $use_utf8 = $_pci_r->{res}[3]{"x.hint.result_binary"} ? 0 : 0;
if ($use_utf8) { binmode STDOUT, ":utf8" }
if ($is_stream) {
    my $code = $_pci_r->{res}[2]; if (ref($code) ne "CODE") { die "Result is a stream but no coderef provided" } if (0) { while(defined(my $l=$code->())) { print $l; print "\n" unless "" eq "buf"; } } else { while (defined(my $rec=$code->())) { print _pci_json()->encode($rec),"\n" } }
} else {
    print $fres;
}
if (defined $save_res) { $_pci_r->{res}[2] = $save_res }
}

### exit

{
my $status = $_pci_r->{res}[0];
my $exit_code = $_pci_r->{res}[3]{"cmdline.exit_code"} // ($status =~ /200|304/ ? 0 : ($status-300));
exit($exit_code);
}

=pod

=encoding UTF-8

=head1 NAME

td - Manipulate table data

=head1 VERSION

This document describes version 0.08 of main (from Perl distribution App-td), released on 2016-01-01.

=head1 SYNOPSIS

Usage:

 % td [options] <action> [argv] ...

=head1 DESCRIPTION

I<td> receives table data from standard input and performs an action on it. It
has functionality similar to some Unix commands like I<head>, I<tail>, I<wc>,
I<cut>, I<sort> except that it operates on table rows/columns instead of
lines/characters. This is convenient to use with CLI scripts that output table
data.

A I<table data> is JSON-encoded data in the form of either: C<hos> (hash of
scalars, which is viewed as a two-column table where the columns are C<key> and
C<value>), C<aos> (array of scalars, which is viewed as a 1-column array where the
column is C<elem>), C<aoaos> (array of arrays of scalars), or C<aohos> (array of
hashes of scalars).

The input can also be an I<enveloped> table data, where the envelope is an array:
C<[status, message, content, meta]> and C<content> is the actual table data. This
kind of data is produced by C<Perinci::CmdLine>-based scripts and can contain
more detailed table specification in the C<meta> hash, which C<td> can parse.

First you might want to use the C<info> action to see if the input is a table
data:

 % osnames -l --json | td info

If input is not valid JSON, a JSON parse error will be displayed. If input is
valid JSON but not a table data, another error will be displayed. Otherwise,
information about the table will be displayed (form, number of columns, column
names, number of rows, and so on).

Next, you can use these actions:

 # count number of rows (equivalent to "wc -l" Unix command)
 % osnames -l --json | td rowcount
 
 # append a row containing rowcount
 % osnames -l --json | td rowcount-row
 
 # append a row containing column names
 % lcpan related-mods Perinci::CmdLine | td colnames-row
 
 # count number of columns
 % osnames -l --json | td colcount
 
 # select some columns
 % osnames -l --json | td select value description
 
 # only show first 5 rows
 % osnames -l --json | td head -n5
 
 # only show last 5 rows
 % osnames -l --json | td tail -n5
 
 # sort by column(s) (add "-" prefix to for descending order)
 % osnames -l --json | td sort value tags
 % osnames -l --json | td sort -- -value
 
 # return sum of all numeric columns
 % list-files -l --json | td sum
 
 # append a sum row
 % list-files -l --json | td sum-row
 
 # return average of all numeric columns
 % list-files -l --json | td avg
 
 # append an average row
 % list-files -l --json | td avg-row
 
 # add a row number column (1, 2, 3, ...)
 % list-files -l --json | td rownum-col

=head1 OPTIONS

C<*> marks required options.

=head2 Main options

=over

=item B<--action>=I<s>*

Action to perform on input table.

Valid values:

 ["avg","avg-row","colcount","colcount-row","colnames-row","head","info","rowcount","rowcount-row","rownum-col","select","sort","sum","sum-row","tail","wc","wc-row"]

=item B<--argv-json>=I<s>

Arguments (JSON-encoded).

See C<--argv>.

=item B<--argv>=I<s@>

Arguments.

Default value:

 []

Can be specified multiple times.

=item B<--lines>=I<i>, B<-n>

=back

=head2 Output options

=over

=item B<--format>=I<s>

Choose output format, e.g. json, text.

Default value:

 undef

=item B<--json>

Set output format to json.

=item B<--naked-res>

When outputing as JSON, strip result envelope.

Default value:

 0

By default, when outputing as JSON, the full enveloped result is returned, e.g.:

    [200,"OK",[1,2,3],{"func.extra"=>4}]

The reason is so you can get the status (1st element), status message (2nd
element) as well as result metadata/extra result (4th element) instead of just
the result (3rd element). However, sometimes you want just the result, e.g. when
you want to pipe the result for more post-processing. In this case you can use
`--naked-res` so you just get:

    [1,2,3]


=back

=head2 Other options

=over

=item B<--help>, B<-h>, B<-?>

Display help message and exit.

=item B<--version>, B<-v>

Display program's version and exit.

=back

=head1 COMPLETION

The distribution comes with a shell completer script (L<_td>) for
this script.

=head2 bash

To activate bash completion for this script, put:

 complete -C _td td

in your bash startup (e.g. C<~/.bashrc>). Your next shell session will then
recognize tab completion for the command. Or, you can also directly execute the
line above in your shell to activate immediately.

It is recommended, however, that you install L<shcompgen> which allows you to
activate completion scripts for several kinds of scripts on multiple shells.
Some CPAN distributions (those that are built with
L<Dist::Zilla::Plugin::GenShellCompletion>) will even automatically enable shell
completion for their included scripts (using C<shcompgen>) at installation time,
so you can immadiately have tab completion.

=head2 tcsh

To activate tcsh completion for this script, put:

 complete _td 'p/*/`td`/'

in your tcsh startup (e.g. C<~/.tcshrc>). Your next shell session will then
recognize tab completion for the command. Or, you can also directly execute the
line above in your shell to activate immediately.

It is also recommended to install C<shcompgen> (see above).

=head2 other shells

For fish and zsh, install C<shcompgen> as described above.

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-td>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-td>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-td>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut

__DATA__
Data::Section::Seekable v1
Data/Check/Structure.pm,32,3555,0;0
Getopt/Long/EvenLess.pm,3619,4425,1;165
JSON/Tiny/Subclassable.pm,8078,8834,2;326
Local/_pci_check_args.pm,16945,3893,3;713
Local/_pci_clean_json.pm,20871,3412,4;787
Perinci/Result/Format/Lite.pm,24321,28172,5;841
Scalar/Util/Numeric/PP.pm,52527,1353,6;1670
Text/Table/Tiny.pm,53907,2733,7;1740

### Data/Check/Structure.pm ###
#package Data::Check::Structure;
#
#our $DATE = '2014-07-14'; 
#our $VERSION = '0.03'; 
#
#use 5.010001;
#use strict;
#use warnings;
#
#require Exporter;
#our @ISA = qw(Exporter);
#our @EXPORT_OK = qw(
#                       is_aoa
#                       is_aoaos
#                       is_aoh
#                       is_aohos
#                       is_aos
#                       is_hoa
#                       is_hoaos
#                       is_hoh
#                       is_hohos
#                       is_hos
#               );
#
#sub is_aos {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'ARRAY';
#    for my $i (0..@$data-1) {
#        last if defined($max) && $i >= $max;
#        return 0 if ref($data->[$i]);
#    }
#    1;
#}
#
#sub is_aoa {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'ARRAY';
#    for my $i (0..@$data-1) {
#        last if defined($max) && $i >= $max;
#        return 0 unless ref($data->[$i]) eq 'ARRAY';
#    }
#    1;
#}
#
#sub is_aoaos {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'ARRAY';
#    my $aos_opts = {max=>$max};
#    for my $i (0..@$data-1) {
#        last if defined($max) && $i >= $max;
#        return 0 unless is_aos($data->[$i], $aos_opts);
#    }
#    1;
#}
#
#sub is_aoh {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'ARRAY';
#    for my $i (0..@$data-1) {
#        last if defined($max) && $i >= $max;
#        return 0 unless ref($data->[$i]) eq 'HASH';
#    }
#    1;
#}
#
#sub is_aohos {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'ARRAY';
#    my $hos_opts = {max=>$max};
#    for my $i (0..@$data-1) {
#        last if defined($max) && $i >= $max;
#        return 0 unless is_hos($data->[$i], $hos_opts);
#    }
#    1;
#}
#
#sub is_hos {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'HASH';
#    my $i = 0;
#    for my $k (keys %$data) {
#        last if defined($max) && ++$i >= $max;
#        return 0 if ref($data->{$k});
#    }
#    1;
#}
#
#sub is_hoa {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'HASH';
#    my $i = 0;
#    for my $k (keys %$data) {
#        last if defined($max) && ++$i >= $max;
#        return 0 unless ref($data->{$k}) eq 'ARRAY';
#    }
#    1;
#}
#
#sub is_hoaos {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'HASH';
#    my $i = 0;
#    for my $k (keys %$data) {
#        last if defined($max) && ++$i >= $max;
#        return 0 unless is_aos($data->{$k});
#    }
#    1;
#}
#
#sub is_hoh {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'HASH';
#    my $i = 0;
#    for my $k (keys %$data) {
#        last if defined($max) && ++$i >= $max;
#        return 0 unless ref($data->{$k}) eq 'HASH';
#    }
#    1;
#}
#
#sub is_hohos {
#    my ($data, $opts) = @_;
#    $opts //= {};
#    my $max = $opts->{max};
#
#    return 0 unless ref($data) eq 'HASH';
#    my $i = 0;
#    for my $k (keys %$data) {
#        last if defined($max) && ++$i >= $max;
#        return 0 unless is_hos($data->{$k});
#    }
#    1;
#}
#
#1;
#
#__END__
#
### Getopt/Long/EvenLess.pm ###
#package Getopt::Long::EvenLess;
#
#our $DATE = '2016-12-03'; 
#our $VERSION = '0.07'; 
#
#
#our @EXPORT   = qw(GetOptions);
#our @EXPORT_OK = qw(GetOptionsFromArray);
#
#sub import {
#    my $pkg = shift;
#    my $caller = caller;
#    my @imp = @_ ? @_ : @EXPORT;
#    for my $imp (@imp) {
#        if (grep {$_ eq $imp} (@EXPORT, @EXPORT_OK)) {
#            *{"$caller\::$imp"} = \&{$imp};
#        } else {
#            die "$imp is not exported by ".__PACKAGE__;
#        }
#    }
#}
#
#sub GetOptionsFromArray {
#    my ($argv, %spec) = @_;
#
#    my $success = 1;
#
#    my %spec_by_opt_name;
#    for (keys %spec) {
#        my $orig = $_;
#        s/=[fios]\@?\z//;
#        s/\|.+//;
#        $spec_by_opt_name{$_} = $orig;
#    }
#
#    my $code_find_opt = sub {
#        my ($wanted, $short_mode) = @_;
#        my @candidates;
#      OPT_SPEC:
#        for my $spec (keys %spec) {
#            $spec =~ s/=[fios]\@?\z//;
#            my @opts = split /\|/, $spec;
#            for my $o (@opts) {
#                next if $short_mode && length($o) > 1;
#                if ($o eq $wanted) {
#                    @candidates = ($opts[0]);
#                    last OPT_SPEC;
#                } elsif (index($o, $wanted) == 0) {
#                    push @candidates, $opts[0];
#                    next OPT_SPEC;
#                }
#            }
#        }
#        if (!@candidates) {
#            warn "Unknown option: $wanted\n";
#            $success = 0;
#            return undef; 
#        } elsif (@candidates > 1) {
#            warn "Option $wanted is ambiguous (" .
#                join(", ", @candidates) . ")\n";
#            $success = 0;
#            return ''; 
#        }
#        return $candidates[0];
#    };
#
#    my $code_set_val = sub {
#        my $name = shift;
#
#        my $spec_key = $spec_by_opt_name{$name};
#        my $handler  = $spec{$spec_key};
#
#        $handler->({name=>$name}, @_ ? $_[0] : 1);
#    };
#
#    my $i = -1;
#    my @remaining;
#  ELEM:
#    while (++$i < @$argv) {
#        if ($argv->[$i] eq '--') {
#
#            push @remaining, @{$argv}[$i+1 .. @$argv-1];
#            last ELEM;
#
#        } elsif ($argv->[$i] =~ /\A--(.+?)(?:=(.*))?\z/) {
#
#            my ($used_name, $val_in_opt) = ($1, $2);
#            my $opt = $code_find_opt->($used_name);
#            if (!defined($opt)) {
#                push @remaining, $argv->[$i];
#                next ELEM;
#            } elsif (!length($opt)) {
#                next ELEM; 
#            }
#
#            my $spec = $spec_by_opt_name{$opt};
#            if ($spec =~ /=[fios]\@?\z/) {
#                if (defined $val_in_opt) {
#                    $code_set_val->($opt, $val_in_opt);
#                } else {
#                    if ($i+1 >= @$argv) {
#                        warn "Option $used_name requires an argument\n";
#                        $success = 0;
#                        last ELEM;
#                    }
#                    $i++;
#                    $code_set_val->($opt, $argv->[$i]);
#                }
#            } else {
#                $code_set_val->($opt);
#            }
#
#        } elsif ($argv->[$i] =~ /\A-(.*)/) {
#
#            my $str = $1;
#          SHORT_OPT:
#            while ($str =~ s/(.)//) {
#                my $used_name = $1;
#                my $opt = $code_find_opt->($1, 'short');
#                next SHORT_OPT unless defined($opt) && length($opt);
#
#                my $spec = $spec_by_opt_name{$opt};
#                if ($spec =~ /=[fios]\@?\z/) {
#                    if (length $str) {
#                        $code_set_val->($opt, $str);
#                        next ELEM;
#                    } else {
#                        if ($i+1 >= @$argv) {
#                            warn "Option $used_name requires an argument\n";
#                            $success = 0;
#                            last ELEM;
#                        }
#                        $i++;
#                        $code_set_val->($opt, $argv->[$i]);
#                    }
#                } else {
#                    $code_set_val->($opt);
#                }
#            }
#
#        } else { 
#
#            push @remaining, $argv->[$i];
#            next;
#
#        }
#    }
#
#  RETURN:
#    splice @$argv, 0, ~~@$argv, @remaining; 
#    return $success;
#}
#
#sub GetOptions {
#    GetOptionsFromArray(\@ARGV, @_);
#}
#
#1;
#
#__END__
#
### JSON/Tiny/Subclassable.pm ###
#use 5.008;
#use strict;
#use warnings;
#
#{
#	package JSON::Tiny::Subclassable;
#
#	our $AUTHORITY = 'cpan:TOBYINK';
#	our $VERSION   = '0.005';
#	our @ISA       = qw(JSON::Tiny);
#	
#	use B;
#	use Encode ();
#	use Scalar::Util ();
#	
#	BEGIN {
#		eval { require Sub::Name; Sub::Name->import('subname'); 1 }
#			or eval q{ sub subname { $_[1] } };
#	};
#	
#	sub new {
#		my $class = shift;
#		bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, $class;
#	}
#	
#	sub error {
#		$_[0]->{error} = $_[1] if @_ > 1;
#		return $_[0]->{error};
#	}
#	
#	sub pretty {
#		$_[0]->{pretty} = $_[1] if @_ > 1;
#		return $_[0]->{pretty};
#	}
#	
#	sub import {
#		my $class  = shift;
#		my $caller = caller;
#		my $opts   = {};
#		while (@_) {
#			my $arg = shift;
#			$opts->{$arg} = ref $_[0] ? shift @_ : undef;
#		}
#		if (exists $opts->{'j'}) {
#			my $func = ((ref $opts->{j} eq 'HASH') && $opts->{j}{-as}) || 'j';
#			no strict 'refs';
#			*{"$caller\::$func"} = subname "$class\::j" => sub {
#				my $d = shift;
#				return $class->new->encode($d) if ref $d eq 'ARRAY' || ref $d eq 'HASH';
#				return $class->new->decode($d);
#			};
#			delete $opts->{'j'};
#		}
#	}
#	
#	__PACKAGE__->import('j');
#	
#	my $FALSE = bless \(my $false = 0), 'JSON::Tiny::_Bool';
#	my $TRUE  = bless \(my $true  = 1), 'JSON::Tiny::_Bool';
#	
#	my %ESCAPE = (
#		'"'     => '"',
#		'\\'    => '\\',
#		'/'     => '/',
#		'b'     => "\x07",
#		'f'     => "\x0C",
#		'n'     => "\x0A",
#		'r'     => "\x0D",
#		't'     => "\x09",
#		'u2028' => "\x{2028}",
#		'u2029' => "\x{2029}"
#	);
#	my %REVERSE = map { $ESCAPE{$_} => "\\$_" } keys %ESCAPE;
#	for (0x00 .. 0x1F, 0x7F) {
#		my $k = pack 'C', $_;
#		$REVERSE{$k} = sprintf '\u%.4X', $_ unless defined $REVERSE{$k};
#	}
#	
#	my $UTF_PATTERNS = {
#		'UTF-32BE' => qr/^\0\0\0[^\0]/,
#		'UTF-16BE' => qr/^\0[^\0]\0[^\0]/,
#		'UTF-32LE' => qr/^[^\0]\0\0\0/,
#		'UTF-16LE' => qr/^[^\0]\0[^\0]\0/
#	};
#	
#	my $WHITESPACE_RE = qr/[\x20\x09\x0a\x0d]*/;
#	
#	sub DOES {
#		my ($proto, $role) = @_;
#		return 1 if $role eq 'Mojo::JSON';
#		return $proto->SUPER::DOES($role);
#	}
#	
#	sub decode {
#		my ($self, $bytes) = @_;
#		
#		$self->error(undef);
#		
#		$self->error('Missing or empty input') and return undef unless $bytes; 
#		
#		$bytes =~ s/^(?:\357\273\277|\377\376\0\0|\0\0\376\377|\376\377|\377\376)//g;
#		
#		$self->error('Wide character in input') and return undef 
#			unless utf8::downgrade($bytes, 1);
#		
#		my $encoding = 'UTF-8';
#		$bytes =~ $UTF_PATTERNS->{$_} and $encoding = $_ for keys %$UTF_PATTERNS;
#		
#		my $d_res = eval { $bytes = Encode::decode($encoding, $bytes, 1); 1 };
#		$bytes = undef unless $d_res;
#		
#		my $res = eval {
#			local $_ = $bytes;
#			
#			m/\G$WHITESPACE_RE/gc;
#			
#			my $ref;
#			if (m/\G\[/gc) { $ref = $self->_decode_array() }
#			
#			elsif (m/\G\{/gc) { $ref = $self->_decode_object() }
#			
#			else { $self->_exception('Expected array or object') }
#			
#			unless (m/\G$WHITESPACE_RE\z/gc) {
#				my $got = ref $ref eq 'ARRAY' ? 'array' : 'object';
#				$self->_exception("Unexpected data after $got");
#			}
#			
#			$ref;
#		};
#		
#		if (!$res && (my $e = $@)) {
#			chomp $e;
#			$self->error($e);
#		}
#		
#		return $res;
#	}
#	
#	sub encode {
#		my ($self, $ref) = @_;
#		
#		my $eof = '';
#		if ($self->pretty) {
#			$self->{_indent} = '';
#			$eof .= "\n";
#		}
#		
#		return Encode::encode 'UTF-8', $self->_encode_values($ref).$eof;
#	}
#	
#	sub false {$FALSE}
#	sub true  {$TRUE}
#	
#	sub _new_hash  { +{} }
#	sub _new_array { +[] }
#	
#	sub _decode_array {
#		my $self  = shift;
#		my $array = $self->_new_array;
#		until (m/\G$WHITESPACE_RE\]/gc) {
#			
#			push @$array, $self->_decode_value();
#			
#			redo if m/\G$WHITESPACE_RE,/gc;
#			
#			last if m/\G$WHITESPACE_RE\]/gc;
#			
#			$self->_exception('Expected comma or right square bracket while parsing array');
#		}
#		
#		return $array;
#	}
#	
#	sub _decode_object {
#		my $self = shift;
#		my $hash = $self->_new_hash;
#		until (m/\G$WHITESPACE_RE\}/gc) {
#			
#			m/\G$WHITESPACE_RE"/gc
#				or $self->_exception('Expected string while parsing object');
#			
#			my $key = $self->_decode_string();
#			
#			m/\G$WHITESPACE_RE:/gc
#				or $self->_exception('Expected colon while parsing object');
#			
#			$hash->{$key} = $self->_decode_value();
#			
#			redo if m/\G$WHITESPACE_RE,/gc;
#			
#			last if m/\G$WHITESPACE_RE\}/gc;
#			
#			$self->_exception('Expected comma or right curly bracket while parsing object');
#		}
#		
#		return $hash;
#	}
#	
#	sub _decode_string {
#		my $self = shift;
#		my $pos = pos;
#		
#		m#\G(((?:[^\x00-\x1F\\"]|\\(?:["\\/bfnrt]|u[[:xdigit:]]{4})){0,32766})*)#gc;
#		my $str = $1;
#		
#		unless (m/\G"/gc) {
#			$self->_exception('Unexpected character or invalid escape while parsing string')
#				if m/\G[\x00-\x1F\\]/;
#			$self->_exception('Unterminated string');
#		}
#		
#		if (index($str, '\\u') < 0) {
#			$str =~ s!\\(["\\/bfnrt])!$ESCAPE{$1}!gs;
#			return $str;
#		}
#		
#		my $buffer = '';
#		while ($str =~ m/\G([^\\]*)\\(?:([^u])|u(.{4}))/gc) {
#			$buffer .= $1;
#			
#			if ($2) { $buffer .= $ESCAPE{$2} }
#			
#			else {
#				my $ord = hex $3;
#				
#				if (($ord & 0xF800) == 0xD800) {
#					
#					($ord & 0xFC00) == 0xD800
#						or pos($_) = $pos + pos($str), $self->_exception('Missing high-surrogate');
#					
#					$str =~ m/\G\\u([Dd][C-Fc-f]..)/gc
#						or pos($_) = $pos + pos($str), $self->_exception('Missing low-surrogate');
#					
#					$ord = 0x10000 + ($ord - 0xD800) * 0x400 + (hex($1) - 0xDC00);
#				}
#				
#				$buffer .= pack 'U', $ord;
#			}
#		}
#		
#		return $buffer . substr $str, pos($str), length($str);
#	}
#	
#	sub _decode_value {
#		my $self = shift;
#		
#		m/\G$WHITESPACE_RE/gc;
#		
#		return $self->_decode_string() if m/\G"/gc;
#		
#		return $self->_decode_array() if m/\G\[/gc;
#		
#		return $self->_decode_object() if m/\G\{/gc;
#		
#		return 0 + $1
#			if m/\G([-]?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?)/gc;
#		
#		return $self->true if m/\Gtrue/gc;
#		
#		return $self->false if m/\Gfalse/gc;
#		
#		return undef if m/\Gnull/gc;  
#		
#		$self->_exception('Expected string, array, object, number, boolean or null');
#	}
#	
#	sub _encode_array {
#		my $self = shift;
#		
#		return "[]" unless @{$_[0]};
#		
#		return '[' . join(',', map { $self->_encode_values($_) } @{shift()}) . ']'
#			unless exists $self->{_indent};
#		
#		my $indent = $self->{_indent};
#		return "\[\n$indent\t"
#			. join(",\n$indent\t", map {
#				local $self->{_indent} = "$indent\t"; $self->_encode_values($_)
#			} @{shift()})
#			. "\n$indent\]";
#	}
#	
#	sub _encode_object {
#		my $self = shift;
#		my $object = shift;
#		
#		my $indent;
#		if (exists $self->{_indent}) {
#			$indent = $self->{_indent};
#			$self->{_indent} .= "\t";
#		}
#		
#		my @pairs;
#		my $space = defined $indent ? q( ) : q();
#		while (my ($k, $v) = each %$object) {
#			push @pairs, sprintf(
#				'%s:%s%s',
#				$self->_encode_string($k),
#				$space,
#				$self->_encode_values($v),
#			);
#		}
#		
#		if (defined $indent)
#		{
#			$self->{_indent} =~ s/^.//;
#			return "{}" unless @pairs;
#			return "\{\n$indent\t" . join(",\n$indent\t", @pairs) . "\n$indent\}";
#		}
#		else
#		{
#			return '{' . join(',', @pairs) . '}';
#		}
#	}
#	
#	sub _encode_string {
#		my $self = shift;
#		my $string = shift;
#		
#		$string =~ s!([\x00-\x1F\x7F\x{2028}\x{2029}\\"/\b\f\n\r\t])!$REVERSE{$1}!gs;
#		
#		return "\"$string\"";
#	}
#	
#	sub _encode_values {
#		my $self = shift;
#		my $value = shift;
#		
#		if (my $ref = ref $value) {
#			
#			return $self->_encode_array($value) if $ref eq 'ARRAY';
#			
#			return $self->_encode_object($value) if $ref eq 'HASH';
#			
#			return $$value ? 'true' : 'false' if $ref eq 'SCALAR';
#			return $value  ? 'true' : 'false' if $ref eq 'JSON::Tiny::_Bool';
#			
#			if (Scalar::Util::blessed $value && (my $sub = $value->can('TO_JSON'))) {
#				return $self->_encode_values($value->$sub);
#			}
#		}
#		
#		return 'null' unless defined $value;
#		
#		return 0 + $value
#			if B::svref_2object(\$value)->FLAGS & (B::SVp_IOK | B::SVp_NOK);
#		
#		return $self->_encode_string($value);
#	}
#	
#	sub _exception {
#		my $self = shift;
#		
#		m/\G$WHITESPACE_RE/gc;
#		
#		my $context = 'Malformed JSON: ' . shift;
#		if (m/\G\z/gc) { $context .= ' before end of data' }
#		else {
#			my @lines = split /\n/, substr($_, 0, pos);
#			$context .= ' at line ' . @lines . ', offset ' . length(pop @lines || '');
#		}
#		
#		die "$context\n";
#	}
#}
#
#{
#	package JSON::Tiny::_Bool;
#	no warnings;
#	use overload
#		'0+' => sub { ${$_[0]} },
#		'""' => sub { ${$_[0]} },
#		fallback => 1,
#	;
#	sub DOES {
#		my ($proto, $role) = @_;
#		return 1 if $role eq 'Mojo::JSON::_Bool';
#		return 1 if $role =~ /^JSON::(?:PP::|XS::)?Boolean$/;
#		return $proto->SUPER::DOES($role);
#	}
#}
#
#1;
#
#__END__
#
### Local/_pci_check_args.pm ###
#sub _pci_check_args {
#    my $args = shift;
#  FILL_FROM_POS: {
#        1;
#        if (@ARGV > 1) { if (exists $args->{"argv"}) { return [400, "You specified --argv but also argument #1"]; } else { $args->{"argv"} = [splice(@ARGV, 1)]; } }
#        if (@ARGV > 0) { if (exists $args->{"action"}) { return [400, "You specified --action but also argument #0"]; } else { $args->{"action"} = delete($ARGV[0]); } }
#    }
#    my @check_argv = @ARGV;
#
#    no warnings ('void');
#    use experimental ("smartmatch");
#    require List::Util;
#    require Scalar::Util::Numeric::PP;
#    my $_sahv_dpath;
#    my $_sahv_err;
#    if (exists $args->{"action"}) {
#        $_sahv_dpath = [];
#        ((defined($args->{"action"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#        
#        &&
#        
#        ((!ref($args->{"action"})) ? 1 : (($_sahv_err //= "Not of type text"),0))
#        
#        &&
#        
#        (
#        (($args->{"action"} ~~ ["avg","avg-row","colcount","colcount-row","colnames-row","head","info","rowcount","rowcount-row","rownum-col","select","sort","sum","sum-row","tail","wc","wc-row"]) ? 1 : (($_sahv_err //= "Must be one of [\"avg\",\"avg-row\",\"colcount\",\"colcount-row\",\"colnames-row\",\"head\",\"info\",\"rowcount\",\"rowcount-row\",\"rownum-col\",\"select\",\"sort\",\"sum\",\"sum-row\",\"tail\",\"wc\",\"wc-row\"]"),0)))
#         ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#    } 
#    $args->{"argv"} //= [];
#    if (exists $args->{"argv"}) {
#        $_sahv_dpath = [];
#        ((defined($args->{"argv"})) ? 1 : (($_sahv_err //= (@$_sahv_dpath ? '@'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . "Required but not specified"),0))
#        
#        &&
#        
#        ((ref($args->{"argv"}) eq 'ARRAY') ? 1 : (($_sahv_err //= (@$_sahv_dpath ? '@'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . "Not of type array"),0))
#        
#        &&
#        
#        ([push(@{$_sahv_dpath}, undef), ~~(
#        ((!defined(List::Util::first(sub {!(
#                ($_sahv_dpath->[-1] = $_),
#                ((defined($args->{"argv"}->[$_])) ? 1 : (($_sahv_err //= (@$_sahv_dpath ? '@'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . "Required but not specified"),0))
#                
#                &&
#                
#                ((!ref($args->{"argv"}->[$_])) ? 1 : (($_sahv_err //= (@$_sahv_dpath ? '@'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . "Not of type text"),0))
#                )}, 0..@{$args->{"argv"}}-1))) ? 1 : (($_sahv_err //= (@$_sahv_dpath ? '@'.join("",map {"[$_]"} @$_sahv_dpath).": " : "") . "Not of type text"),0))), pop(@{$_sahv_dpath})]->[1])
#         ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#    } 
#    if (exists $args->{"lines"}) {
#        $_sahv_dpath = [];
#        ((defined($args->{"lines"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#        
#        &&
#        
#        ((Scalar::Util::Numeric::PP::isint($args->{"lines"})) ? 1 : (($_sahv_err //= "Not of type integer"),0))
#        
#        &&
#        
#        (
#        (($args->{"lines"} >= 0) ? 1 : (($_sahv_err //= "Must be at least 0"),0)))
#         ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#    } 
#
#    return [400, "Missing required argument: action"] unless exists $args->{"action"};
#    return [400, "Missing required value for argument: action"] if exists($args->{"action"}) && !defined($args->{"action"});
#    return [400, "Missing required value for argument: argv"] if exists($args->{"argv"}) && !defined($args->{"argv"});
#    return [400, "Missing required value for argument: lines"] if exists($args->{"lines"}) && !defined($args->{"lines"});
#    _pci_err([500, "Extraneous command-line argument(s): ".join(", ", @check_argv)]) if @check_argv;
#    [200];
#}
#1;
### Local/_pci_clean_json.pm ###
#require Scalar::Util; use feature 'state'; sub _pci_clean_json { state $cleanser = sub {
#require Scalar::Util;
#my $data = shift;
#state %refs;
#state $ctr_circ;
#state $process_array;
#state $process_hash;
#if (!$process_array) { $process_array = sub { my $a = shift; for my $e (@$a) { my $ref=ref($e);
#    if ($ref && $refs{ $e }++) { if (++$ctr_circ <= 1) { $e = Data::Clone::clone($e); redo } else { $e = 'CIRCULAR'; $ref = '' } }
#    elsif ($ref eq 'DateTime') { $e = $e->epoch; $ref = ref($e) }
#    elsif ($ref eq 'Math::BigInt') { $e = $e->bstr; $ref = ref($e) }
#    elsif ($ref eq 'Regexp') { $e = "$e"; $ref = "" }
#    elsif ($ref eq 'SCALAR') { $e = ${ $e }; $ref = ref($e) }
#    elsif ($ref eq 'Time::Moment') { $e = $e->epoch; $ref = ref($e) }
#    elsif ($ref eq 'version') { $e = "$e"; $ref = "" }
#    elsif (Scalar::Util::blessed($e)) { if (!$Data::Clean::_clone && 0) { $e = Acme::Damn::damn($e) } else { $e = Function::Fallback::CoreOrPP::_unbless_fallback($e) } $ref = ref($e) }
#    my $reftype=Scalar::Util::reftype($e)//"";
#    if ($reftype eq "ARRAY") { $process_array->($e) }
#    elsif ($reftype eq "HASH") { $process_hash->($e) }
#    elsif ($ref) { $e = $ref; $ref = "" }
#} } }
#if (!$process_hash) { $process_hash = sub { my $h = shift; for my $k (keys %$h) { my $ref=ref($h->{$k});
#    if ($ref && $refs{ $h->{$k} }++) { if (++$ctr_circ <= 1) { $h->{$k} = Data::Clone::clone($h->{$k}); redo } else { $h->{$k} = 'CIRCULAR'; $ref = '' } }
#    elsif ($ref eq 'DateTime') { $h->{$k} = $h->{$k}->epoch; $ref = ref($h->{$k}) }
#    elsif ($ref eq 'Math::BigInt') { $h->{$k} = $h->{$k}->bstr; $ref = ref($h->{$k}) }
#    elsif ($ref eq 'Regexp') { $h->{$k} = "$h->{$k}"; $ref = "" }
#    elsif ($ref eq 'SCALAR') { $h->{$k} = ${ $h->{$k} }; $ref = ref($h->{$k}) }
#    elsif ($ref eq 'Time::Moment') { $h->{$k} = $h->{$k}->epoch; $ref = ref($h->{$k}) }
#    elsif ($ref eq 'version') { $h->{$k} = "$h->{$k}"; $ref = "" }
#    elsif (Scalar::Util::blessed($h->{$k})) { if (!$Data::Clean::_clone && 0) { $h->{$k} = Acme::Damn::damn($h->{$k}) } else { $h->{$k} = Function::Fallback::CoreOrPP::_unbless_fallback($h->{$k}) } $ref = ref($h->{$k}) }
#    my $reftype=Scalar::Util::reftype($h->{$k})//"";
#    if ($reftype eq "ARRAY") { $process_array->($h->{$k}) }
#    elsif ($reftype eq "HASH") { $process_hash->($h->{$k}) }
#    elsif ($ref) { $h->{$k} = $ref; $ref = "" }
#} } }
#%refs = (); $ctr_circ=0;
#for ($data) { my $ref=ref($_);
#    if ($ref && $refs{ $_ }++) { if (++$ctr_circ <= 1) { $_ = Data::Clone::clone($_); redo } else { $_ = 'CIRCULAR'; $ref = '' } }
#    elsif ($ref eq 'DateTime') { $_ = $_->epoch; $ref = ref($_) }
#    elsif ($ref eq 'Math::BigInt') { $_ = $_->bstr; $ref = ref($_) }
#    elsif ($ref eq 'Regexp') { $_ = "$_"; $ref = "" }
#    elsif ($ref eq 'SCALAR') { $_ = ${ $_ }; $ref = ref($_) }
#    elsif ($ref eq 'Time::Moment') { $_ = $_->epoch; $ref = ref($_) }
#    elsif ($ref eq 'version') { $_ = "$_"; $ref = "" }
#    elsif (Scalar::Util::blessed($_)) { if (!$Data::Clean::_clone && 0) { $_ = Acme::Damn::damn($_) } else { $_ = Function::Fallback::CoreOrPP::_unbless_fallback($_) } $ref = ref($_) }
#    my $reftype=Scalar::Util::reftype($_)//"";
#    if ($reftype eq "ARRAY") { $process_array->($_) }
#    elsif ($reftype eq "HASH") { $process_hash->($_) }
#    elsif ($ref) { $_ = $ref; $ref = "" }
#}
#$data
#}
#;; $cleanser->(shift) }
#1;
### Perinci/Result/Format/Lite.pm ###
#package Perinci::Result::Format::Lite;
#
#our $DATE = '2016-12-29'; 
#our $VERSION = '0.22'; 
#
#use 5.010001;
#
#use List::Util qw(first max);
#
#use Exporter qw(import);
#our @EXPORT_OK = qw(format);
#
#sub firstidx (&@) {
#    my $f = shift;
#    foreach my $i ( 0 .. $#_ )
#        {
#            local *_ = \$_[$i];
#            return $i if $f->();
#        }
#    return -1;
#}
#
#sub _json {
#    state $json = do {
#        if    (eval { require Cpanel::JSON::XS; 1 })   { Cpanel::JSON::XS->new->canonical(1)->convert_blessed->allow_nonref }
#        elsif (eval { require JSON::Tiny::Subclassable; 1 }) { JSON::Tiny::Subclassable->new }
#        elsif (eval { require JSON::PP; 1 })   { JSON::PP->new->canonical(1)->convert_blessed->allow_nonref }
#        else { die "Can't find any JSON module" }
#    };
#    $json;
#};
#
#sub __cleanse {
#    state $cleanser = do {
#        eval { require Data::Clean::JSON; 1 };
#        if ($@) {
#            undef;
#        } else {
#            Data::Clean::JSON->get_cleanser;
#        }
#    };
#    if ($cleanser) {
#        $cleanser->clean_in_place($_[0]);
#    } else {
#        $_[0];
#    }
#}
#
#sub __gen_table {
#    my ($data, $header_row, $resmeta, $format) = @_;
#
#    $resmeta //= {};
#
#    my @columns;
#    if ($header_row) {
#        @columns = @{$data->[0]};
#    } else {
#        @columns = map {"col$_"} 0..@{$data->[0]}-1;
#    }
#
#    my $column_orders; 
#  SET_COLUMN_ORDERS: {
#
#        my $tcos;
#        if ($ENV{FORMAT_PRETTY_TABLE_COLUMN_ORDERS}) {
#            $tcos = _json->encode($ENV{FORMAT_PRETTY_TABLE_COLUMN_ORDERS});
#        } elsif (my $rfos = ($resmeta->{'cmdline.format_options'} //
#                                 $resmeta->{format_options})) {
#            my $rfo = $rfos->{'text-pretty'} // $rfos->{text} // $rfos->{any};
#            if ($rfo) {
#                $tcos = $rfo->{table_column_orders};
#            }
#        }
#        if ($tcos) {
#          COLS:
#            for my $cols (@$tcos) {
#                for my $col (@$cols) {
#                    next COLS unless first {$_ eq $col} @columns;
#                }
#                $column_orders = $cols;
#                last SET_COLUMN_ORDERS;
#            }
#        }
#
#        $column_orders = $resmeta->{'table.fields'};
#    }
#
#    if ($column_orders) {
#        my @map0 = sort {
#            my $idx_a = firstidx(sub {$_ eq $a->[1]},
#                                 @$column_orders) // 9999;
#            my $idx_b = firstidx(sub {$_ eq $b->[1]},
#                                 @$column_orders) // 9999;
#            $idx_a <=> $idx_b || $a->[1] cmp $b->[1];
#        } map {[$_, $columns[$_]]} 0..$#columns;
#        my @map;
#        for (0..$#map0) {
#            $map[$_] = $map0[$_][0];
#        }
#        my $newdata = [];
#        for my $row (@$data) {
#            my @newrow;
#            for (0..$#map) { $newrow[$_] = $row->[$map[$_]] }
#            push @$newdata, \@newrow;
#        }
#        $data = $newdata;
#        my @newcolumns;
#        for (@map) { push @newcolumns, $columns[$_] }
#        @columns = @newcolumns;
#    }
#
#    my @field_idxs; 
#    {
#        my $tff = $resmeta->{'table.fields'} or last;
#        for my $i (0..$#columns) {
#            $field_idxs[$i] = firstidx { $_ eq $columns[$i] } @$tff;
#        }
#    }
#
#    {
#        last unless $header_row && @$data;
#        my $tff = $resmeta->{'table.fields'} or last;
#        my $tfu = $resmeta->{'table.field_units'} or last;
#        for my $i (0..$#columns) {
#            my $field_idx = $field_idxs[$i];
#            next unless $field_idx >= 0;
#            next unless defined $tfu->[$field_idx];
#            $data->[0][$i] .= " ($tfu->[$field_idx])";
#        }
#    }
#
#    {
#        my $tff   = $resmeta->{'table.fields'} or last;
#        my $tffmt = $resmeta->{'table.field_formats'} or last;
#
#        for my $ffmt (@$tffmt) {
#            next unless $ffmt;
#            if ($ffmt eq 'iso8601') {
#            }
#        }
#
#        for my $i (0..$#{$data}) {
#            my $row = $data->[$i];
#            for my $j (0..$#columns) {
#                next unless defined $row->[$j];
#                my $field_idx = $field_idxs[$j];
#                next unless $field_idx >= 0;
#                my $ffmt = $tffmt->[$field_idx];
#                next unless $ffmt;
#                if ($ffmt eq 'iso8601_datetime' || $ffmt eq 'iso8601_date') {
#                    if ($row->[$j] =~ /\A[0-9]+\z/) {
#                        my @t = gmtime($row->[$j]);
#                        if ($ffmt eq 'iso8601_datetime') {
#                            $row->[$j] = sprintf(
#                                "%04d-%02d-%02dT%02d:%02d:%02dZ",
#                                $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);
#                        } else {
#                            $row->[$j] = sprintf(
#                                "%04d-%02d-%02d",
#                                $t[5]+1900, $t[4]+1, $t[3]);
#                        }
#                    }
#                } elsif ($ffmt eq 'boolstr') {
#                    $row->[$j] = $row->[$j] ? "yes" : "no";
#                } elsif ($ffmt eq 'sci2dec') {
#                    if ($row->[$j] =~ /\A(?:[+-]?)(?:\d+\.|\d*\.(\d+))[eE]([+-]?\d+)\z/) {
#                        my $n = length($1 || "") - $2; $n = 0 if $n < 0;
#                        $row->[$j] = sprintf("%.${n}f", $row->[$j]);
#                    }
#                }
#            }
#        }
#    }
#
#    if ($format eq 'text-pretty') {
#        {
#            no warnings 'uninitialized';
#            my $tfa = $resmeta->{'table.field_aligns'} or last;
#            last unless @$data;
#
#            for my $colidx (0..$#columns) {
#                my $field_idx = $field_idxs[$colidx];
#                next unless $field_idx >= 0;
#                my $align = $tfa->[$field_idx];
#                next unless $align;
#
#                my $maxw;
#                my ($maxw_bd, $maxw_d, $maxw_ad); 
#                if ($align eq 'number') {
#                    my (@w_bd, @w_d, @w_ad);
#                    for my $i (0..$#{$data}) {
#                        my $row = $data->[$i];
#                        if (@$row > $colidx) {
#                            my $cell = $row->[$colidx];
#                            if ($header_row && $i == 0) {
#                                my $w = length($cell);
#                                push @w_bd, 0;
#                                push @w_bd, 0;
#                                push @w_ad, 0;
#                            } elsif ($cell =~ /\A([+-]?\d+)(\.?)(\d*)\z/) {
#                                push @w_bd, length($1);
#                                push @w_d , length($2);
#                                push @w_ad, length($3);
#                            } elsif ($cell =~ /\A([+-]?\d+\.?\d*)([eE])([+-]?\d+)\z/) {
#                                push @w_bd, length($1);
#                                push @w_d , length($2);
#                                push @w_ad, length($3);
#                            } else {
#                                push @w_bd, length($cell);
#                                push @w_bd, 0;
#                                push @w_ad, 0;
#                            }
#                        } else {
#                            push @w_bd, 0;
#                            push @w_d , 0;
#                            push @w_ad, 0;
#                        }
#                    }
#                    $maxw_bd = max(@w_bd);
#                    $maxw_d  = max(@w_d);
#                    $maxw_ad = max(@w_ad);
#                    if ($header_row) {
#                        my $w = length($data->[0][$colidx]);
#                        if ($maxw_d == 0 && $maxw_ad == 0) {
#                            $maxw_bd = $w;
#                        }
#                    }
#                }
#
#                $maxw = max(map {
#                    @$_ > $colidx ? length($_->[$colidx]) : 0
#                } @$data);
#
#                for my $i (0..$#{$data}) {
#                    my $row = $data->[$i];
#                    for my $i (0..$#{$data}) {
#                        my $row = $data->[$i];
#                        next unless @$row > $colidx;
#                        my $cell = $row->[$colidx];
#                        next unless defined($cell);
#                        if ($align eq 'number') {
#                            my ($bd, $d, $ad);
#                            if ($header_row && $i == 0) {
#                            } elsif (($bd, $d, $ad) = $cell =~ /\A([+-]?\d+)(\.?)(\d*)\z/) {
#                                $cell = join(
#                                    '',
#                                    (' ' x ($maxw_bd - length($bd))), $bd,
#                                    $d , (' ' x ($maxw_d  - length($d ))),
#                                    $ad, (' ' x ($maxw_ad - length($ad))),
#                                );
#                            } elsif (($bd, $d, $ad) = $cell =~ /\A([+-]?\d+\.?\d*)([eE])([+-]?\d+)\z/) {
#                                $cell = join(
#                                    '',
#                                    (' ' x ($maxw_bd - length($bd))), $bd,
#                                    $d , (' ' x ($maxw_d  - length($d ))),
#                                    $ad, (' ' x ($maxw_ad - length($ad))),
#                                );
#                            }
#                            my $w = length($cell);
#                            $cell = (' ' x ($maxw - $w)) . $cell
#                                if $maxw > $w;
#                        } elsif ($align eq 'right') {
#                            $cell = (' ' x ($maxw - length($cell))) . $cell;
#                        } elsif ($align eq 'middle' || $align eq 'center') {
#                            my $w = length($cell);
#                            my $n = int(($maxw-$w)/2);
#                            $cell = (' ' x $n) . $cell . (' ' x ($maxw-$w-$n));
#                        } else {
#                            $cell .= (' ' x ($maxw - length($cell)));
#
#                        }
#                        $row->[$colidx] = $cell;
#                    }
#                }
#            } 
#        } 
#
#        my $fres;
#        if (my $backend = $ENV{FORMAT_PRETTY_TABLE_BACKEND}) {
#            require Text::Table::Any;
#            $fres = Text::Table::Any::table(rows=>$data, header_row=>$header_row, backend=>$backend);
#        } else {
#            require Text::Table::Tiny;
#            $fres = Text::Table::Tiny::table(rows=>$data, header_row=>$header_row);
#        }
#        $fres .= "\n" unless $fres =~ /\R\z/ || !length($fres);
#        $fres;
#    } elsif ($format eq 'csv') {
#        no warnings 'uninitialized';
#        join(
#            "",
#            map {
#                my $row = $_;
#                join(
#                    ",",
#                    map {
#                        my $cell = $_;
#                        $cell =~ s/(["\\])/\\$1/g;
#                        qq("$cell");
#                    } @$row)."\n";
#            } @$data
#        );
#    } elsif ($format eq 'html') {
#        no warnings 'uninitialized';
#        require HTML::Entities;
#
#        my $tfa = $resmeta->{'table.field_aligns'};
#
#        my @res;
#        push @res, "<table".($resmeta->{'table.html_class'} ?
#                                 " class=\"".HTML::Entities::encode_entities(
#                                     $resmeta->{'table.html_class'})."\"" : "").
#                                         ">\n";
#        for my $i (0..$#{$data}) {
#            my $data_elem = $i == 0 ? "th" : "td";
#            push @res, "<thead>\n" if $i == 0;
#            push @res, "<tbody>\n" if $i == 1;
#            push @res, " <tr>\n";
#            my $row = $data->[$i];
#            for my $j (0..$#{$row}) {
#                my $field_idx = $field_idxs[$j];
#                my $align;
#                if ($field_idx >= 0 && $tfa->[$field_idx]) {
#                    $align = $tfa->[$field_idx];
#                    $align = "right" if $align eq 'number';
#                    $align = "middle" if $align eq 'center';
#                }
#                push @res, "  <$data_elem",
#                    ($align ? " align=\"$align\"" : ""),
#                    ">", HTML::Entities::encode_entities($row->[$j]),
#                    "</$data_elem>\n";
#            }
#            push @res, " </tr>\n";
#            push @res, "</thead>\n" if $i == 0;
#        }
#        push @res, "</tbody>\n";
#        push @res, "</table>\n";
#        join '', @res;
#    } else {
#        no warnings 'uninitialized';
#        shift @$data if $header_row;
#        join("", map {join("\t", @$_)."\n"} @$data);
#    }
#}
#
#sub format {
#    my ($res, $format, $is_naked, $cleanse) = @_;
#
#    if ($format =~ /\A(text|text-simple|text-pretty|csv|html)\z/) {
#        $format = $format eq 'text' ?
#            ((-t STDOUT) ? 'text-pretty' : 'text-simple') : $format;
#        no warnings 'uninitialized';
#        if ($res->[0] !~ /^(2|304)/) {
#            my $fres = "ERROR $res->[0]: $res->[1]";
#            if (my $prev = $res->[3]{prev}) {
#                $fres .= " ($prev->[0]: $prev->[1])";
#            }
#            return "$fres\n";
#        } elsif ($res->[3] && $res->[3]{"x.hint.result_binary"}) {
#            return $res->[2];
#        } else {
#            require Data::Check::Structure;
#            my $data = $res->[2];
#            my $max = 5;
#            if (!ref($data)) {
#                $data //= "";
#                $data .= "\n" unless !length($data) || $data =~ /\n\z/;
#                return $data;
#            } elsif (ref($data) eq 'ARRAY' && !@$data) {
#                return "";
#            } elsif (Data::Check::Structure::is_aos($data, {max=>$max})) {
#                return join("", map {"$_\n"} @$data);
#            } elsif (Data::Check::Structure::is_aoaos($data, {max=>$max})) {
#                return __gen_table($data, 0, $res->[3], $format);
#            } elsif (Data::Check::Structure::is_hos($data, {max=>$max})) {
#                $data = [map {[$_, $data->{$_}]} sort keys %$data];
#                unshift @$data, ["key", "value"];
#                return __gen_table($data, 1, $res->[3], $format);
#            } elsif (Data::Check::Structure::is_aohos($data, {max=>$max})) {
#                my @fieldnames;
#                if ($res->[3] && $res->[3]{'table.fields'} &&
#                        $res->[3]{'table.hide_unknown_fields'}) {
#                    @fieldnames = @{ $res->[3]{'table.fields'} };
#                } else {
#                    my %fieldnames;
#                    for my $row (@$data) {
#                        $fieldnames{$_}++ for keys %$row;
#                    }
#                    @fieldnames = sort keys %fieldnames;
#                }
#                my $newdata = [];
#                for my $row (@$data) {
#                    push @$newdata, [map {$row->{$_}} @fieldnames];
#                }
#                unshift @$newdata, \@fieldnames;
#                return __gen_table($newdata, 1, $res->[3], $format);
#            } else {
#                $format = 'json-pretty';
#            }
#        }
#    }
#
#    my $tff = $res->[3]{'table.fields'};
#    $res = $res->[2] if $is_naked;
#
#    unless ($format =~ /\Ajson(-pretty)?\z/) {
#        warn "Unknown format '$format', fallback to json-pretty";
#        $format = 'json-pretty';
#    }
#    __cleanse($res) if ($cleanse//1);
#    if ($format =~ /json/) {
#        if ($tff && _json->can("sort_by") &&
#                eval { require Sort::ByExample; 1}) {
#            my $cmp = Sort::ByExample->cmp($tff);
#            _json->sort_by(sub { $cmp->($JSON::PP::a, $JSON::PP::b) });
#        }
#
#        if ($format eq 'json') {
#            return _json->encode($res) . "\n";
#        } else {
#            _json->pretty(1);
#            return _json->encode($res);
#        }
#    }
#}
#
#{
#    no strict 'refs';
#    $main::fatpacked{"Data/Check/Structure.pm"} = '##line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'DATA_CHECK_STRUCTURE';
##package Data::Check::Structure;
##
##our $DATE = '2014-07-14'; 
##our $VERSION = '0.03'; 
##
##use 5.010001;
##use strict;
##use warnings;
##
##require Exporter;
##our @ISA = qw(Exporter);
##our @EXPORT_OK = qw(
##                       is_aoa
##                       is_aoaos
##                       is_aoh
##                       is_aohos
##                       is_aos
##                       is_hoa
##                       is_hoaos
##                       is_hoh
##                       is_hohos
##                       is_hos
##               );
##
##sub is_aos {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'ARRAY';
##    for my $i (0..@$data-1) {
##        last if defined($max) && $i >= $max;
##        return 0 if ref($data->[$i]);
##    }
##    1;
##}
##
##sub is_aoa {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'ARRAY';
##    for my $i (0..@$data-1) {
##        last if defined($max) && $i >= $max;
##        return 0 unless ref($data->[$i]) eq 'ARRAY';
##    }
##    1;
##}
##
##sub is_aoaos {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'ARRAY';
##    my $aos_opts = {max=>$max};
##    for my $i (0..@$data-1) {
##        last if defined($max) && $i >= $max;
##        return 0 unless is_aos($data->[$i], $aos_opts);
##    }
##    1;
##}
##
##sub is_aoh {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'ARRAY';
##    for my $i (0..@$data-1) {
##        last if defined($max) && $i >= $max;
##        return 0 unless ref($data->[$i]) eq 'HASH';
##    }
##    1;
##}
##
##sub is_aohos {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'ARRAY';
##    my $hos_opts = {max=>$max};
##    for my $i (0..@$data-1) {
##        last if defined($max) && $i >= $max;
##        return 0 unless is_hos($data->[$i], $hos_opts);
##    }
##    1;
##}
##
##sub is_hos {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'HASH';
##    my $i = 0;
##    for my $k (keys %$data) {
##        last if defined($max) && ++$i >= $max;
##        return 0 if ref($data->{$k});
##    }
##    1;
##}
##
##sub is_hoa {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'HASH';
##    my $i = 0;
##    for my $k (keys %$data) {
##        last if defined($max) && ++$i >= $max;
##        return 0 unless ref($data->{$k}) eq 'ARRAY';
##    }
##    1;
##}
##
##sub is_hoaos {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'HASH';
##    my $i = 0;
##    for my $k (keys %$data) {
##        last if defined($max) && ++$i >= $max;
##        return 0 unless is_aos($data->{$k});
##    }
##    1;
##}
##
##sub is_hoh {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'HASH';
##    my $i = 0;
##    for my $k (keys %$data) {
##        last if defined($max) && ++$i >= $max;
##        return 0 unless ref($data->{$k}) eq 'HASH';
##    }
##    1;
##}
##
##sub is_hohos {
##    my ($data, $opts) = @_;
##    $opts //= {};
##    my $max = $opts->{max};
##
##    return 0 unless ref($data) eq 'HASH';
##    my $i = 0;
##    for my $k (keys %$data) {
##        last if defined($max) && ++$i >= $max;
##        return 0 unless is_hos($data->{$k});
##    }
##    1;
##}
##
##1;
##
##__END__
##
#DATA_CHECK_STRUCTURE
#
#    $main::fatpacked{"Text/Table/Any.pm"} = '##line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TEXT_TABLE_ANY';
##package Text::Table::Any;
##
##our $DATE = '2016-12-29'; 
##our $VERSION = '0.06'; 
##
##
##sub _encode {
##    my $val = shift;
##    $val =~ s/([\\"])/\\$1/g;
##    "\"$val\"";
##}
##
##sub table {
##    my %params = @_;
##
##    my $rows       = $params{rows} or die "Must provide rows!";
##    my $backend    = $params{backend} || 'Text::Table::Tiny';
##    my $header_row = $params{header_row} // 0;
##
##    if ($backend eq 'Text::Table::Tiny') {
##        require Text::Table::Tiny;
##        return Text::Table::Tiny::table(
##            rows => $rows, header_row => $header_row) . "\n";
##    } elsif ($backend eq 'Text::Table::TinyColor') {
##        require Text::Table::TinyColor;
##        return Text::Table::TinyColor::table(
##            rows => $rows, header_row => $header_row) . "\n";
##    } elsif ($backend eq 'Text::Table::TinyColorWide') {
##        require Text::Table::TinyColorWide;
##        return Text::Table::TinyColorWide::table(
##            rows => $rows, header_row => $header_row) . "\n";
##    } elsif ($backend eq 'Text::Table::TinyWide') {
##        require Text::Table::TinyWide;
##        return Text::Table::TinyWide::table(
##            rows => $rows, header_row => $header_row) . "\n";
##    } elsif ($backend eq 'Text::Table::Org') {
##        require Text::Table::Org;
##        return Text::Table::Org::table(
##            rows => $rows, header_row => $header_row);
##    } elsif ($backend eq 'Text::Table::CSV') {
##        require Text::Table::CSV;
##        return Text::Table::CSV::table(
##            rows => $rows);
##    } elsif ($backend eq 'Text::Table::HTML') {
##        require Text::Table::HTML;
##        return Text::Table::HTML::table(
##            rows => $rows, header_row => $header_row);
##    } elsif ($backend eq 'Text::Table::HTML::DataTables') {
##        require Text::Table::HTML::DataTables;
##        return Text::Table::HTML::DataTables::table(
##            rows => $rows, header_row => $header_row);
##    } elsif ($backend eq 'Text::ANSITable') {
##        require Text::ANSITable;
##        my $t = Text::ANSITable->new(
##            use_utf8 => 0,
##            use_box_chars => 0,
##            use_color => 0,
##            border_style => 'Default::single_ascii',
##        );
##        if ($header_row) {
##            $t->columns($rows->[0]);
##            $t->add_row($rows->[$_]) for 1..@$rows-1;
##        } else {
##            $t->columns([ map {"col$_"} 0..$#{$rows->[0]} ]);
##            $t->add_row($_) for @$rows;
##        }
##        return $t->draw;
##    } elsif ($backend eq 'Text::ASCIITable') {
##        require Text::ASCIITable;
##        my $t = Text::ASCIITable->new();
##        if ($header_row) {
##            $t->setCols(@{ $rows->[0] });
##            $t->addRow(@{ $rows->[$_] }) for 1..@$rows-1;
##        } else {
##            $t->setCols(map { "col$_" } 0..$#{ $rows->[0] });
##            $t->addRow(@$_) for @$rows;
##        }
##        return "$t";
##    } elsif ($backend eq 'Text::FormatTable') {
##        require Text::FormatTable;
##        my $t = Text::FormatTable->new(join('|', ('l') x @{ $rows->[0] }));
##        $t->head(@{ $rows->[0] });
##        $t->row(@{ $rows->[$_] }) for 1..@$rows-1;
##        return $t->render;
##    } elsif ($backend eq 'Text::MarkdownTable') {
##        require Text::MarkdownTable;
##        my $out = "";
##        my $fields =  $header_row ?
##            $rows->[0] : [map {"col$_"} 0..$#{ $rows->[0] }];
##        my $t = Text::MarkdownTable->new(file => \$out, columns => $fields);
##        foreach (($header_row ? 1:0) .. $#{$rows}) {
##            my $row = $rows->[$_];
##            $t->add( {
##                map { $fields->[$_] => $row->[$_] } 0..@$fields-1
##            });
##        }
##        $t->done;
##        return $out;
##    } elsif ($backend eq 'Text::Table') {
##        require Text::Table;
##        my $t = Text::Table->new(@{ $rows->[0] });
##        $t->load(@{ $rows }[1..@$rows-1]);
##        return $t;
##    } elsif ($backend eq 'Text::TabularDisplay') {
##        require Text::TabularDisplay;
##        my $t = Text::TabularDisplay->new(@{ $rows->[0] });
##        $t->add(@{ $rows->[$_] }) for 1..@$rows-1;
##        return $t->render . "\n";
##    } else {
##        die "Unknown backend '$backend'";
##    }
##}
##
##1;
##
##__END__
##
#TEXT_TABLE_ANY
#
#    $main::fatpacked{"Text/Table/Tiny.pm"} = '##line '.(1+__LINE__).' "'.__FILE__."\"\n".<<'TEXT_TABLE_TINY';
##use 5.006;
##use strict;
##use warnings;
##package Text::Table::Tiny;
##$Text::Table::Tiny::VERSION = '0.04';
##use parent 'Exporter';
##use List::Util qw();
##
##our @EXPORT_OK = qw/ generate_table /;
##
##
##
##our $COLUMN_SEPARATOR = '|';
##our $ROW_SEPARATOR = '-';
##our $CORNER_MARKER = '+';
##our $HEADER_ROW_SEPARATOR = '=';
##our $HEADER_CORNER_MARKER = 'O';
##
##sub generate_table {
##
##    my %params = @_;
##    my $rows = $params{rows} or die "Must provide rows!";
##
##    my $widths = _maxwidths($rows);
##    my $max_index = _max_array_index($rows);
##
##    my $format = _get_format($widths);
##    my $row_sep = _get_row_separator($widths);
##    my $head_row_sep = _get_header_row_separator($widths);
##
##    my @table;
##    push @table, $row_sep;
##
##    my $data_begins = 0;
##    if ( $params{header_row} ) {
##        my $header_row = $rows->[0];
##        $data_begins++;
##        push @table, sprintf(
##                         $format, 
##                         map { defined($header_row->[$_]) ? $header_row->[$_] : '' } (0..$max_index)
##                     );
##        push @table, $params{separate_rows} ? $head_row_sep : $row_sep;
##    }
##
##    foreach my $row ( @{ $rows }[$data_begins..$#$rows] ) {
##        push @table, sprintf(
##	    $format, 
##	    map { defined($row->[$_]) ? $row->[$_] : '' } (0..$max_index)
##	);
##        push @table, $row_sep if $params{separate_rows};
##    }
##
##    push @table, $row_sep unless $params{separate_rows};
##    return join("\n",grep {$_} @table);
##}
##
##sub _get_cols_and_rows ($) {
##    my $rows = shift;
##    return ( List::Util::max( map { scalar @$_ } @$rows), scalar @$rows);
##}
##
##sub _maxwidths {
##    my $rows = shift;
##    my $max_index = _max_array_index($rows);
##    my $widths = [];
##    for my $i (0..$max_index) {
##        my $max = List::Util::max(map {defined $$_[$i] ? length($$_[$i]) : 0} @$rows);
##        push @$widths, $max;
##    }
##    return $widths;
##}
##
##sub _max_array_index {
##    my $rows = shift;
##    return List::Util::max( map { $#$_ } @$rows );
##}
##
##sub _get_format {
##    my $widths = shift;
##    return "$COLUMN_SEPARATOR ".join(" $COLUMN_SEPARATOR ",map { "%-${_}s" } @$widths)." $COLUMN_SEPARATOR";
##}
##
##sub _get_row_separator {
##    my $widths = shift;
##    return "$CORNER_MARKER$ROW_SEPARATOR".join("$ROW_SEPARATOR$CORNER_MARKER$ROW_SEPARATOR",map { $ROW_SEPARATOR x $_ } @$widths)."$ROW_SEPARATOR$CORNER_MARKER";
##}
##
##sub _get_header_row_separator {
##    my $widths = shift;
##    return "$HEADER_CORNER_MARKER$HEADER_ROW_SEPARATOR".join("$HEADER_ROW_SEPARATOR$HEADER_CORNER_MARKER$HEADER_ROW_SEPARATOR",map { $HEADER_ROW_SEPARATOR x $_ } @$widths)."$HEADER_ROW_SEPARATOR$HEADER_CORNER_MARKER";
##}
##
##*table = \&generate_table;
##
##1;
##
##__END__
##
##
#TEXT_TABLE_TINY
#
#    $main::fatpacked{$_} =~ s/^\#//mg for ('Data/Check/Structure.pm', 'Text/Table/Any.pm', 'Text/Table/Tiny.pm');
#    my $class = 'FatPacked::'.(0+\%main::fatpacked);
#    unless (defined &{"${class}::INC"}) { if ($] < 5.008) { *{"${class}::INC"} = sub { if (my $fat = $_[0]{$_[1]}) { return sub { return 0 unless length $fat; $fat =~ s/^([^\n]*\n?)//; $_ = $1; return 1; }; } return; }; } else { *{"${class}::INC"} = sub { if (my $fat = $_[0]{$_[1]}) { open my $fh, '<', \$fat or die "FatPacker error loading $_[1] (could be a perl installation issue?)"; return $fh; } return; }; } }
#    my $hook = bless(\%main::fatpacked, $class);
#    push @INC, $hook unless grep {ref($_) && "$_" eq "$hook"} @INC;
#}
#
#1;
#
#__END__
#
### Scalar/Util/Numeric/PP.pm ###
#package Scalar::Util::Numeric::PP;
#
#our $DATE = '2016-01-22'; 
#our $VERSION = '0.04'; 
#
#use 5.010001;
#use strict;
#use warnings;
#
#require Exporter;
#our @ISA       = qw(Exporter);
#our @EXPORT_OK = qw(
#                       isint
#                       isnum
#                       isnan
#                       isinf
#                       isneg
#                       isfloat
#               );
#
#sub isint {
#    local $_ = shift;
#    return 0 unless defined;
#    return 1 if /\A\s*[+-]?(?:0|[1-9][0-9]*)\s*\z/s;
#    0;
#}
#
#sub isnan($) {
#    local $_ = shift;
#    return 0 unless defined;
#    return 1 if /\A\s*[+-]?nan\s*\z/is;
#    0;
#}
#
#sub isinf($) {
#    local $_ = shift;
#    return 0 unless defined;
#    return 1 if /\A\s*[+-]?inf(?:inity)?\s*\z/is;
#    0;
#}
#
#sub isneg($) {
#    local $_ = shift;
#    return 0 unless defined;
#    return 1 if /\A\s*-/;
#    0;
#}
#
#sub isnum($) {
#    local $_ = shift;
#    return 0 unless defined;
#    return 1 if isint($_);
#    return 1 if isfloat($_);
#    0;
#}
#
#sub isfloat($) {
#    local $_ = shift;
#    return 0 unless defined;
#    return 1 if /\A\s*[+-]?
#                 (?: (?:0|[1-9][0-9]*)(\.[0-9]+)? | (\.[0-9]+) )
#                 ([eE][+-]?[0-9]+)?\s*\z/sx && $1 || $2 || $3;
#    return 1 if isnan($_) || isinf($_);
#    0;
#}
#
#1;
#
#__END__
#
### Text/Table/Tiny.pm ###
#use 5.006;
#use strict;
#use warnings;
#package Text::Table::Tiny;
#$Text::Table::Tiny::VERSION = '0.04';
#use parent 'Exporter';
#use List::Util qw();
#
#our @EXPORT_OK = qw/ generate_table /;
#
#
#
#our $COLUMN_SEPARATOR = '|';
#our $ROW_SEPARATOR = '-';
#our $CORNER_MARKER = '+';
#our $HEADER_ROW_SEPARATOR = '=';
#our $HEADER_CORNER_MARKER = 'O';
#
#sub generate_table {
#
#    my %params = @_;
#    my $rows = $params{rows} or die "Must provide rows!";
#
#    my $widths = _maxwidths($rows);
#    my $max_index = _max_array_index($rows);
#
#    my $format = _get_format($widths);
#    my $row_sep = _get_row_separator($widths);
#    my $head_row_sep = _get_header_row_separator($widths);
#
#    my @table;
#    push @table, $row_sep;
#
#    my $data_begins = 0;
#    if ( $params{header_row} ) {
#        my $header_row = $rows->[0];
#        $data_begins++;
#        push @table, sprintf(
#                         $format, 
#                         map { defined($header_row->[$_]) ? $header_row->[$_] : '' } (0..$max_index)
#                     );
#        push @table, $params{separate_rows} ? $head_row_sep : $row_sep;
#    }
#
#    foreach my $row ( @{ $rows }[$data_begins..$#$rows] ) {
#        push @table, sprintf(
#	    $format, 
#	    map { defined($row->[$_]) ? $row->[$_] : '' } (0..$max_index)
#	);
#        push @table, $row_sep if $params{separate_rows};
#    }
#
#    push @table, $row_sep unless $params{separate_rows};
#    return join("\n",grep {$_} @table);
#}
#
#sub _get_cols_and_rows ($) {
#    my $rows = shift;
#    return ( List::Util::max( map { scalar @$_ } @$rows), scalar @$rows);
#}
#
#sub _maxwidths {
#    my $rows = shift;
#    my $max_index = _max_array_index($rows);
#    my $widths = [];
#    for my $i (0..$max_index) {
#        my $max = List::Util::max(map {defined $$_[$i] ? length($$_[$i]) : 0} @$rows);
#        push @$widths, $max;
#    }
#    return $widths;
#}
#
#sub _max_array_index {
#    my $rows = shift;
#    return List::Util::max( map { $#$_ } @$rows );
#}
#
#sub _get_format {
#    my $widths = shift;
#    return "$COLUMN_SEPARATOR ".join(" $COLUMN_SEPARATOR ",map { "%-${_}s" } @$widths)." $COLUMN_SEPARATOR";
#}
#
#sub _get_row_separator {
#    my $widths = shift;
#    return "$CORNER_MARKER$ROW_SEPARATOR".join("$ROW_SEPARATOR$CORNER_MARKER$ROW_SEPARATOR",map { $ROW_SEPARATOR x $_ } @$widths)."$ROW_SEPARATOR$CORNER_MARKER";
#}
#
#sub _get_header_row_separator {
#    my $widths = shift;
#    return "$HEADER_CORNER_MARKER$HEADER_ROW_SEPARATOR".join("$HEADER_ROW_SEPARATOR$HEADER_CORNER_MARKER$HEADER_ROW_SEPARATOR",map { $HEADER_ROW_SEPARATOR x $_ } @$widths)."$HEADER_ROW_SEPARATOR$HEADER_CORNER_MARKER";
#}
#
#*table = \&generate_table;
#
#1;
#
#__END__
#
#
