#!perl

### begin code_after_shebang
# Note: This script is a CLI for Riap function /App/hr/hr_app
# and generated automatically using Perinci::CmdLine::Gen version 0.501

### end code_after_shebang
# PERICMD_INLINE_SCRIPT: {"code_after_shebang":"...","config_dirs":null,"config_filename":"hr.conf","env_name":"HR_OPT","include":["App::hr"],"log":null,"pack_deps":1,"pod":0,"read_config":"0","read_env":"0","script_name":"hr","script_summary":null,"script_version":"0.268","shebang":"perl","skip_format":1,"subcommands":null,"url":"/App/hr/hr_app","use_cleanser":1,"validate_args":1}

# This script is generated by Perinci::CmdLine::Inline version 0.554 on Sat Sep  3 19:00:57 2022.

# Rinci metadata taken from these modules: App::hr (no version)

# You probably should not manually edit this file.

## no critic: TestingAndDebugging::RequireUseStrict

# PODNAME: hr
# ABSTRACT: Print horizontal bar on the terminal

# BEGIN DATAPACK CODE
package main::_DataPacker;
our $handler;
sub main::_DataPacker::INC { goto $handler }

package main;
{
    my $toc;
    my $data_linepos = 1;
    $main::_DataPacker::handler = sub {
        my $debug = $ENV{PERL_DATAPACKER_DEBUG};
        if ($debug) {
            my @caller0 = caller;
            warn "[datapacker] Hook called with arguments: (".join(",", @_).") by package $caller0[0] in file $caller0[1] line $caller0[2]\n";
        }

        $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]}) {
            warn "[datapacker] $_[1] FOUND in packed modules\n" if $debug;
            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;
        } else {
            warn "[datapacker] $_[1] NOT found in packed modules\n" if $debug;
        }
        return;
    }; # handler
    unshift @INC, bless(sub {"dummy"}, "main::_DataPacker");
}
# END DATAPACK CODE

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

# load modules


### declare global variables

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2022-09-03'; # DATE
our $DIST = 'App-hr'; # DIST
our $VERSION = '0.268'; # VERSION

my $_pci_metas = {""=>{args=>{blink=>{cmdline_aliases=>{B=>{}},schema=>["bool",{req=>1}],summary=>"Return a blinking bar"},color=>{cmdline_aliases=>{c=>{}},schema=>["str",{req=>1}],summary=>"Specify a color (see Term::ANSIColor)"},height=>{cmdline_aliases=>{H=>{}},default=>1,schema=>["int",{min=>1,req=>1}],summary=>"Specify height (number of rows)"},pattern=>{cmdline_aliases=>{p=>{}},pos=>0,schema=>["str",{req=>1}],summary=>"Specify a pattern"},random_color=>{schema=>["bool",{is=>1}]},random_pattern=>{cmdline_aliases=>{r=>{code=>sub{"DUMMY"},is_flag=>1,summary=>"Alias for --random-pattern --random-color"}},schema=>["bool",{is=>1}]},space_after=>{cmdline_aliases=>{a=>{}},default=>0,schema=>["int",{min=>0,req=>1}],summary=>"Number of empty rows after drawing the bar"},space_before=>{cmdline_aliases=>{b=>{}},default=>0,schema=>["int",{min=>0,req=>1}],summary=>"Number of empty rows before drawing the bar"}},args_rels=>{"choose_one&"=>[["color","random_color"],["pattern","random_pattern"]]},description=>"\n<prog:hr> can be useful as a marker/separator, especially if you use other\ncommands that might produce a lot of output, and you need to scroll back lots of\npages to see previous output. Example:\n\n    % hr; command-that-produces-lots-of-output\n    ============================================================================\n    Command output\n    ...\n    ...\n    ...\n\n    % hr -r; some-command; hr -r; another-command\n\nUsage:\n\n    % hr\n    ============================================================================\n\n    % hr -c red  ;# will output the same bar, but in red\n\n    % hr --random-color  ;# will output the same bar, but in random color\n\n    % hr x----\n    x----x----x----x----x----x----x----x----x----x----x----x----x----x----x----x\n\n    % hr -- -x-  ;# specify a pattern that starts with a dash\n    % hr -p -x-  ;# ditto\n\n    % hr --random-pattern\n    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n\n    % hr --random-pattern\n    *---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---\n\n    % hr -r  ;# shortcut for --random-pattern --random-color\n\n    % hr -Br ;# a BLINKING random pattern, random color bar\n\n    % hr --help\n\nIf you use Perl, you can also use the `hr` function in <pm:App::hr> module.\n\n",result=>{},summary=>"Print horizontal bar on the terminal",v=>1.1}};

our $_pci_meta_result_stream = 0;
our $_pci_meta_result_type;
our $_pci_meta_result_type_is_simple;
our $_pci_meta_skip_format = 0;
our $_pci_r = {naked_res=>0,read_config=>0,read_env=>0,subcommand_name=>""};
our %_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 }
        else { require JSON::PP; JSON::PP->new->canonical(1)->allow_nonref }
    };
    $json;
}

### begin code_before_parse_cmdline_options
### end code_before_parse_cmdline_options
### get arguments (from config file, env, command-line args

{
my %mentioned_args;
require Getopt::Long::EvenLess;
my $go_spec1 = {
    'help|h|?' => sub { print "hr - Print horizontal bar on the terminal\n\nUsage:\n  hr --help (or -h, -?)\n  hr --version (or -v)\n  hr [--blink|-B|--no-blink|--noblink] [--color=str|-c=str]\n    [--height=int|-H=int] [--page-result[=program]] [--random-color]\n    [--random-pattern|-r] [--space-after=int|-a=int]\n    [--space-before=int|-b=int] -- [pattern]\n\n<prog:hr> can be useful as a marker/separator, especially if you use other\ncommands that might produce a lot of output, and you need to scroll back lots of\npages to see previous output. Example:\n\n    % hr; command-that-produces-lots-of-output\n    ============================================================================\n    Command output\n    ...\n    ...\n    ...\n\n    % hr -r; some-command; hr -r; another-command\n\nUsage:\n\n    % hr\n    ============================================================================\n\n    % hr -c red  ;# will output the same bar, but in red\n\n    % hr --random-color  ;# will output the same bar, but in random color\n\n    % hr x----\n    x----x----x----x----x----x----x----x----x----x----x----x----x----x----x----x\n\n    % hr -- -x-  ;# specify a pattern that starts with a dash\n    % hr -p -x-  ;# ditto\n\n    % hr --random-pattern\n    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n\n    % hr --random-pattern\n    *---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---\n\n    % hr -r  ;# shortcut for --random-pattern --random-color\n\n    % hr -Br ;# a BLINKING random pattern, random color bar\n\n    % hr --help\n\nIf you use Perl, you can also use the `hr` function in <pm:App::hr> module.\n\nMain options:\n  --blink, -B           Return a blinking bar\n  --color=s, -c         Specify a color (see Term::ANSIColor)\n  --height=s, -H        Specify height (number of rows) [1]\n  --pattern=s, -p       Specify a pattern (=arg[0])\n  --random-color        \n  --random-pattern      \n  --space-after=s, -a   Number of empty rows after drawing the bar [0]\n  --space-before=s, -b  Number of empty rows before drawing the bar [0]\n  -r                    Alias for --random-pattern --random-color\n\nOutput options:\n  --page-result  Filter output through a pager\n\nOther options:\n  --help, -h, -?  Display help message and exit\n  --version, -v   Display program's version and exit\n"; exit 0; },
    'page-result:s' => sub { $_pci_r->{page_result} = 1; },
    'version|v' => sub { no warnings 'once'; require App::hr; print "hr version ", "0.268", ($App::hr::DATE ? " ($App::hr::DATE)" : ''), "\n"; print "  Generated by Perinci::CmdLine::Inline version 0.554 (2022-01-16)\n"; exit 0 },
};
my $go_spec2 = {
    'B' => sub {         $_pci_args{'blink'} = $_[1];
 },
    'H=s' => sub {         $_pci_args{'height'} = $_[1];
 },
    'a=s' => sub {         $_pci_args{'space_after'} = $_[1];
 },
    'b=s' => sub {         $_pci_args{'space_before'} = $_[1];
 },
    'blink' => sub {         $_pci_args{'blink'} = $_[1];
 },
    'c=s' => sub {         $_pci_args{'color'} = $_[1];
 },
    'color=s' => sub {         $_pci_args{'color'} = $_[1];
 },
    'height=s' => sub {         $_pci_args{'height'} = $_[1];
 },
    'help|h|?' => sub {  },
    'no-blink' => sub {         $_pci_args{'blink'} = 0;
 },
    'noblink' => sub {         $_pci_args{'blink'} = 0;
 },
    'p=s' => sub {         $_pci_args{'pattern'} = $_[1];
 },
    'page-result:s' => sub {  },
    'pattern=s' => sub {         $_pci_args{'pattern'} = $_[1];
 },
    'r' => sub {         my $code = sub{package App::hr;use warnings;use strict 'subs', 'vars';use feature 'say';$_[0]{'random_color'} = 1;$_[0]{'random_pattern'} = 1}; $code->(\%_pci_args);
 },
    'random-color' => sub {         $_pci_args{'random_color'} = $_[1];
 },
    'random-pattern' => sub {         $_pci_args{'random_pattern'} = $_[1];
 },
    'space-after=s' => sub {         $_pci_args{'space_after'} = $_[1];
 },
    'space-before=s' => sub {         $_pci_args{'space_before'} = $_[1];
 },
    'version|v' => sub {  },
};
my $old_conf = Getopt::Long::EvenLess::Configure("pass_through");
Getopt::Long::EvenLess::GetOptions(%$go_spec1);
Getopt::Long::EvenLess::Configure($old_conf);
my $res = Getopt::Long::EvenLess::GetOptions(%$go_spec2);
_pci_err([500, "GetOptions failed"]) unless $res;
}

### check arguments

{
require Local::_pci_check_args; my $res = _pci_check_args(\%_pci_args);
_pci_err($res) if $res->[0] != 200;
$_pci_r->{args} = \%_pci_args;
}

### call function

{
my $sc_name = $_pci_r->{subcommand_name};
if ($sc_name eq "") {
    $_pci_meta_result_type = "";
    require App::hr;
    eval { $_pci_r->{res} = App::hr::hr_app(%_pci_args) };
    if ($@) { die if $ENV{PERINCI_CMDLINE_INLINE_DEBUG_DIE}; $_pci_r->{res} = [500, "Function died: $@"] }
}
}

### format & display result

{
my $fh;
if ($_pci_r->{page_result} // $ENV{PAGE_RESULT} // $_pci_r->{res}[3]{"cmdline.page_result"}) {
my $pager = $_pci_r->{pager} // $_pci_r->{res}[3]{"cmdline.pager"} // $ENV{PAGER} // "less -FRSX";
open $fh, "| $pager"; ## no critic InputOutput::ProhibitTwoArgOpen
} else {
$fh = \*STDOUT;
}
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} // $_pci_meta_result_stream // 0;
if ($is_success && (1 || $_pci_meta_skip_format || $_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, ":encoding(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 ($_pci_meta_result_type_is_simple) { while(defined(my $l=$code->())) { print $fh $l; print $fh "\n" unless $_pci_meta_result_type eq "buf"; } } else { while (defined(my $rec=$code->())) { if (!defined($rec) || ref $rec) { print $fh _pci_json()->encode($rec),"\n" } else { print $fh $rec,"\n" } } }
} else {
    print $fh $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

hr - Print horizontal bar on the terminal

=head1 VERSION

This document describes version 0.268 of main::_DataPacker (from Perl distribution App-hr), released on 2022-09-03.

=head1 SYNOPSIS

B<hr> [B<--blink>|B<-B>|B<--no-blink>|B<--noblink>] [B<--color>=I<str>|B<-c>=I<str>] [B<--height>=I<int>|B<-H>=I<int>] [B<--random-color>] [B<--random-pattern>|B<-r>] [B<--space-after>=I<int>|B<-a>=I<int>] [B<--space-before>=I<int>|B<-b>=I<int>] -- [I<pattern>]

=head1 DESCRIPTION

L<hr> can be useful as a marker/separator, especially if you use other
commands that might produce a lot of output, and you need to scroll back lots of
pages to see previous output. Example:

 % hr; command-that-produces-lots-of-output
 ============================================================================
 Command output
 ...
 ...
 ...
 
 % hr -r; some-command; hr -r; another-command

Usage:

 % hr
 ============================================================================
 
 % hr -c red  ;# will output the same bar, but in red
 
 % hr --random-color  ;# will output the same bar, but in random color
 
 % hr x----
 x----x----x----x----x----x----x----x----x----x----x----x----x----x----x----x
 
 % hr -- -x-  ;# specify a pattern that starts with a dash
 % hr -p -x-  ;# ditto
 
 % hr --random-pattern
 vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
 
 % hr --random-pattern
 *---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---
 
 % hr -r  ;# shortcut for --random-pattern --random-color
 
 % hr -Br ;# a BLINKING random pattern, random color bar
 
 % hr --help

If you use Perl, you can also use the C<hr> function in L<App::hr> module.

=head1 OPTIONS

C<*> marks required options.

=head2 Main options

=over

=item B<--blink>, B<-B>

Return a blinking bar.

=item B<--color>=I<s>, B<-c>

Specify a color (see Term::ANSIColor).

=item B<--height>=I<s>, B<-H>

Specify height (number of rows).

Default value:

 1

=item B<--pattern>=I<s>, B<-p>

Specify a pattern.

Can also be specified as the 1st command-line argument.

=item B<--random-color>

=item B<--random-pattern>

=item B<--space-after>=I<s>, B<-a>

Number of empty rows after drawing the bar.

Default value:

 0

=item B<--space-before>=I<s>, B<-b>

Number of empty rows before drawing the bar.

Default value:

 0

=item B<-r>

Alias for --random-pattern --random-color.

See C<--random-pattern>.

=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 script comes with a companion shell completer script (L<_hr>)
for this script.

=head2 bash

To activate bash completion for this script, put:

 complete -C _hr hr

in your bash startup (e.g. F<~/.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 modules using L<cpanm-shcompgen>
which can activate shell completion for scripts immediately.

=head2 tcsh

To activate tcsh completion for this script, put:

 complete hr 'p/*/`hr`/'

in your tcsh startup (e.g. F<~/.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 L<shcompgen> (see above).

=head2 other shells

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

=head1 HOMEPAGE

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

=head1 SOURCE

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

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 CONTRIBUTING


To contribute, you can send patches by email/via RT, or send pull requests on
GitHub.

Most of the time, you don't need to build the distribution yourself. You can
simply modify the code, then test via:

 % prove -l

If you want to build the distribution (e.g. to try to install it locally on your
system), you can install L<Dist::Zilla>,
L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
that are considered a bug and can be reported to me.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2022, 2021, 2020, 2018, 2016, 2015, 2014 by perlancar <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.

=head1 BUGS

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

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.

=cut

__DATA__
Data::Section::Seekable v1
App/hr.pm,18,7817,0;0
Clone/PP.pm,7855,6331,1;318
Getopt/Long/EvenLess.pm,14218,11364,2;511
Local/_pci_check_args.pm,25615,6528,3;893
Local/_pci_clean_json.pm,32176,4414,4;1034
Scalar/Util/Numeric/PP.pm,36624,3106,5;1096

### App/hr.pm ###
#package App::hr;
#
#use feature 'say';
#use strict 'subs', 'vars';
#use warnings;
#
#use Exporter 'import';
#
## AUTHORITY
## DATE
## DIST
## VERSION
#
#our @EXPORT_OK = qw(
#                       hr
#                       hr_r
#                       hr_Br
#               );
#
#our %SPEC;
#
## from Code::Embeddable
#sub pick {
#    return unless @_;
#    return $_[@_*rand];
#}
#
#my $term_width;
#if (defined $ENV{COLUMNS}) {
#    $term_width = $ENV{COLUMNS};
#} elsif (eval { require Term::Size; 1 }) {
#    ($term_width, undef) = Term::Size::chars(*STDOUT{IO});
#} else {
#    $term_width = 80;
#}
#
#sub hr {
#    my ($pattern, $color, $blink) = @_;
#    $pattern = "=" if !defined($pattern) || !length($pattern);
#    my $n  = int($term_width / length($pattern))+1;
#    my $hr = substr(($pattern x $n), 0, $term_width);
#    if ($^O =~ /MSWin/) {
#        substr($hr, -1, 1) = '';
#    }
#
#    # should we actually output color?
#    my $do_color = do {
#        if (exists $ENV{NO_COLOR}) {
#            0;
#        } elsif (defined $ENV{COLOR}) {
#            $ENV{COLOR};
#        } else {
#            (-t STDOUT); ## no critic: InputOutput::ProhibitInteractiveTest
#        }
#    };
#    undef $color unless $do_color;
#
#    $hr = "\e[5m$hr\e[0m" if $blink;
#
#    if (defined $color) {
#        require Term::ANSIColor;
#        $hr = Term::ANSIColor::colored([$color], $hr);
#    }
#    return $hr if defined(wantarray);
#    say $hr;
#}
#
#$SPEC{hr_app} = {
#    v => 1.1,
#    summary => 'Print horizontal bar on the terminal',
#    description => <<'_',
#
#<prog:hr> can be useful as a marker/separator, especially if you use other
#commands that might produce a lot of output, and you need to scroll back lots of
#pages to see previous output. Example:
#
#    % hr; command-that-produces-lots-of-output
#    ============================================================================
#    Command output
#    ...
#    ...
#    ...
#
#    % hr -r; some-command; hr -r; another-command
#
#Usage:
#
#    % hr
#    ============================================================================
#
#    % hr -c red  ;# will output the same bar, but in red
#
#    % hr --random-color  ;# will output the same bar, but in random color
#
#    % hr x----
#    x----x----x----x----x----x----x----x----x----x----x----x----x----x----x----x
#
#    % hr -- -x-  ;# specify a pattern that starts with a dash
#    % hr -p -x-  ;# ditto
#
#    % hr --random-pattern
#    vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#
#    % hr --random-pattern
#    *---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---*---
#
#    % hr -r  ;# shortcut for --random-pattern --random-color
#
#    % hr -Br ;# a BLINKING random pattern, random color bar
#
#    % hr --help
#
#If you use Perl, you can also use the `hr` function in <pm:App::hr> module.
#
#_
#    args_rels => {
#        'choose_one&' => [
#            [qw/color random_color/],
#            [qw/pattern random_pattern/],
#        ],
#    },
#    args => {
#        color => {
#            summary => 'Specify a color (see Term::ANSIColor)',
#            schema => 'str*',
#            cmdline_aliases => {c=>{}},
#        },
#        random_color => {
#            schema => ['bool', is=>1],
#        },
#        blink => {
#            summary => 'Return a blinking bar',
#            schema => 'bool*',
#            cmdline_aliases => {B=>{}},
#        },
#        height => {
#            summary => 'Specify height (number of rows)',
#            schema => ['int*', min=>1],
#            default => 1,
#            cmdline_aliases => {H=>{}},
#        },
#        space_before => {
#            summary => 'Number of empty rows before drawing the bar',
#            schema => ['int*', min=>0],
#            default => 0,
#            cmdline_aliases => {b=>{}},
#        },
#        space_after => {
#            summary => 'Number of empty rows after drawing the bar',
#            schema => ['int*', min=>0],
#            default => 0,
#            cmdline_aliases => {a=>{}},
#        },
#        pattern => {
#            summary => 'Specify a pattern',
#            schema => 'str*',
#            pos => 0,
#            cmdline_aliases => {p=>{}},
#        },
#        random_pattern => {
#            schema => ['bool', is=>1],
#            cmdline_aliases => {
#                r => {
#                    summary => 'Alias for --random-pattern --random-color',
#                    is_flag => 1,
#                    code => sub {
#                        $_[0]{random_color} = 1;
#                        $_[0]{random_pattern} = 1;
#                    },
#                },
#            },
#        },
#    },
#};
#sub hr_app {
#    my %args = @_;
#
#    if ($args{random_color}) {
#        $args{color} = pick(
#            'red',
#            'bright_red',
#            'green',
#            'bright_green',
#            'blue',
#            'bright_blue',
#            'cyan',
#            'bright_cyan',
#            'magenta',
#            'bright_magenta',
#            'yellow',
#            'bright_yellow',
#            'white',
#            'bright_white',
#        );
#    }
#
#    if ($args{random_pattern}) {
#        $args{pattern} = pick(
#            '.',
#            '-',
#            '=',
#            'x',
#            'x-',
#            'x---',
#            'x-----',
#            '*',
#            '*-',
#            '*---',
#            '*-----',
#            '/\\',
#            'v',
#            'V',
#        );
#    }
#
#    my $res = hr($args{pattern}, $args{color}, $args{blink});
#    $res = join(
#        "",
#        ("\n" x ($args{space_before} // 0)),
#        ("$res\n" x ($args{height} // 1)),
#        ("\n" x ($args{space_after} // 0)),
#    );
#
#    [200, "OK", $res];
#}
#
#sub hr_r {
#    my $res = hr_app(random_color=>1, random_pattern=>1);
#    my $hr  = $res->[2];
#    return $hr if defined(wantarray);
#    print $hr;
#}
#
#sub hr_Br {
#    my $res = hr_app(blink=>1, random_color=>1, random_pattern=>1);
#    my $hr  = $res->[2];
#    return $hr if defined(wantarray);
#    print $hr;
#}
#
#1;
## ABSTRACT: Print horizontal bar on the terminal
#
#=for Pod::Coverage ^(pick)$
#
#=head1 SYNOPSIS
#
# use App::hr qw(hr hr_r);
# hr;
#
#Sample output:
#
# =============================================================================
#
#Set pattern:
#
# hr('x----');
#
#Sample output:
#
# x----x----x----x----x----x----x----x----x----x----x----x----x----x----x----x-
#
#Use random color and random pattern:
#
# hr_r;
#
#You can also use the provided CLI L<hr>.
#
#
#=head1 DESCRIPTION
#
#A demo screencast:
#
## IMAGE: share/images/screencast1.gif
#
#
#=head1 prepend:FUNCTIONS
#
#=head2 hr([ $pattern [, $color ] ]) => optional STR
#
#Print (under void context) or return (under scalar/array context) a horizontal
#ruler with the width of the terminal.
#
#Terminal width is determined using L<Term::Size>.
#
#C<$pattern> is optional, can be multicharacter, but cannot be empty string. The
#defautl is C<=>.
#
#Under Windows, will shave one character at the end because the terminal cursor
#will move a line down when printing at the last column.
#
#If C<$color> is set (to a color supported by L<Term::ANSIColor>) I<and> colored
#output is enabled, output will be colored. Colored output is enabled if: 1) no
#C<NO_COLOR> environment variable is defined; 2) C<COLOR> is undefined or true,
#or program is run interactively.
#
#=head2 hr_r => optional STR
#
#Like C<hr>, but will set random pattern and random color.
#
#=head2 hr_Br => optional STR
#
#Like C<hr>, but will set random pattern and random color and return a blinking
#bar.
#
#
#=head1 ENVIRONMENT
#
#=head2 NO_COLOR
#
#=head2 COLOR
#
#
#=head1 SEE ALSO
#
#L<ruler> (L<App::ruler>)
#
#=cut
### Clone/PP.pm ###
#package Clone::PP;
#
#use 5.006;
#use strict;
#use warnings;
#use vars qw($VERSION @EXPORT_OK);
#use Exporter;
#
#$VERSION = 1.08;
#
#@EXPORT_OK = qw( clone );
#sub import { goto &Exporter::import } # lazy Exporter
#
## These methods can be temporarily overridden to work with a given class.
#use vars qw( $CloneSelfMethod $CloneInitMethod );
#$CloneSelfMethod ||= 'clone_self';
#$CloneInitMethod ||= 'clone_init';
#
## Used to detect looped networks and avoid infinite recursion. 
#use vars qw( %CloneCache );
#
## Generic cloning function
#sub clone {
#  my $source = shift;
#
#  return undef if not defined($source);
#  
#  # Optional depth limit: after a given number of levels, do shallow copy.
#  my $depth = shift;
#  return $source if ( defined $depth and $depth -- < 1 );
#  
#  # Maintain a shared cache during recursive calls, then clear it at the end.
#  local %CloneCache = ( undef => undef ) unless ( exists $CloneCache{undef} );
#  
#  return $CloneCache{ $source } if ( defined $CloneCache{ $source } );
#  
#  # Non-reference values are copied shallowly
#  my $ref_type = ref $source or return $source;
#  
#  # Extract both the structure type and the class name of referent
#  my $class_name;
#  if ( "$source" =~ /^\Q$ref_type\E\=([A-Z]+)\(0x[0-9a-f]+\)$/ ) {
#    $class_name = $ref_type;
#    $ref_type = $1;
#    # Some objects would prefer to clone themselves; check for clone_self().
#    return $CloneCache{ $source } = $source->$CloneSelfMethod() 
#				  if $source->can($CloneSelfMethod);
#  }
#  
#  # To make a copy:
#  # - Prepare a reference to the same type of structure;
#  # - Store it in the cache, to avoid looping if it refers to itself;
#  # - Tie in to the same class as the original, if it was tied;
#  # - Assign a value to the reference by cloning each item in the original;
#  
#  my $copy;
#  if ($ref_type eq 'HASH') {
#    $CloneCache{ $source } = $copy = {};
#    if ( my $tied = tied( %$source ) ) { tie %$copy, ref $tied }
#    %$copy = map { ! ref($_) ? $_ : clone($_, $depth) } %$source;
#  } elsif ($ref_type eq 'ARRAY') {
#    $CloneCache{ $source } = $copy = [];
#    if ( my $tied = tied( @$source ) ) { tie @$copy, ref $tied }
#    @$copy = map { ! ref($_) ? $_ : clone($_, $depth) } @$source;
#  } elsif ($ref_type eq 'REF' or $ref_type eq 'SCALAR') {
#    $CloneCache{ $source } = $copy = \( my $var = "" );
#    if ( my $tied = tied( $$source ) ) { tie $$copy, ref $tied }
#    $$copy = clone($$source, $depth);
#  } else {
#    # Shallow copy anything else; this handles a reference to code, glob, regex
#    $CloneCache{ $source } = $copy = $source;
#  }
#  
#  # - Bless it into the same class as the original, if it was blessed;
#  # - If it has a post-cloning initialization method, call it.
#  if ( $class_name ) {
#    bless $copy, $class_name;
#    $copy->$CloneInitMethod() if $copy->can($CloneInitMethod);
#  }
#  
#  return $copy;
#}
#
#1;
#
#__END__
#
#=head1 NAME
#
#Clone::PP - Recursively copy Perl datatypes
#
#=head1 SYNOPSIS
#
#  use Clone::PP qw(clone);
#  
#  $item = { 'foo' => 'bar', 'move' => [ 'zig', 'zag' ]  };
#  $copy = clone( $item );
#
#  $item = [ 'alpha', 'beta', { 'gamma' => 'vlissides' } ];
#  $copy = clone( $item );
#
#  $item = Foo->new();
#  $copy = clone( $item );
#
#Or as an object method:
#
#  require Clone::PP;
#  push @Foo::ISA, 'Clone::PP';
#  
#  $item = Foo->new();
#  $copy = $item->clone();
#
#=head1 DESCRIPTION
#
#This module provides a general-purpose clone function to make deep
#copies of Perl data structures. It calls itself recursively to copy
#nested hash, array, scalar and reference types, including tied
#variables and objects.
#
#The clone() function takes a scalar argument to copy. To duplicate
#arrays or hashes, pass them in by reference:
#
#  my $copy = clone(\@array);    my @copy = @{ clone(\@array) };
#  my $copy = clone(\%hash);     my %copy = %{ clone(\%hash) };
#
#The clone() function also accepts an optional second parameter that
#can be used to limit the depth of the copy. If you pass a limit of
#0, clone will return the same value you supplied; for a limit of
#1, a shallow copy is constructed; for a limit of 2, two layers of
#copying are done, and so on.
#
#  my $shallow_copy = clone( $item, 1 );
#
#To allow objects to intervene in the way they are copied, the
#clone() function checks for a couple of optional methods. If an
#object provides a method named C<clone_self>, it is called and the
#result returned without further processing. Alternately, if an
#object provides a method named C<clone_init>, it is called on the
#copied object before it is returned.
#
#=head1 BUGS
#
#Some data types, such as globs, regexes, and code refs, are always copied shallowly.
#
#References to hash elements are not properly duplicated. (This is why two tests in t/dclone.t that are marked "todo".) For example, the following test should succeed but does not:
#
#  my $hash = { foo => 1 }; 
#  $hash->{bar} = \{ $hash->{foo} }; 
#  my $copy = clone( \%hash ); 
#  $hash->{foo} = 2; 
#  $copy->{foo} = 2; 
#  ok( $hash->{bar} == $copy->{bar} );
#
#To report bugs via the CPAN web tracking system, go to 
#C<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Clone-PP> or send mail 
#to C<Dist=Clone-PP#rt.cpan.org>, replacing C<#> with C<@>.
#
#=head1 SEE ALSO
#
#L<Clone> - a baseclass which provides a C<clone()> method.
#
#L<MooseX::Clone> - find-grained cloning for Moose objects.
#
#The C<dclone()> function in L<Storable>.
#
#L<Data::Clone> -
#polymorphic data cloning (see its documentation for what that means).
#
#L<Clone::Any> - use whichever of the cloning methods is available.
#
#=head1 REPOSITORY
#
#L<https://github.com/neilbowers/Clone-PP>
#
#=head1 AUTHOR AND CREDITS
#
#Developed by Matthew Simon Cavalletto at Evolution Softworks. 
#More free Perl software is available at C<www.evoscript.org>.
#
#
#=head1 COPYRIGHT AND LICENSE
#
#Copyright 2003 Matthew Simon Cavalletto. You may contact the author
#directly at C<evo@cpan.org> or C<simonm@cavalletto.org>.
#
#Code initially derived from Ref.pm. Portions Copyright 1994 David Muir Sharnoff.
#
#Interface based by Clone by Ray Finch with contributions from chocolateboy.
#Portions Copyright 2001 Ray Finch. Portions Copyright 2001 chocolateboy. 
#
#You may use, modify, and distribute this software under the same terms as Perl.
#
#=cut
### Getopt/Long/EvenLess.pm ###
#package Getopt::Long::EvenLess;
#
#our $DATE = '2019-02-02'; # DATE
#our $VERSION = '0.112'; # VERSION
#
## IFUNBUILT
## # use strict 'subs', 'vars';
## # use warnings;
## END IFUNBUILT
#
#our @EXPORT   = qw(GetOptions);
#our @EXPORT_OK = qw(GetOptionsFromArray);
#
#my $config = {
#    pass_through => 0,
#    auto_abbrev => 1,
#};
#
#sub Configure {
#    my $old_config = { %$config };
#
#    if (ref($_[0]) eq 'HASH') {
#        for (keys %{$_[0]}) {
#            $config->{$_} = $_[0]{$_};
#        }
#    } else {
#        for (@_) {
#            if ($_ eq 'pass_through') {
#                $config->{pass_through} = 1;
#            } elsif ($_ eq 'no_pass_through') {
#                $config->{pass_through} = 0;
#            } elsif ($_ eq 'auto_abbrev') {
#                $config->{auto_abbrev} = 1;
#            } elsif ($_ eq 'no_auto_abbrev') {
#                $config->{auto_abbrev} = 0;
#            } elsif ($_ =~ /\A(no_ignore_case|no_getopt_compat|gnu_compat|bundling|permute)\z/) {
#                # ignore, already behaves that way
#            } else {
#                die "Unknown configuration '$_'";
#            }
#        }
#    }
#    $old_config;
#}
#
#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) {
#                    # perfect match, we immediately go with this one
#                    @candidates = ($opts[0]);
#                    last OPT_SPEC;
#                } elsif ($config->{auto_abbrev} && index($o, $wanted) == 0) {
#                    # prefix match, collect candidates first
#                    push @candidates, $opts[0];
#                    next OPT_SPEC;
#                }
#            }
#        }
#        if (!@candidates) {
#            unless ($config->{pass_through}) {
#                warn "Unknown option: $wanted\n";
#                $success = 0;
#            }
#            return undef; # means unknown
#        } elsif (@candidates > 1) {
#            unless ($config->{pass_through}) {
#                warn "Option $wanted is ambiguous (" .
#                    join(", ", @candidates) . ")\n";
#                $success = 0;
#            }
#            return ''; # means ambiguous
#        }
#        return $candidates[0];
#    };
#
#    my $code_set_val = sub {
#        my $name = shift;
#
#        my $spec_key = $spec_by_opt_name{$name};
#        my $destination = $spec{$spec_key};
#
#        $destination->({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)) {
#                # unknown option
#                push @remaining, $argv->[$i];
#                next ELEM;
#            } elsif (!length($opt)) {
#                push @remaining, $argv->[$i];
#                next ELEM; # ambiguous
#            }
#
#            my $spec = $spec_by_opt_name{$opt};
#            # check whether option requires an argument
#            if ($spec =~ /=[fios][@%]?\z/) {
#                if (defined $val_in_opt) {
#                    # argument is taken after =
#                    $code_set_val->($opt, $val_in_opt);
#                } else {
#                    if ($i+1 >= @$argv) {
#                        # we are the last element
#                        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;
#            my $remaining_pushed;
#          SHORT_OPT:
#            while ($str =~ s/(.)//) {
#                my $used_name = $1;
#                my $short_opt = $1;
#                my $opt = $code_find_opt->($short_opt, 'short');
#                if (!defined $opt) {
#                    # unknown short option
#                    push @remaining, "-" unless $remaining_pushed++;
#                    $remaining[-1] .= $short_opt;
#                    next SHORT_OPT;
#                } elsif (!length $opt) {
#                    # ambiguous short option
#                    push @remaining, "-" unless $remaining_pushed++;
#                    $remaining[-1] .= $short_opt;
#                }
#
#                my $spec = $spec_by_opt_name{$opt};
#                # check whether option requires an argument
#                if ($spec =~ /=[fios][@%]?\z/) {
#                    if (length $str) {
#                        # argument is taken from $str
#                        $code_set_val->($opt, $str);
#                        next ELEM;
#                    } else {
#                        if ($i+1 >= @$argv) {
#                            # we are the last element
#                            unless ($config->{pass_through}) {
#                                warn "Option $used_name requires an argument\n";
#                                $success = 0;
#                            }
#                            last ELEM;
#                        }
#                        # take the next element as argument
#                        $i++;
#                        $code_set_val->($opt, $argv->[$i]);
#                    }
#                } else {
#                    $code_set_val->($opt);
#                }
#            }
#
#        } else { # argument
#
#            push @remaining, $argv->[$i];
#            next;
#
#        }
#    }
#
#  RETURN:
#    splice @$argv, 0, ~~@$argv, @remaining; # replace with remaining elements
#    return $success;
#}
#
#sub GetOptions {
#    GetOptionsFromArray(\@ARGV, @_);
#}
#
#1;
## ABSTRACT: Like Getopt::Long::Less, but with even less features
#
#__END__
#
#=pod
#
#=encoding UTF-8
#
#=head1 NAME
#
#Getopt::Long::EvenLess - Like Getopt::Long::Less, but with even less features
#
#=head1 VERSION
#
#This document describes version 0.112 of Getopt::Long::EvenLess (from Perl distribution Getopt-Long-EvenLess), released on 2019-02-02.
#
#=head1 DESCRIPTION
#
#This module (GLEL for short) is a reimplementation of L<Getopt::Long> (GL for
#short), but with much less features. It's an even more stripped down version of
#L<Getopt::Long::Less> (GLL for short) and is perhaps less convenient to use for
#day-to-day scripting work.
#
#The main goal is minimum amount of code and small startup overhead. This module
#is an experiment of how little code I can use to support the stuffs I usually do
#with GL.
#
#Compared to GL and GLL, it:
#
#=over
#
#=item * has minimum Configure() support
#
#Only these configurations are known: pass_through, no_pass_through (default).
#
#GLEL is equivalent to GL in this mode: bundling, no_ignore_case,
#no_getopt_compat, gnu_compat, permute.
#
#No support for configuring via import options e.g.:
#
# use Getopt::Long qw(:config pass_through);
#
#=item * does not support increment (C<foo+>)
#
#=item * no type checking (C<foo=i>, C<foo=f>, C<foo=s> all accept any string)
#
#=item * does not support optional value (C<foo:s>), only no value (C<foo>) or required value (C<foo=s>)
#
#=item * does not support desttypes (C<foo=s@>)
#
#=item * does not support destination other than coderef (so no C<< "foo=s" => \$scalar >>, C<< "foo=s" => \@ary >>, no C<< "foo=s" => \%hash >>, only C<< "foo=s" => sub { ... } >>)
#
#Also, in coderef destination, code will get a simple hash instead of a
#"callback" object as its first argument.
#
#=item * does not support hashref as first argument
#
#=item * does not support bool/negation (no C<foo!>, so you have to declare both C<foo> and C<no-foo> manually)
#
#=back
#
#The result?
#
#B<Amount of code>. GLEL 0.07 is about 175 lines of code, while GL is about 1500.
#Sure, if you I<really> want to be minimalistic, you can use this single line of
#code to get options:
#
# @ARGV = grep { /^--([^=]+)(=(.*))?/ ? ($opts{$1} = $2 ? $3 : 1, 0) : 1 } @ARGV;
#
#and you're already able to extract C<--flag> or C<--opt=val> from C<@ARGV> but
#you also lose a lot of stuffs like autoabbreviation, C<--opt val> syntax support
#syntax (which is more common, but requires you specify an option spec), custom
#destination, etc.
#
#=head1 FUNCTIONS
#
#=head2 Configure(@configs | \%config) => hash
#
#Set configuration. Known configurations:
#
#=over
#
#=item * pass_through
#
#Ignore errors (unknown/ambiguous option) and still make GetOptions return true.
#
#=item * no_pass_through (default)
#
#=item * no_auto_abbrev
#
#=item * auto_abbrev (default)
#
#=item * no_ignore_case
#
#=item * no_getopt_compat
#
#=item * gnu_compat
#
#=item * bundling
#
#=item * permute
#
#=back
#
#Return old configuration data. To restore old configuration data you can pass it
#back to C<Configure()>, e.g.:
#
# my $orig_conf = Getopt::Long::EvenLess::Configure("pass_through");
# # ...
# Getopt::Long::EvenLess::Configure($orig_conf);
#
#=head2 GetOptions(%spec) => bool
#
#Shortcut for:
#
# GetOptionsFromArray(\@ARGV, %spec)
#
#=head2 GetOptionsFromArray(\@ary, %spec) => bool
#
#Get (and strip) options from C<@ary>. Return true on success or false on failure
#(unknown option, etc).
#
#=head1 HOMEPAGE
#
#Please visit the project's homepage at L<https://metacpan.org/release/Getopt-Long-EvenLess>.
#
#=head1 SOURCE
#
#Source repository is at L<https://github.com/perlancar/perl-Getopt-Long-EvenLess>.
#
#=head1 BUGS
#
#Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Getopt-Long-EvenLess>
#
#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 SEE ALSO
#
#L<Getopt::Long>
#
#L<Getopt::Long::Less>
#
#If you want I<more> features intead of less, try L<Getopt::Long::More>.
#
#Benchmarks in L<Bencher::Scenario::GetoptModules>
#
#=head1 AUTHOR
#
#perlancar <perlancar@cpan.org>
#
#=head1 COPYRIGHT AND LICENSE
#
#This software is copyright (c) 2019, 2017, 2016, 2015 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
### Local/_pci_check_args.pm ###
#sub _pci_check_args {
#    my ($args) = @_;
#    my $sc_name = $_pci_r->{subcommand_name};
#    if ($sc_name eq "") {
#      FILL_FROM_POS: {
#            1;
#            if (@ARGV > 0) { if (exists $args->{"pattern"}) { return [400, "You specified --pattern but also argument #0"]; } else { $args->{"pattern"} = delete($ARGV[0]); } }
#        }
#        my @check_argv = @ARGV;
#        # fill from cmdline_src
#
#        # fill defaults from "default" property and check against schema
#        no warnings ('void');
#        require Scalar::Util::Numeric::PP;
#        my $_sahv_dpath;
#        my $_sahv_err;
#        if (exists $args->{"blink"}) {
#            $_sahv_dpath = [];
#            # req #0
#            ((defined($args->{"blink"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#            
#            &&
#            
#            # check type 'bool'
#            ((!ref($args->{"blink"})) ? 1 : (($_sahv_err //= "Not of type boolean value"),0))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        if (exists $args->{"color"}) {
#            $_sahv_dpath = [];
#            # req #0
#            ((defined($args->{"color"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#            
#            &&
#            
#            # check type 'str'
#            ((!ref($args->{"color"})) ? 1 : (($_sahv_err //= "Not of type text"),0))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        $args->{"height"} //= 1;
#        if (exists $args->{"height"}) {
#            $_sahv_dpath = [];
#            # req #0
#            ((defined($args->{"height"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#            
#            &&
#            
#            # check type 'int'
#            ((Scalar::Util::Numeric::PP::isint($args->{"height"})) ? 1 : (($_sahv_err //= "Not of type integer"),0))
#            
#            &&
#            
#            (# clause: min
#            (($args->{"height"} >= 1) ? 1 : (($_sahv_err //= "Must be at least 1"),0)))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        if (exists $args->{"pattern"}) {
#            $_sahv_dpath = [];
#            # req #0
#            ((defined($args->{"pattern"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#            
#            &&
#            
#            # check type 'str'
#            ((!ref($args->{"pattern"})) ? 1 : (($_sahv_err //= "Not of type text"),0))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        if (exists $args->{"random_color"}) {
#            $_sahv_dpath = [];
#            # skip if undef
#            (!defined($args->{"random_color"}) ? 1 : 
#            
#            (# check type 'bool'
#            ((!ref($args->{"random_color"})) ? 1 : (($_sahv_err //= "Not of type boolean value"),0))
#            
#            &&
#            
#            (# clause: is
#            (($args->{"random_color"} ? 1:0) == (1 ? 1:0) ? 1 : (($_sahv_err //= "Must have the value 1"),0)))))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        if (exists $args->{"random_pattern"}) {
#            $_sahv_dpath = [];
#            # skip if undef
#            (!defined($args->{"random_pattern"}) ? 1 : 
#            
#            (# check type 'bool'
#            ((!ref($args->{"random_pattern"})) ? 1 : (($_sahv_err //= "Not of type boolean value"),0))
#            
#            &&
#            
#            (# clause: is
#            (($args->{"random_pattern"} ? 1:0) == (1 ? 1:0) ? 1 : (($_sahv_err //= "Must have the value 1"),0)))))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        $args->{"space_after"} //= 0;
#        if (exists $args->{"space_after"}) {
#            $_sahv_dpath = [];
#            # req #0
#            ((defined($args->{"space_after"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#            
#            &&
#            
#            # check type 'int'
#            ((Scalar::Util::Numeric::PP::isint($args->{"space_after"})) ? 1 : (($_sahv_err //= "Not of type integer"),0))
#            
#            &&
#            
#            (# clause: min
#            (($args->{"space_after"} >= 0) ? 1 : (($_sahv_err //= "Must be at least 0"),0)))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#        $args->{"space_before"} //= 0;
#        if (exists $args->{"space_before"}) {
#            $_sahv_dpath = [];
#            # req #0
#            ((defined($args->{"space_before"})) ? 1 : (($_sahv_err //= "Required but not specified"),0))
#            
#            &&
#            
#            # check type 'int'
#            ((Scalar::Util::Numeric::PP::isint($args->{"space_before"})) ? 1 : (($_sahv_err //= "Not of type integer"),0))
#            
#            &&
#            
#            (# clause: min
#            (($args->{"space_before"} >= 0) ? 1 : (($_sahv_err //= "Must be at least 0"),0)))
#             ; if ($_sahv_err) { return [400, "Argument validation failed: $_sahv_err"] }
#        } # if date arg exists
#
#        # check required args
#        return [400, "Missing required value for argument: blink"] if exists($args->{"blink"}) && !defined($args->{"blink"});
#        return [400, "Missing required value for argument: color"] if exists($args->{"color"}) && !defined($args->{"color"});
#        return [400, "Missing required value for argument: height"] if exists($args->{"height"}) && !defined($args->{"height"});
#        return [400, "Missing required value for argument: pattern"] if exists($args->{"pattern"}) && !defined($args->{"pattern"});
#        return [400, "Missing required value for argument: space_after"] if exists($args->{"space_after"}) && !defined($args->{"space_after"});
#        return [400, "Missing required value for argument: space_before"] if exists($args->{"space_before"}) && !defined($args->{"space_before"});
#        _pci_err([500, "Extraneous command-line argument(s): ".join(", ", @check_argv)]) if @check_argv;
#        [200];
#    } else { _pci_err([500, "Unknown subcommand1: $sc_name"]); }
#}
#1;
### Local/_pci_clean_json.pm ###
#sub _pci_clean_json { require Scalar::Util; require Clone::PP;  use feature 'state'; state $cleanser = sub {
#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 = Clone::PP::clone($e); redo } else { $e = 'CIRCULAR'; $ref = '' } }
#    elsif ($ref eq 'Cpanel::JSON::XS::Boolean') { $e = $e ? 1:0; $ref = '' }
#    elsif ($ref eq 'DateTime') { $e = $e->epoch; $ref = ref($e) }
#    elsif ($ref eq 'JSON::PP::Boolean') { $e = $e ? 1:0; $ref = '' }
#    elsif ($ref eq 'JSON::XS::Boolean') { $e = $e ? 1:0; $ref = '' }
#    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)) { my $reftype = Scalar::Util::reftype($e); $e = $reftype eq "HASH" ? {%{ $e }} : $reftype eq "ARRAY" ? [@{ $e }] : $reftype eq "SCALAR" ? \(my $copy = ${ $e }) : $reftype eq "CODE" ? sub { goto &{ $e } } :(die "Cannot unbless object with type $ref") }
#    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} = Clone::PP::clone($h->{$k}); redo } else { $h->{$k} = 'CIRCULAR'; $ref = '' } }
#    elsif ($ref eq 'Cpanel::JSON::XS::Boolean') { $h->{$k} = $h->{$k} ? 1:0; $ref = '' }
#    elsif ($ref eq 'DateTime') { $h->{$k} = $h->{$k}->epoch; $ref = ref($h->{$k}) }
#    elsif ($ref eq 'JSON::PP::Boolean') { $h->{$k} = $h->{$k} ? 1:0; $ref = '' }
#    elsif ($ref eq 'JSON::XS::Boolean') { $h->{$k} = $h->{$k} ? 1:0; $ref = '' }
#    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})) { my $reftype = Scalar::Util::reftype($h->{$k}); $h->{$k} = $reftype eq "HASH" ? {%{ $h->{$k} }} : $reftype eq "ARRAY" ? [@{ $h->{$k} }] : $reftype eq "SCALAR" ? \(my $copy = ${ $h->{$k} }) : $reftype eq "CODE" ? sub { goto &{ $h->{$k} } } :(die "Cannot unbless object with type $ref") }
#    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) { $_ = Clone::PP::clone($_); redo } else { $_ = 'CIRCULAR'; $ref = '' } }
#    elsif ($ref eq 'Cpanel::JSON::XS::Boolean') { $_ = $_ ? 1:0; $ref = '' }
#    elsif ($ref eq 'DateTime') { $_ = $_->epoch; $ref = ref($_) }
#    elsif ($ref eq 'JSON::PP::Boolean') { $_ = $_ ? 1:0; $ref = '' }
#    elsif ($ref eq 'JSON::XS::Boolean') { $_ = $_ ? 1:0; $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($_)) { my $reftype = Scalar::Util::reftype($_); $_ = $reftype eq "HASH" ? {%{ $_ }} : $reftype eq "ARRAY" ? [@{ $_ }] : $reftype eq "SCALAR" ? \(my $copy = ${ $_ }) : $reftype eq "CODE" ? sub { goto &{ $_ } } :(die "Cannot unbless object with type $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;
### Scalar/Util/Numeric/PP.pm ###
#package Scalar::Util::Numeric::PP;
#
#our $DATE = '2016-01-22'; # DATE
#our $VERSION = '0.04'; # VERSION
#
#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;
## ABSTRACT: Pure-perl drop-in replacement/approximation of Scalar::Util::Numeric
#
#__END__
#
#=pod
#
#=encoding UTF-8
#
#=head1 NAME
#
#Scalar::Util::Numeric::PP - Pure-perl drop-in replacement/approximation of Scalar::Util::Numeric
#
#=head1 VERSION
#
#This document describes version 0.04 of Scalar::Util::Numeric::PP (from Perl distribution Scalar-Util-Numeric-PP), released on 2016-01-22.
#
#=head1 SYNOPSIS
#
#=head1 DESCRIPTION
#
#This module is written mainly for the convenience of L<Data::Sah>, as a drop-in
#pure-perl replacement for the XS module L<Scalar::Util::Numeric>, in the case
#when Data::Sah needs to generate code that uses PP modules instead of XS ones.
#
#Not all functions from Scalar::Util::Numeric have been provided.
#
#=head1 FUNCTIONS
#
#=head2 isint
#
#=head2 isfloat
#
#=head2 isnum
#
#=head2 isneg
#
#=head2 isinf
#
#=head2 isnan
#
#=head1 HOMEPAGE
#
#Please visit the project's homepage at L<https://metacpan.org/release/Scalar-Util-Numeric-PP>.
#
#=head1 SOURCE
#
#Source repository is at L<https://github.com/perlancar/perl-Scalar-Util-Numeric-PP>.
#
#=head1 BUGS
#
#Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Scalar-Util-Numeric-PP>
#
#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 SEE ALSO
#
#L<Data::Sah>
#
#L<Scalar::Util::Numeric>
#
#=head1 AUTHOR
#
#perlancar <perlancar@cpan.org>
#
#=head1 COPYRIGHT AND LICENSE
#
#This software is copyright (c) 2016 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
### begin code_after_end
### end code_after_end
