view release on metacpan or search on metacpan
script/gen-generic-ind-company-names view on Meta::CPAN
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;
# load modules
### declare global variables
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=>1,read_env=>1,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 = {
'config-path=s@' => sub { $_pci_r->{config_paths} //= []; push @{ $_pci_r->{config_paths} }, $_[1]; },
'config-profile=s' => sub { $_pci_r->{config_profile} = $_[1]; },
'format=s' => sub { $_pci_r->{format} = $_[1]; },
'help|h|?' => sub { print "gen-generic-ind-company-names - Generate nice-sounding, generic Indonesian company names\n\nUsage:\n gen-generic-ind-company-names --help (or -h, -?)\n gen-generic-ind-company-names --version (or -v)\n gen-generic-in...
'json' => sub { $_pci_r->{format} = (-t STDOUT) ? "json-pretty" : "json"; },
'naked-res' => sub { $_pci_r->{naked_res} = 1; },
'no-config' => sub { $_pci_r->{read_config} = 0; },
'no-env' => sub { $_pci_r->{read_env} = 0; },
'no-naked-res|nonaked-res' => sub { $_pci_r->{naked_res} = 0; },
'page-result:s' => sub { $_pci_r->{page_result} = 1; },
'version|v' => sub { no warnings 'once'; require Acme::ID::CompanyName; print "gen-generic-ind-company-names version ", "0.007", ($Acme::ID::CompanyName::DATE ? " ($Acme::ID::CompanyName::DATE)" : ''), "\n"; print " Generated by Perinci::CmdLine...
};
script/gen-generic-ind-company-names view on Meta::CPAN
#When summaries are not shown, user will just be seeing something like:
#
# -a
# -l
# --sort
#
#But when summaries are shown, user will see:
#
# -a -- Show hidden files
# -l -- Show details
# --sort -- Specify sort order
#
#which is quite helpful.
#
#=item * workaround_with_wordbreaks
#
#Boolean. Default is true. See source code for more details.
#
#=back
#
#
#=back
#
#Return value: Formatted string (or array, if `as` is set to `array`) (str|array)
#
#
#
#=head2 join_wordbreak_words
#
#Usage:
#
# join_wordbreak_words() -> [status, msg, payload, meta]
#
#Post-process parse_cmdline() result by joining some words.
#
#C<parse_cmdline()>, like bash, splits some characters that are considered as
#word-breaking characters:
#
# "'@><=;|&(:
#
#So if command-line is:
#
# command --module=Data::Dump bob@example.org
#
#then they will be parsed as:
#
# ["command", "--module", "=", "Data", "::", "Dump", "bob", '@', "example.org"]
#
#Normally in Perl applications, we want C<:>, C<@> to be part of word. So this
#routine will convert the above into:
#
# ["command", "--module=Data::Dump", 'bob@example.org']
#
#This function is not exported by default, but exportable.
#
#No arguments.
#
#Returns an enveloped result (an array).
#
#First element (status) is an integer containing HTTP status code
#(200 means OK, 4xx caller error, 5xx function error). Second element
#(msg) is a string containing error message, or 'OK' if status is
#200. Third element (payload) is optional, the actual result. Fourth
#element (meta) is called result metadata and is optional, a hash
#that contains extra information.
#
#Return value: (any)
#
#
#
#=head2 parse_cmdline
#
#Usage:
#
# parse_cmdline($cmdline, $point, $opts) -> array
#
#Parse shell command-line for processing by completion routines.
#
#This function basically converts C<COMP_LINE> (str) and C<COMP_POINT> (int) into
#something like (but not exactly the same as) C<COMP_WORDS> (array) and
#C<COMP_CWORD> (int) that bash supplies to shell functions.
#
#The differences with bash are (these differences are mostly for parsing
#convenience for programs that use this routine; this comparison is made against
#bash versions 4.2-4.3):
#
#1) quotes and backslashes are stripped (bash's C<COMP_WORDS> contains all the
# quotes and backslashes);
#
#2) quoted phrase that contains spaces, or phrase that contains escaped spaces is
# parsed as a single word. For example:
#
# command "First argument" Second\ argument
#
# bash would split it as (represented as Perl):
#
# ["command", "\"First", "argument\"", "Second\\", "argument"]
#
# which is not very convenient. We parse it into:
#
# ["command", "First argument", "Second argument"]
#
#3) variables are substituted with their values from environment variables except
# for the current word (C<COMP_WORDS[COMP_CWORD]>) (bash does not perform
# variable substitution for C<COMP_WORDS>). However, note that special shell
# variables that are not environment variables like C<$0>, C<$_>, C<$IFS> will not
# be replaced correctly because bash does not export those variables for us.
#
#4) tildes (C<~>) are expanded with user's home directory except for the current
# word (bash does not perform tilde expansion for C<COMP_WORDS>);
#
#Caveats:
#
#=over
#
#=item * Like bash, we group non-whitespace word-breaking characters into its own word.
#By default C<COMP_WORDBREAKS> is:
#
#"'@><=;|&(:
#
#So if raw command-line is:
#
script/gen-generic-ind-company-names view on Meta::CPAN
#Other modules related to bash shell tab completion: L<Bash::Completion>,
#L<Getopt::Complete>, L<Term::Bash::Completion::Generator>.
#
#Programmable Completion section in Bash manual:
#L<https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html>
#
#=head1 AUTHOR
#
#perlancar <perlancar@cpan.org>
#
#=head1 COPYRIGHT AND LICENSE
#
#This software is copyright (c) 2020, 2019, 2018, 2016, 2015, 2014 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
### Config/IOD/Base.pm ###
#package Config::IOD::Base;
#
#our $DATE = '2019-01-17'; # DATE
#our $VERSION = '0.342'; # VERSION
#
#use 5.010001;
#use strict;
#use warnings;
##use Carp; # avoided to shave a bit of startup time
#
#use constant +{
# COL_V_ENCODING => 0, # either "!j"... or '"', '[', '{', '~'
# COL_V_WS1 => 1,
# COL_V_VALUE => 2,
# COL_V_WS2 => 3,
# COL_V_COMMENT_CHAR => 4,
# COL_V_COMMENT => 5,
#};
#
#sub new {
# my ($class, %attrs) = @_;
# $attrs{default_section} //= 'GLOBAL';
# $attrs{allow_bang_only} //= 1;
# $attrs{allow_duplicate_key} //= 1;
# $attrs{enable_directive} //= 1;
# $attrs{enable_encoding} //= 1;
# $attrs{enable_quoting} //= 1;
# $attrs{enable_bracket} //= 1;
# $attrs{enable_brace} //= 1;
# $attrs{enable_tilde} //= 1;
# $attrs{enable_expr} //= 0;
# $attrs{expr_vars} //= {};
# $attrs{ignore_unknown_directive} //= 0;
# # allow_encodings
# # disallow_encodings
# # allow_directives
# # disallow_directives
# bless \%attrs, $class;
#}
#
## borrowed from Parse::CommandLine. differences: returns arrayref. return undef
## on error (instead of dying).
#sub _parse_command_line {
# my ($self, $str) = @_;
#
# $str =~ s/\A\s+//ms;
# $str =~ s/\s+\z//ms;
#
# my @argv;
# my $buf;
# my $escaped;
# my $double_quoted;
# my $single_quoted;
#
# for my $char (split //, $str) {
# if ($escaped) {
# $buf .= $char;
# $escaped = undef;
# next;
# }
#
# if ($char eq '\\') {
# if ($single_quoted) {
# $buf .= $char;
# }
# else {
# $escaped = 1;
# }
# next;
# }
#
# if ($char =~ /\s/) {
# if ($single_quoted || $double_quoted) {
# $buf .= $char;
# }
# else {
# push @argv, $buf if defined $buf;
# undef $buf;
# }
# next;
# }
#
# if ($char eq '"') {
# if ($single_quoted) {
# $buf .= $char;
# next;
# }
# $double_quoted = !$double_quoted;
# next;
# }
#
# if ($char eq "'") {
# if ($double_quoted) {
# $buf .= $char;
# next;
# }
# $single_quoted = !$single_quoted;
# next;
# }
#
# $buf .= $char;
# }
script/gen-generic-ind-company-names view on Meta::CPAN
#
#And the result will be:
#
# {
# section1 => {foo=>1, bar=>"monkey"},
# section2 => {baz=>2, qux=>"greasemonkey", quux=>"greasemonkey 2"},
# }
#
#For safety, you'll need to set C<enable_expr> attribute to 1 first to enable
#this feature.
#
#The syntax of the expression (the C<expr> encoding) is not officially specified
#yet in the L<IOD> specification. It will probably be Expr (see
#L<Language::Expr::Manual::Syntax>). At the moment, this module implements a very
#limited subset that is compatible (lowest common denominator) with Perl syntax
#and uses C<eval()> to evaluate the expression. However, only the limited subset
#is allowed (checked by Perl 5.10 regular expression).
#
#The supported terms:
#
# number
# string (double-quoted and single-quoted)
# undef literal
# simple variable ($abc, no namespace, no array/hash sigil, no special variables)
# function call (only the 'val' function is supported)
# grouping (parenthesis)
#
#The supported operators are:
#
# + - .
# * / % x
# **
# unary -, unary +, !, ~
#
#The C<val()> function refers to the configuration key. If the argument contains
#".", it will be assumed as C<SECTIONNAME.KEYNAME>, otherwise it will access the
#current section's key. Since parsing is done in a single pass, you can only
#refer to the already mentioned key.
#
#Code will be compiled using Perl's C<eval()> in the
#C<Config::IOD::Expr::_Compiled> namespace, with C<no strict>, C<no warnings>.
#
#=for END_BLOCK: expression
#
#=head1 ATTRIBUTES
#
#=for BEGIN_BLOCK: attributes
#
#=head2 default_section => str (default: C<GLOBAL>)
#
#If a key line is specified before any section line, this is the section that the
#key will be put in.
#
#=head2 enable_directive => bool (default: 1)
#
#If set to false, then directives will not be parsed. Lines such as below will be
#considered a regular comment:
#
# ;!include foo.ini
#
#and lines such as below will be considered a syntax error (B<regardless> of the
#C<allow_bang_only> setting):
#
# !include foo.ini
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_encoding => bool (default: 1)
#
#If set to false, then encoding notation will be ignored and key value will be
#parsed as verbatim. Example:
#
# name = !json null
#
#With C<enable_encoding> turned off, value will not be undef but will be string
#with the value of (as Perl literal) C<"!json null">.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_quoting => bool (default: 1)
#
#If set to false, then quotes on key value will be ignored and key value will be
#parsed as verbatim. Example:
#
# name = "line 1\nline2"
#
#With C<enable_quoting> turned off, value will not be a two-line string, but will
#be a one line string with the value of (as Perl literal) C<"line 1\\nline2">.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_bracket => bool (default: 1)
#
#If set to false, then JSON literal array will be parsed as verbatim. Example:
#
# name = [1,2,3]
#
#With C<enable_bracket> turned off, value will not be a three-element array, but
#will be a string with the value of (as Perl literal) C<"[1,2,3]">.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_brace => bool (default: 1)
#
#If set to false, then JSON literal object (hash) will be parsed as verbatim.
#Example:
#
# name = {"a":1,"b":2}
#
#With C<enable_brace> turned off, value will not be a hash with two pairs, but
#will be a string with the value of (as Perl literal) C<'{"a":1,"b":2}'>.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_tilde => bool (default: 1)
#
#If set to true (the default), then value that starts with C<~> (tilde) will be
#assumed to use !path encoding, unless an explicit encoding has been otherwise
#specified.
#
#Example:
script/gen-generic-ind-company-names view on Meta::CPAN
#
#If defined, directives listed here are not allowed. Note that if
#C<allow_directives> is also set, a directive must also be in that list.
#
#=head2 allow_bang_only => bool (default: 1)
#
#Since the mistake of specifying a directive like this:
#
# !foo
#
#instead of the correct:
#
# ;!foo
#
#is very common, the spec allows it. This reader, however, can be configured to
#be more strict.
#
#=head2 allow_duplicate_key => bool (default: 1)
#
#If set to 0, you can forbid duplicate key, e.g.:
#
# [section]
# a=1
# a=2
#
#or:
#
# [section]
# a=1
# b=2
# c=3
# a=10
#
#In traditional INI file, to specify an array you specify multiple keys. But when
#there is only a single key, it is unclear if the value is a single-element array
#or a scalar. You can use this setting to avoid this array/scalar ambiguity in
#config file and force user to use JSON encoding or bracket to specify array:
#
# [section]
# a=[1,2]
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 ignore_unknown_directive => bool (default: 0)
#
#If set to true, will not die if an unknown directive is encountered. It will
#simply be ignored as a regular comment.
#
#B<NOTE: Turning this setting on violates IOD specification.>
#
#=for END_BLOCK: attributes
#
#=head1 METHODS
#
#=for BEGIN_BLOCK: methods
#
#=head2 new(%attrs) => obj
#
#=head2 $reader->read_file($filename)
#
#Read IOD configuration from a file. Die on errors.
#
#=head2 $reader->read_string($str)
#
#Read IOD configuration from a string. Die on errors.
#
#=head1 HOMEPAGE
#
#Please visit the project's homepage at L<https://metacpan.org/release/Config-IOD-Reader>.
#
#=head1 SOURCE
#
#Source repository is at L<https://github.com/perlancar/perl-Config-IOD-Reader>.
#
#=head1 BUGS
#
#Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Config-IOD-Reader>
#
#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) 2019, 2018, 2017, 2016, 2015, 2014 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
### Config/IOD/Reader.pm ###
#package Config::IOD::Reader;
#
#our $DATE = '2019-01-17'; # DATE
#our $VERSION = '0.342'; # VERSION
#
#use 5.010001;
#use strict;
#use warnings;
#
#use parent qw(Config::IOD::Base);
#
#sub _merge {
# my ($self, $section) = @_;
#
# my $res = $self->{_res};
# for my $msect (@{ $self->{_merge} }) {
# if ($msect eq $section) {
# # ignore merging self
# next;
# #local $self->{_linum} = $self->{_linum}-1;
# #$self->_err("Can't merge section '$msect' to '$section': ".
# # "Same section");
# }
# if (!exists($res->{$msect})) {
# local $self->{_linum} = $self->{_linum}-1;
# $self->_err("Can't merge section '$msect' to '$section': ".
# "Section '$msect' not seen yet");
# }
# for my $k (keys %{ $res->{$msect} }) {
# $res->{$section}{$k} //= $res->{$msect}{$k};
script/gen-generic-ind-company-names view on Meta::CPAN
# [section2]
# baz =!e 1+1
# qux =!e "grease" . val("section1.bar")
# quux=!e val("qux") . " " . val('baz')
#
#And the result will be:
#
# {
# section1 => {foo=>1, bar=>"monkey"},
# section2 => {baz=>2, qux=>"greasemonkey", quux=>"greasemonkey 2"},
# }
#
#For safety, you'll need to set C<enable_expr> attribute to 1 first to enable
#this feature.
#
#The syntax of the expression (the C<expr> encoding) is not officially specified
#yet in the L<IOD> specification. It will probably be Expr (see
#L<Language::Expr::Manual::Syntax>). At the moment, this module implements a very
#limited subset that is compatible (lowest common denominator) with Perl syntax
#and uses C<eval()> to evaluate the expression. However, only the limited subset
#is allowed (checked by Perl 5.10 regular expression).
#
#The supported terms:
#
# number
# string (double-quoted and single-quoted)
# undef literal
# simple variable ($abc, no namespace, no array/hash sigil, no special variables)
# function call (only the 'val' function is supported)
# grouping (parenthesis)
#
#The supported operators are:
#
# + - .
# * / % x
# **
# unary -, unary +, !, ~
#
#The C<val()> function refers to the configuration key. If the argument contains
#".", it will be assumed as C<SECTIONNAME.KEYNAME>, otherwise it will access the
#current section's key. Since parsing is done in a single pass, you can only
#refer to the already mentioned key.
#
#Code will be compiled using Perl's C<eval()> in the
#C<Config::IOD::Expr::_Compiled> namespace, with C<no strict>, C<no warnings>.
#
#=head1 ATTRIBUTES
#
#=head2 default_section => str (default: C<GLOBAL>)
#
#If a key line is specified before any section line, this is the section that the
#key will be put in.
#
#=head2 enable_directive => bool (default: 1)
#
#If set to false, then directives will not be parsed. Lines such as below will be
#considered a regular comment:
#
# ;!include foo.ini
#
#and lines such as below will be considered a syntax error (B<regardless> of the
#C<allow_bang_only> setting):
#
# !include foo.ini
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_encoding => bool (default: 1)
#
#If set to false, then encoding notation will be ignored and key value will be
#parsed as verbatim. Example:
#
# name = !json null
#
#With C<enable_encoding> turned off, value will not be undef but will be string
#with the value of (as Perl literal) C<"!json null">.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_quoting => bool (default: 1)
#
#If set to false, then quotes on key value will be ignored and key value will be
#parsed as verbatim. Example:
#
# name = "line 1\nline2"
#
#With C<enable_quoting> turned off, value will not be a two-line string, but will
#be a one line string with the value of (as Perl literal) C<"line 1\\nline2">.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_bracket => bool (default: 1)
#
#If set to false, then JSON literal array will be parsed as verbatim. Example:
#
# name = [1,2,3]
#
#With C<enable_bracket> turned off, value will not be a three-element array, but
#will be a string with the value of (as Perl literal) C<"[1,2,3]">.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_brace => bool (default: 1)
#
#If set to false, then JSON literal object (hash) will be parsed as verbatim.
#Example:
#
# name = {"a":1,"b":2}
#
#With C<enable_brace> turned off, value will not be a hash with two pairs, but
#will be a string with the value of (as Perl literal) C<'{"a":1,"b":2}'>.
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 enable_tilde => bool (default: 1)
#
#If set to true (the default), then value that starts with C<~> (tilde) will be
#assumed to use !path encoding, unless an explicit encoding has been otherwise
#specified.
#
#Example:
script/gen-generic-ind-company-names view on Meta::CPAN
#If defined, only directives listed here are allowed. Note that if
#C<disallow_directives> is also set, a directive must also not be in that list.
#
#=head2 disallow_directives => array
#
#If defined, directives listed here are not allowed. Note that if
#C<allow_directives> is also set, a directive must also be in that list.
#
#=head2 allow_bang_only => bool (default: 1)
#
#Since the mistake of specifying a directive like this:
#
# !foo
#
#instead of the correct:
#
# ;!foo
#
#is very common, the spec allows it. This reader, however, can be configured to
#be more strict.
#
#=head2 allow_duplicate_key => bool (default: 1)
#
#If set to 0, you can forbid duplicate key, e.g.:
#
# [section]
# a=1
# a=2
#
#or:
#
# [section]
# a=1
# b=2
# c=3
# a=10
#
#In traditional INI file, to specify an array you specify multiple keys. But when
#there is only a single key, it is unclear if the value is a single-element array
#or a scalar. You can use this setting to avoid this array/scalar ambiguity in
#config file and force user to use JSON encoding or bracket to specify array:
#
# [section]
# a=[1,2]
#
#B<NOTE: Turning this setting off violates IOD specification.>
#
#=head2 ignore_unknown_directive => bool (default: 0)
#
#If set to true, will not die if an unknown directive is encountered. It will
#simply be ignored as a regular comment.
#
#B<NOTE: Turning this setting on violates IOD specification.>
#
#=head1 METHODS
#
#=head2 new(%attrs) => obj
#
#=head2 $reader->read_file($filename[ , $callback ]) => hash
#
#Read IOD configuration from a file. Die on errors.
#
#See C<read_string> for more information on C<$callback> argument.
#
#=head2 $reader->read_string($str[ , $callback ]) => hash
#
#Read IOD configuration from a string. Die on errors.
#
#C<$callback> is an optional coderef argument that will be called during various
#stages. It can be useful if you want more information (especially ordering). It
#will be called with hash argument C<%args>
#
#=over
#
#=item * Found a directive line
#
#Arguments passed: C<event> (str, has the value of 'directive'), C<linum> (int,
#line number, starts from 1), C<line> (str, raw line), C<directive> (str,
#directive name), C<cur_section> (str, current section name), C<args> (array,
#directive arguments).
#
#=item * Found a comment line
#
#Arguments passed: C<event> (str, 'comment'), C<linum>, C<line>, C<cur_section>.
#
#=item * Found a section line
#
#Arguments passed: C<event> (str, 'section'), C<linum>, C<line>, C<cur_section>,
#C<section> (str, section name).
#
#=item * Found a key line
#
#Arguments passed: C<event> (str, 'section'), C<linum>, C<line>, C<cur_section>,
#C<key> (str, key name), C<val> (any, value name, already decoded if encoded),
#C<raw_val> (str, raw value).
#
#=back
#
#TODO: callback when there is merging.
#
#=head1 HOMEPAGE
#
#Please visit the project's homepage at L<https://metacpan.org/release/Config-IOD-Reader>.
#
#=head1 SOURCE
#
#Source repository is at L<https://github.com/perlancar/perl-Config-IOD-Reader>.
#
#=head1 BUGS
#
#Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Config-IOD-Reader>
#
#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<IOD> - specification
#
#L<Config::IOD> - round-trip parser for reading as well as writing IOD documents
#
#L<IOD::Examples> - sample documents
#
#=head1 AUTHOR
#
#perlancar <perlancar@cpan.org>
script/gen-generic-ind-company-names view on Meta::CPAN
#
#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/Sah/Normalize.pm ###
#package Data::Sah::Normalize;
#
#use 5.010001;
#use strict;
#use warnings;
#
#our $DATE = '2018-09-10'; # DATE
#our $VERSION = '0.050'; # VERSION
#
#require Exporter;
#our @ISA = qw(Exporter);
#our @EXPORT_OK = qw(
# normalize_clset
# normalize_schema
#
# $type_re
# $clause_name_re
# $clause_re
# $attr_re
# $funcset_re
# $compiler_re
# );
#
#our $type_re = qr/\A(?:[A-Za-z_]\w*::)*[A-Za-z_]\w*\z/;
#our $clause_name_re = qr/\A[A-Za-z_]\w*\z/;
#our $clause_re = qr/\A[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*\z/;
#our $attr_re = $clause_re;
#our $funcset_re = qr/\A(?:[A-Za-z_]\w*::)*[A-Za-z_]\w*\z/;
#our $compiler_re = qr/\A[A-Za-z_]\w*\z/;
#our $clause_attr_on_empty_clause_re = qr/\A(?:\.[A-Za-z_]\w*)+\z/;
#
#sub normalize_clset($;$) {
# my ($clset0, $opts) = @_;
# $opts //= {};
#
# my $clset = {};
# for my $c (sort keys %$clset0) {
# my $c0 = $c;
#
# my $v = $clset0->{$c};
#
# # ignore expression
# my $expr;
# if ($c =~ s/=\z//) {
# $expr++;
# # XXX currently can't disregard merge prefix when checking
# # conflict
# die "Conflict between '$c=' and '$c'" if exists $clset0->{$c};
# $clset->{"$c.is_expr"} = 1;
# }
#
# my $sc = "";
# my $cn;
# {
# my $errp = "Invalid clause name syntax '$c0'"; # error prefix
# if (!$expr && $c =~ s/\A!(?=.)//) {
# die "$errp, syntax should be !CLAUSE"
# unless $c =~ $clause_name_re;
# $sc = "!";
# } elsif (!$expr && $c =~ s/(?<=.)\|\z//) {
# die "$errp, syntax should be CLAUSE|"
# unless $c =~ $clause_name_re;
# $sc = "|";
# } elsif (!$expr && $c =~ s/(?<=.)\&\z//) {
# die "$errp, syntax should be CLAUSE&"
# unless $c =~ $clause_name_re;
# $sc = "&";
# } elsif (!$expr && $c =~ /\A([^.]+)(?:\.(.+))?\((\w+)\)\z/) {
# my ($c2, $a, $lang) = ($1, $2, $3);
# die "$errp, syntax should be CLAUSE(LANG) or C.ATTR(LANG)"
# unless $c2 =~ $clause_name_re &&
# (!defined($a) || $a =~ $attr_re);
# $sc = "(LANG)";
# $cn = $c2 . (defined($a) ? ".$a" : "") . ".alt.lang.$lang";
# } elsif ($c !~ $clause_re &&
# $c !~ $clause_attr_on_empty_clause_re) {
# die "$errp, please use letter/digit/underscore only";
# }
# }
#
# # XXX can't disregard merge prefix when checking conflict
# if ($sc eq '!') {
# die "Conflict between clause shortcuts '!$c' and '$c'"
# if exists $clset0->{$c};
# die "Conflict between clause shortcuts '!$c' and '$c|'"
# if exists $clset0->{"$c|"};
# die "Conflict between clause shortcuts '!$c' and '$c&'"
# if exists $clset0->{"$c&"};
# $clset->{$c} = $v;
# $clset->{"$c.op"} = "not";
# } elsif ($sc eq '&') {
# die "Conflict between clause shortcuts '$c&' and '$c'"
# if exists $clset0->{$c};
# die "Conflict between clause shortcuts '$c&' and '$c|'"
# if exists $clset0->{"$c|"};
# die "Clause 'c&' value must be an array"
# unless ref($v) eq 'ARRAY';
# $clset->{$c} = $v;
# $clset->{"$c.op"} = "and";
# } elsif ($sc eq '|') {
# die "Conflict between clause shortcuts '$c|' and '$c'"
# if exists $clset0->{$c};
# die "Clause 'c|' value must be an array"
# unless ref($v) eq 'ARRAY';
# $clset->{$c} = $v;
# $clset->{"$c.op"} = "or";
# } elsif ($sc eq '(LANG)') {
# die "Conflict between clause '$c' and '$cn'"
# if exists $clset0->{$cn};
# $clset->{$cn} = $v;
# } else {
# $clset->{$c} = $v;
# }
#
# }
script/gen-generic-ind-company-names view on Meta::CPAN
#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>.
script/gen-generic-ind-company-names view on Meta::CPAN
# 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 "...
# 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 "...
# 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;
### Log/ger.pm ###
#package Log::ger;
#
#our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
#our $DATE = '2021-01-31'; # DATE
#our $DIST = 'Log-ger'; # DIST
#our $VERSION = '0.038'; # VERSION
#
##IFUNBUILT
## use strict 'subs', 'vars';
## use warnings;
##END IFUNBUILT
#
#our $re_addr = qr/\(0x([0-9a-f]+)/o;
#
#our %Levels = (
# fatal => 10,
# error => 20,
# warn => 30,
# info => 40,
# debug => 50,
# trace => 60,
#);
#
#our %Level_Aliases = (
# off => 0,
# warning => 30,
#);
#
#our $Current_Level = 30;
#
#our $Caller_Depth_Offset = 0;
#
## a flag that can be used by null output to skip using formatter
#our $_outputter_is_null;
#
#our $_dumper;
#
#our %Global_Hooks;
#
## in Log/ger/Heavy.pm
## our %Default_Hooks = (
#
#our %Package_Targets; # key = package name, value = \%per_target_conf
#our %Per_Package_Hooks; # key = package name, value = { phase => hooks, ... }
#
#our %Hash_Targets; # key = hash address, value = [$hashref, \%per_target_conf]
#our %Per_Hash_Hooks; # key = hash address, value = { phase => hooks, ... }
#
#our %Object_Targets; # key = object address, value = [$obj, \%per_target_conf]
#our %Per_Object_Hooks; # key = object address, value = { phase => hooks, ... }
#
#my $sub0 = sub {0};
#my $sub1 = sub {1};
#my $default_null_routines;
#
#sub install_routines {
# my ($target, $target_arg, $routines, $name_routines) = @_;
#
# if ($name_routines && !defined &subname) {
# if (eval { require Sub::Name; 1 }) {
# *subname = \&Sub::Name::subname;
# } else {
# *subname = sub {};
# }
# }
#
# if ($target eq 'package') {
##IFUNBUILT
## no warnings 'redefine';
##END IFUNBUILT
# for my $r (@$routines) {
# my ($code, $name, $lnum, $type) = @$r;
# next unless $type =~ /_sub\z/;
# #print "D:installing $name to package $target_arg\n";
# *{"$target_arg\::$name"} = $code;
# subname("$target_arg\::$name", $code) if $name_routines;
# }
script/gen-generic-ind-company-names view on Meta::CPAN
# if (keys %Global_Hooks) {
# require Log::ger::Heavy;
# init_target(object => $obj, \%per_target_conf);
# } else {
# # if we haven't added any hooks etc, skip init_target() process and use
# # this preconstructed routines as shortcut, to save startup overhead
# _set_default_null_routines();
# install_routines(object => $obj, $default_null_routines, 0);
# }
# $obj; # XXX add DESTROY to remove from list of targets
#}
#
#sub _import_to {
# my ($package, $target_pkg, %per_target_conf) = @_;
#
# $per_target_conf{category} = $target_pkg
# if !defined($per_target_conf{category});
# add_target(package => $target_pkg, \%per_target_conf);
# if (keys %Global_Hooks) {
# require Log::ger::Heavy;
# init_target(package => $target_pkg, \%per_target_conf);
# } else {
# # if we haven't added any hooks etc, skip init_target() process and use
# # this preconstructed routines as shortcut, to save startup overhead
# _set_default_null_routines();
# install_routines(package => $target_pkg, $default_null_routines, 0);
# }
#}
#
#sub import {
# my ($package, %per_target_conf) = @_;
#
# my $caller = caller(0);
# $package->_import_to($caller, %per_target_conf);
#}
#
#1;
## ABSTRACT: A lightweight, flexible logging framework
#
#__END__
#
#=pod
#
#=encoding UTF-8
#
#=head1 NAME
#
#Log::ger - A lightweight, flexible logging framework
#
#=head1 VERSION
#
#version 0.038
#
#=head1 SYNOPSIS
#
#=head2 Producing logs
#
#In your module (producer):
#
# package Foo;
# use Log::ger; # will install some logger routines e.g. log_warn, log_error
#
# sub foo {
# ...
# # produce some logs. no need to configure output or level.
# log_error "an error occured: %03d - %s", $errcode, $errmsg;
# ...
# log_debug "http response: %s", $http; # automatic dumping of data
# }
# 1;
#
#=head2 Consuming logs
#
#=head3 Choosing an output
#
#In your application (consumer/listener):
#
# use Foo;
# use Log::ger::Output 'Screen'; # configure output
# # level is by default 'warn'
# foo(); # the error message is shown, but debug message is not.
#
#=head3 Choosing multiple outputs
#
#Instead of screen, you can output to multiple outputs (including multiple
#files):
#
# use Log::ger::Output 'Composite' => (
# outputs => {
# Screen => {},
# File => [
# {conf=>{path=>'/path/to/app.log'}},
# ...
# ],
# ...
# },
# );
#
#See L<Log::ger::Manual::Tutorial::481_Output_Composite> for more examples.
#
#=head3 Choosing level
#
#One way to set level:
#
# use Log::ger::Util;
# Log::ger::Util::set_level('debug'); # be more verbose
# foo(); # the error message as well as debug message are now shown
#
#There are better ways, e.g. letting users configure log level via configuration
#file or command-line option. See L<Log::ger::Manual::Tutorial::300_Level> for
#more details.
#
#=head1 DESCRIPTION
#
#Log::ger is yet another logging framework with the following features:
#
#=over
#
#=item * Separation of producers and consumers/listeners
#
#Like L<Log::Any>, this offers a very easy way for modules to produce some logs
#without having to configure anything. Configuring output, level, etc can be done
#in the application as log consumers/listeners. To read more about this, see the
#documentation of L<Log::Any> or L<Log::ger::Manual> (but nevertheless see
#L<Log::ger::Manual> on why you might prefer Log::ger to Log::Any).
#
#=item * Lightweight and fast
#
#B<Slim distribution.> No non-core dependencies, extra functionalities are
#provided in separate distributions to be pulled as needed.
#
#B<Low startup overhead.> Only ~0.5-1ms. For comparison, L<strict> ~0.2-0.5ms,
#L<warnings> ~2ms, L<Log::Any> (v0.15) ~2-3ms, Log::Any (v1.049) ~8-10ms,
#L<Log::Log4perl> ~35ms. This is measured on a 2014-2015 PC and before doing any
#output configuration. I strive to make C<use Log::ger;> statement to be roughly
#as light as C<use strict;> or C<use warnings;> so the impact of adding the
#statement is really minimal and you can just add logging without much thought to
#most of your modules. This is important to me because I want logging to be
#pervasive.
#
#To test for yourself, try e.g. with L<bencher-code>:
#
# % bencher-code 'use Log::ger' 'use Log::Any' --startup
#
#B<Fast>. Low null-/stealth-logging overhead, about 1.5x faster than Log::Any, 3x
#faster than Log4perl, 5x faster than L<Log::Fast>, ~40x faster than
#L<Log::Contextual>, and ~100x faster than L<Log::Dispatch>.
#
#For more benchmarks, see L<Bencher::Scenarios::LogGer>.
#
#B<Conditional compilation.> There is a plugin to optimize away unneeded logging
#statements, like assertion/conditional compilation, so they have zero runtime
#performance cost. See L<Log::ger::Plugin::OptAway>.
#
#Being lightweight means the module can be used more universally, from CLI to
#long-running daemons to inside routines with tight loops.
#
#=item * Flexible
#
#B<Customizable levels and routine/method names.> Can be used in a procedural or
#OO style. Log::ger can mimic the interface of L<Log::Any>, L<Log::Contextual>,
#L<Log::Log4perl>, or some other popular logging frameworks, to ease migration or
#adjust with your personal style.
#
#B<Per-package settings.> Each importer package can use its own format/layout,
#output. For example, a module that is migrated from Log::Any uses Log::Any-style
#logging, while another uses native Log::ger style, and yet some other uses block
script/gen-generic-ind-company-names view on Meta::CPAN
#will be set by parameters in C<[plugin=...]> sections in C<config>. For example,
#with this configuration:
#
# arg1=val1
# arg2=val2
# -special_arg1=val3
# -special_arg2=val4
#
# [plugin=DumpArgs]
# -event=before_validation
#
# [plugin=Foo]
# arg1=val1
#
#C<args> will become:
#
# {
# arg1=>"val1",
# arg2=>"val2",
# -special_arg1=>"val3",
# -special_arg2=>"val4",
# }
#
#and C<plugins> will become:
#
# [
# 'DumpArgs@before_validation' => {},
# Foo => {arg1=>val},
# ]
#
#This function is not exported by default, but exportable.
#
#Arguments ('*' denotes required arguments):
#
#=over 4
#
#=item * B<args> => I<hash>
#
#=item * B<common_opts> => I<any>
#
#=item * B<config> => I<any>
#
#=item * B<config_profile> => I<any>
#
#=item * B<meta> => I<any>
#
#=item * B<meta_is_normalized> => I<any>
#
#=item * B<plugins> => I<array>
#
#=item * B<r> => I<any>
#
#=item * B<subcommand_name> => I<any>
#
#
#=back
#
#Returns an enveloped result (an array).
#
#First element (status) is an integer containing HTTP status code
#(200 means OK, 4xx caller error, 5xx function error). Second element
#(msg) is a string containing error message, or 'OK' if status is
#200. Third element (payload) is optional, the actual result. Fourth
#element (meta) is called result metadata and is optional, a hash
#that contains extra information.
#
#Return value: (any)
#
#
#
#=head2 get_default_config_dirs
#
#Usage:
#
# get_default_config_dirs() -> [status, msg, payload, meta]
#
#This function is not exported by default, but exportable.
#
#No arguments.
#
#Returns an enveloped result (an array).
#
#First element (status) is an integer containing HTTP status code
#(200 means OK, 4xx caller error, 5xx function error). Second element
#(msg) is a string containing error message, or 'OK' if status is
#200. Third element (payload) is optional, the actual result. Fourth
#element (meta) is called result metadata and is optional, a hash
#that contains extra information.
#
#Return value: (any)
#
#
#
#=head2 read_config
#
#Usage:
#
# read_config(%args) -> [status, msg, payload, meta]
#
#This function is not exported by default, but exportable.
#
#Arguments ('*' denotes required arguments):
#
#=over 4
#
#=item * B<config_dirs> => I<any>
#
#=item * B<config_filename> => I<any>
#
#=item * B<config_paths> => I<any>
#
#=item * B<hook_section> => I<any>
#
#=item * B<program_name> => I<any>
#
#
#=back
#
#Returns an enveloped result (an array).
#
#First element (status) is an integer containing HTTP status code
#(200 means OK, 4xx caller error, 5xx function error). Second element
#(msg) is a string containing error message, or 'OK' if status is
#200. Third element (payload) is optional, the actual result. Fourth
#element (meta) is called result metadata and is optional, a hash
#that contains extra information.
#
#Return value: (any)
#
#=head1 HOMEPAGE
#
#Please visit the project's homepage at L<https://metacpan.org/release/Perinci-CmdLine-Util-Config>.
#
#=head1 SOURCE
#
#Source repository is at L<https://github.com/perlancar/perl-Perinci-CmdLine-Util-Config>.
#
#=head1 BUGS
#
#Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-CmdLine-Util-Config>
#
#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) 2020, 2019, 2018, 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
### Perinci/Result/Format/Lite.pm ###
#package Perinci::Result::Format::Lite;
#
#our $DATE = '2021-03-08'; # DATE
#our $VERSION = '0.279'; # VERSION
#
#use 5.010001;
##IFUNBUILT
## use strict;
## use warnings;
##END IFUNBUILT
#
#use List::Util qw(first max);
#
#use Exporter qw(import);
#our @EXPORT_OK = qw(format);
#
## copy-pasted from List::MoreUtils::PP
#sub firstidx (&@) {
# my $f = shift;
# foreach my $i ( 0 .. $#_ )
# {
# local *_ = \$_[$i];
# return $i if $f->();
# }
# return -1;
script/gen-generic-ind-company-names view on Meta::CPAN
#=cut
### Perinci/Sub/Normalize.pm ###
#package Perinci::Sub::Normalize;
#
#our $DATE = '2018-09-10'; # DATE
#our $VERSION = '0.200'; # VERSION
#
#use 5.010001;
#use strict;
#use warnings;
#
#require Exporter;
#our @ISA = qw(Exporter);
#our @EXPORT_OK = qw(
# normalize_function_metadata
# );
#
#sub _normalize{
# my ($meta, $ver, $opts, $proplist, $nmeta, $prefix, $modprefix) = @_;
#
# my $opt_aup = $opts->{allow_unknown_properties};
# my $opt_nss = $opts->{normalize_sah_schemas};
# my $opt_rip = $opts->{remove_internal_properties};
#
# if (defined $ver) {
# defined($meta->{v}) && $meta->{v} eq $ver
# or die "$prefix: Metadata version must be $ver";
# }
#
# KEY:
# for my $k (keys %$meta) {
# die "Invalid prop/attr syntax '$k', must be word/dotted-word only"
# unless $k =~ /\A(\w+)(?:\.(\w+(?:\.\w+)*))?(?:\((\w+)\))?\z/;
#
# my ($prop, $attr);
# if (defined $3) {
# $prop = $1;
# $attr = defined($2) ? "$2.alt.lang.$3" : "alt.lang.$3";
# } else {
# $prop = $1;
# $attr = $2;
# }
#
# my $nk = "$prop" . (defined($attr) ? ".$attr" : "");
#
# # strip property/attr started with _
# if ($prop =~ /\A_/ || defined($attr) && $attr =~ /\A_|\._/) {
# unless ($opt_rip) {
# $nmeta->{$nk} = $meta->{$k};
# }
# next KEY;
# }
#
# my $prop_proplist = $proplist->{$prop};
#
# # try to load module that declare new props first
# if (!$opt_aup && !$prop_proplist) {
# $modprefix //= $prefix;
# my $mod = "Perinci/Sub/Property$modprefix/$prop.pm";
# eval { require $mod };
# # hide technical error message from require()
# if ($@) {
# die "Unknown property '$prefix/$prop' (and couldn't ".
# "load property module '$mod'): $@" if $@;
# }
# $prop_proplist = $proplist->{$prop};
# }
# die "Unknown property '$prefix/$prop'"
# unless $opt_aup || $prop_proplist;
#
# if ($prop_proplist && $prop_proplist->{_prop}) {
# die "Property '$prefix/$prop' must be a hash"
# unless ref($meta->{$k}) eq 'HASH';
# $nmeta->{$nk} = {};
# _normalize(
# $meta->{$k},
# $prop_proplist->{_ver},
# $opts,
# $prop_proplist->{_prop},
# $nmeta->{$nk},
# "$prefix/$prop",
# );
# } elsif ($prop_proplist && $prop_proplist->{_elem_prop}) {
# die "Property '$prefix/$prop' must be an array"
# unless ref($meta->{$k}) eq 'ARRAY';
# $nmeta->{$nk} = [];
# my $i = 0;
# for (@{ $meta->{$k} }) {
# my $href = {};
# if (ref($_) eq 'HASH') {
# _normalize(
# $_,
# $prop_proplist->{_ver},
# $opts,
# $prop_proplist->{_elem_prop},
# $href,
# "$prefix/$prop/$i",
# );
# push @{ $nmeta->{$nk} }, $href;
# } else {
# push @{ $nmeta->{$nk} }, $_;
# }
# $i++;
# }
# } elsif ($prop_proplist && $prop_proplist->{_value_prop}) {
# die "Property '$prefix/$prop' must be a hash"
# unless ref($meta->{$k}) eq 'HASH';
# $nmeta->{$nk} = {};
# for (keys %{ $meta->{$k} }) {
# $nmeta->{$nk}{$_} = {};
# die "Property '$prefix/$prop/$_' must be a hash"
# unless ref($meta->{$k}{$_}) eq 'HASH';
# _normalize(
# $meta->{$k}{$_},
# $prop_proplist->{_ver},
# $opts,
# $prop_proplist->{_value_prop},
# $nmeta->{$nk}{$_},
# "$prefix/$prop/$_",
# ($prop eq 'args' ? "$prefix/arg" : undef),
# );
# }
# } else {
# if ($k eq 'schema' && $opt_nss) { # XXX currently hardcoded
# require Data::Sah::Normalize;
# $nmeta->{$nk} = Data::Sah::Normalize::normalize_schema(
# $meta->{$k});
# } else {
# $nmeta->{$nk} = $meta->{$k};
# }
# }
# }
#
# $nmeta;
#}
#
#sub normalize_function_metadata($;$) {
# my ($meta, $opts) = @_;
#
# $opts //= {};
#
# $opts->{allow_unknown_properties} //= 0;
# $opts->{normalize_sah_schemas} //= 1;
# $opts->{remove_internal_properties} //= 0;
#
# require Sah::Schema::rinci::function_meta;
# my $sch = $Sah::Schema::rinci::function_meta::schema;
# my $sch_proplist = $sch->[1]{_prop}
# or die "BUG: Rinci schema structure changed (1a)";
#
# _normalize($meta, 1.1, $opts, $sch_proplist, {}, '');
#}
#
#1;
## ABSTRACT: Normalize Rinci function metadata
#
#__END__
#
#=pod
#
#=encoding UTF-8
#
#=head1 NAME
#
#Perinci::Sub::Normalize - Normalize Rinci function metadata
#
#=head1 VERSION
#
#This document describes version 0.200 of Perinci::Sub::Normalize (from Perl distribution Perinci-Sub-Normalize), released on 2018-09-10.
#
#=head1 SYNOPSIS
#
# use Perinci::Sub::Normalize qw(normalize_function_metadata);
#
# my $nmeta = normalize_function_metadata($meta);
#
#=head1 FUNCTIONS
#
#=head2 normalize_function_metadata($meta[ , \%opts ]) => HASH
#
#Normalize and check L<Rinci> function metadata C<$meta>. Return normalized
#metadata, which is a shallow copy of C<$meta>. Die on error.
#
#Available options:
#
#=over
#
#=item * allow_unknown_properties => BOOL (default: 0)
#
#If set to true, will die if there are unknown properties.
#
#=item * normalize_sah_schemas => BOOL (default: 1)
#
#By default, L<Sah> schemas e.g. in C<result/schema> or C<args/*/schema> property
#is normalized using L<Data::Sah>'s C<normalize_schema>. Set this to 0 if you
#don't want this.
#
#=item * remove_internal_properties => BOOL (default: 0)
#
#If set to 1, all properties and attributes starting with underscore (C<_>) with
#will be stripped. According to L<DefHash> specification, they are ignored and
#usually contain notes/comments/extra information.
#
#=back
#
#=head1 HOMEPAGE
#
#Please visit the project's homepage at L<https://metacpan.org/release/Perinci-Sub-Normalize>.
#
#=head1 SOURCE
#
#Source repository is at L<https://github.com/perlancar/perl-Perinci-Sub-Normalize>.
#
#=head1 BUGS
#
#Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-Sub-Normalize>
#
#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<Rinci::function>
#
#=head1 AUTHOR
#
#perlancar <perlancar@cpan.org>
#
#=head1 COPYRIGHT AND LICENSE
#
#This software is copyright (c) 2018, 2016, 2015, 2014 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
### Sah/Schema/rinci/function_meta.pm ###
#package Sah::Schema::rinci::function_meta;
#
#our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
#our $DATE = '2020-09-23'; # DATE
script/gen-generic-ind-company-names view on Meta::CPAN
# deps => {
# _keys => {
# all => {},
# any => {},
# none => {},
# env => {},
# prog => {},
# pkg => {},
# func => {},
# code => {},
# tmp_dir => {},
# trash_dir => {},
# },
# },
# },
#
# examples => [
# {value=>{}, valid=>1},
# {
# value=>{v=>1.1, summary=>"Some function", args=>{a1=>{}, a2=>{}}},
# valid=>1,
# },
# # XXX we have not implemented property & attribute checking
# ],
#
#}, {}];
#
#$schema->[1]{_prop}{args}{_value_prop}{meta} = $schema->[1];
#$schema->[1]{_prop}{args}{_value_prop}{element_meta} = $schema->[1];
#
## just so the dzil plugin won't complain about schema not being normalized.
## because this is a circular structure and normalizing creates a shallow copy.
#
#$schema = Data::Sah::Normalize::normalize_schema($schema);
#
#1;
## ABSTRACT: Rinci function metadata
#
#__END__
#
#=pod
#
#=encoding UTF-8
#
#=head1 NAME
#
#Sah::Schema::rinci::function_meta - Rinci function metadata
#
#=head1 VERSION
#
#This document describes version 1.1.94.0 of Sah::Schema::rinci::function_meta (from Perl distribution Sah-Schemas-Rinci), released on 2020-09-23.
#
#=head1 SYNOPSIS
#
#To check data against this schema (requires L<Data::Sah>):
#
# use Data::Sah qw(gen_validator);
# my $validator = gen_validator("rinci::function_meta*");
# say $validator->($data) ? "valid" : "INVALID!";
#
# # Data::Sah can also create validator that returns nice error message string
# # and/or coerced value. Data::Sah can even create validator that targets other
# # language, like JavaScript. All from the same schema. See its documentation
# # for more details.
#
#To validate function parameters against this schema (requires L<Params::Sah>):
#
# use Params::Sah qw(gen_validator);
#
# sub myfunc {
# my @args = @_;
# state $validator = gen_validator("rinci::function_meta*");
# $validator->(\@args);
# ...
# }
#
#To specify schema in L<Rinci> function metadata and use the metadata with
#L<Perinci::CmdLine> to create a CLI:
#
# # in lib/MyApp.pm
# package MyApp;
# our %SPEC;
# $SPEC{myfunc} = {
# v => 1.1,
# summary => 'Routine to do blah ...',
# args => {
# arg1 => {
# summary => 'The blah blah argument',
# schema => ['rinci::function_meta*'],
# },
# ...
# },
# };
# sub myfunc {
# my %args = @_;
# ...
# }
# 1;
#
# # in myapp.pl
# package main;
# use Perinci::CmdLine::Any;
# Perinci::CmdLine::Any->new(url=>'MyApp::myfunc')->run;
#
# # in command-line
# % ./myapp.pl --help
# myapp - Routine to do blah ...
# ...
#
# % ./myapp.pl --version
#
# % ./myapp.pl --arg1 ...
#
#Sample data:
#
# {} # valid
#
# {args=>{a1=>{},a2=>{}},summary=>"Some function",v=>1.1} # valid
#
#=head1 HOMEPAGE
#
script/gen-generic-ind-company-names view on Meta::CPAN
#
#=head1 NAME
#
#Text::Table::Tiny - generate simple text tables from 2D arrays
#
#=head1 SYNOPSIS
#
# use Text::Table::Tiny 1.02 qw/ generate_table /;
#
# my $rows = [
# [qw/ Pokemon Type Count /],
# [qw/ Abra Psychic 5 /],
# [qw/ Ekans Poison 123 /],
# [qw/ Feraligatr Water 5678 /],
# ];
#
# print generate_table(rows => $rows, header_row => 1), "\n";
#
#
#=head1 DESCRIPTION
#
#This module provides a single function, C<generate_table>, which formats
#a two-dimensional array of data as a text table.
#It handles text that includes ANSI escape codes and wide Unicode characters.
#
#There are a number of options for adjusting the output format,
#but the intention is that the default option is good enough for most uses.
#
#The example shown in the SYNOPSIS generates the following table:
#
# +------------+---------+-------+
# | Pokemon | Type | Count |
# +------------+---------+-------+
# | Abra | Psychic | 5 |
# | Ekans | Poison | 123 |
# | Feraligatr | Water | 5678 |
# +------------+---------+-------+
#
#Support for wide characters was added in 1.02,
#so if you need that,
#you should specify that as your minimum required version,
#as per the SYNOPSIS.
#
#The interface changed with version 0.04,
#so if you use the C<generate_table()> function illustrated above,
#then you need to require at least version 0.04 of this module.
#
#Some of the options described below were added in version 1.00,
#so your best bet is to require at least version 1.00.
#
#
#=head2 generate_table()
#
#The C<generate_table> function understands a number of arguments,
#which are passed as a hash.
#The only required argument is B<rows>.
#Where arguments were not supported in the original release,
#the first supporting version is noted.
#
#If you pass an unknown argument,
#C<generate_table> will die with an error message.
#
#=over 4
#
#
#=item *
#
#rows
#
#Takes an array reference which should contain one or more rows
#of data, where each row is an array reference.
#
#
#=item *
#
#header_row
#
#If given a true value, the first row in the data will be interpreted
#as a header row, and separated from the rest of the table with a ruled line.
#
#
#=item *
#
#separate_rows
#
#If given a true value, a separator line will be drawn between every row in
#the table,
#and a thicker line will be used for the header separator.
#
#=item *
#
#top_and_tail
#
#If given a true value, then the top and bottom border lines will be skipped.
#This reduces the vertical height of the generated table.
#
#Added in 0.04.
#
#=item *
#
#align
#
#This takes an array ref with one entry per column,
#to specify the alignment of that column.
#Legal values are 'l', 'c', and 'r'.
#You can also specify a single alignment for all columns.
#ANSI escape codes are handled.
#
#Added in 1.00.
#
#=item *
#
#style
#
#Specifies the format of the output table.
#The default is C<'classic'>,
#but other options are C<'boxrule'> and C<'norule'>.
#
#If you use the C<boxrule> style,
#you'll probably need to run C<binmode(STDOUT, ':utf8')>.
#