Perinci-CmdLine-Lite
view release on metacpan or search on metacpan
lib/Perinci/CmdLine/Base.pm view on Meta::CPAN
)
||
# then order by pos
($posa <=> $posb)
||
# then by name
($a cmp $b)
} keys %$args_p) {
#log_trace("TMP: handle cmdline_src for arg=%s", $an);
my $as = $args_p->{$an};
my $src = $as->{cmdline_src};
my $type = $as->{schema}[0]
or die "BUG: No schema is defined for arg '$an'";
# Riap::HTTP currently does not support streaming input
my $do_stream = $as->{stream} && $url !~ /^https?:/;
if ($src) {
die [531,
"Invalid 'cmdline_src' value for argument '$an': $src"]
unless $src =~ /\A(stdin|file|stdin_or_files?|stdin_or_args|stdin_line)\z/;
die [531,
"Sorry, argument '$an' is set cmdline_src=$src, but type ".
"is not str/buf/array, only those are supported now"]
unless $do_stream || $type =~ /\A(str|buf|array)\z/; # XXX stdin_or_args needs array only, not str/buf
if ($src =~ /\A(stdin|stdin_or_files?|stdin_or_args)\z/) {
die [531, "Only one argument can be specified ".
"cmdline_src stdin/stdin_or_file/stdin_or_files/stdin_or_args"]
if $stdin_seen++;
}
my $is_ary = $type eq 'array';
if ($src eq 'stdin_line' && !exists($r->{args}{$an})) {
require Perinci::Object;
my $term_readkey_available = eval { require Term::ReadKey; 1 };
my $prompt = Perinci::Object::rimeta($as)->langprop('cmdline_prompt') //
sprintf($self->default_prompt_template, $an);
print $prompt;
my $iactive = is_interactive(*STDOUT);
Term::ReadKey::ReadMode('noecho')
if $term_readkey_available && $iactive && $as->{is_password};
chomp($r->{args}{$an} = <STDIN>);
do { print "\n"; Term::ReadKey::ReadMode(0) if $term_readkey_available }
if $iactive && $as->{is_password};
$r->{args}{"-cmdline_src_$an"} = 'stdin_line';
} elsif ($src eq 'stdin' || $src eq 'file' &&
($r->{args}{$an}//"") eq '-') {
die [400, "Argument $an must be set to '-' which means ".
"from stdin"]
if defined($r->{args}{$an}) &&
$r->{args}{$an} ne '-';
#log_trace("Getting argument '$an' value from stdin ...");
$r->{args}{$an} = $do_stream ?
__gen_iter(\*STDIN, $as, $an) :
$is_ary ? [<STDIN>] :
do {local $/; ~~<STDIN>};
$r->{args}{"-cmdline_src_$an"} = 'stdin';
} elsif ($src eq 'stdin_or_file' || $src eq 'stdin_or_files') {
# push back argument value to @ARGV so <> can work to slurp
# all the specified files
local @ARGV = @ARGV;
unshift @ARGV, $r->{args}{$an}
if defined $r->{args}{$an};
# with stdin_or_file, we only accept one file
splice @ARGV, 1
if @ARGV > 1 && $src eq 'stdin_or_file';
#log_trace("Getting argument '$an' value from ".
# "$src, \@ARGV=%s ...", \@ARGV);
# perl doesn't seem to check files, so we check it here
for (@ARGV) {
next if $_ eq '-';
die [500, "Can't read file '$_': $!"] if !(-r $_);
}
$r->{args}{"-cmdline_srcfilenames_$an"} = [@ARGV];
$r->{args}{$an} = $do_stream ?
__gen_iter(\*ARGV, $as, $an) :
$is_ary ? [<>] :
do {local $/; ~~<>};
$r->{args}{"-cmdline_src_$an"} = $src;
} elsif ($src eq 'stdin_or_args' && !is_interactive(*STDIN)) {
unless (defined($r->{args}{$an})) {
$r->{args}{$an} = $do_stream ?
__gen_iter(\*STDIN, $as, $an) :
$is_ary ? [map {chomp;$_} <STDIN>] :
do {local $/; ~~<STDIN>};
}
} elsif ($src eq 'file') {
unless (exists $r->{args}{$an}) {
if ($as->{req}) {
die [400,
"Please specify filename for argument '$an'"];
} else {
next;
}
}
die [400, "Please specify filename for argument '$an'"]
unless defined $r->{args}{$an};
#log_trace("Getting argument '$an' value from ".
# "file ...");
my $fh;
my $fname = $r->{args}{$an};
unless (open $fh, "<", $fname) {
die [500, "Can't open file '$fname' for argument '$an'".
": $!"];
}
$r->{args}{$an} = $do_stream ?
__gen_iter($fh, $as, $an) :
$is_ary ? [<$fh>] :
do { local $/; ~~<$fh> };
close $fh;
$r->{args}{"-cmdline_src_$an"} = 'file';
$r->{args}{"-cmdline_srcfilenames_$an"} = [$fname];
}
}
# encode to base64 if binary and we want to cross network (because
# it's usually JSON)
( run in 2.186 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )