File Coverage

lib/Pcore/Core/CLI/Arg.pm
Criterion Covered Total %
statement 6 74 8.1
branch 0 40 0.0
condition 0 12 0.0
subroutine 2 10 20.0
pod 0 2 0.0
total 8 138 5.8


line stmt bran cond sub pod time code
1             package Pcore::Core::CLI::Arg;
2              
3 5     5   37 use Pcore -class;
  5         11  
  5         34  
4 5     5   66 use Pcore::Util::Scalar qw[is_plain_arrayref];
  5         11  
  5         45  
5              
6             with qw[Pcore::Core::CLI::Type];
7              
8             has name => ( is => 'ro', isa => Str, required => 1 );
9              
10             has isa => ( is => 'ro', isa => Maybe CodeRef | RegexpRef | ArrayRef | Enum [ keys $Pcore::Core::CLI::Type::TYPE->%* ] );
11             has default => ( is => 'ro', isa => Str | ArrayRef );
12              
13             has min => ( is => 'lazy', isa => PositiveOrZeroInt ); # 0 - option is not required
14             has max => ( is => 'lazy', isa => PositiveOrZeroInt ); # 0 - unlimited repeats
15              
16             has type => ( is => 'lazy', isa => Str, init_arg => undef );
17             has is_repeatable => ( is => 'lazy', isa => Bool, init_arg => undef );
18             has is_required => ( is => 'lazy', isa => Bool, init_arg => undef );
19             has help_spec => ( is => 'lazy', isa => Str, init_arg => undef );
20              
21 0     0 0   sub BUILD ( $self, $args ) {
  0            
  0            
  0            
22 0           my $name = $self->name;
23              
24             # max
25 0 0 0       die qq[Argument "$name", "max" must be >= "min" ] if $self->max && $self->max < $self->min;
26              
27             # default
28 0 0         if ( defined $self->default ) {
29 0 0         die qq[Argument "$name", default value can be used only for required argument (min > 0)] if $self->min == 0;
30              
31 0 0         if ( $self->is_repeatable ) {
32 0 0         die qq[Argument "$name", default value must be a array for repeatable argument] if !is_plain_arrayref $self->default;
33             }
34             else {
35 0 0         die qq[Argument "$name", default value must be a string for plain argument] if ref $self->default;
36             }
37             }
38              
39 0           return;
40             }
41              
42 0     0     sub _build_min ($self) {
  0            
  0            
43 0           return 1;
44             }
45              
46 0     0     sub _build_max ($self) {
  0            
  0            
47 0 0         return $self->min ? $self->min : 1;
48             }
49              
50 0     0     sub _build_type ($self) {
  0            
  0            
51 0           return uc $self->name =~ s/_/-/smgr;
52             }
53              
54 0     0     sub _build_is_repeatable ($self) {
  0            
  0            
55 0 0         return $self->max != 1 ? 1 : 0;
56             }
57              
58 0     0     sub _build_is_required ($self) {
  0            
  0            
59 0 0 0       return $self->min && !defined $self->default ? 1 : 0;
60             }
61              
62 0     0     sub _build_help_spec ($self) {
  0            
  0            
63 0           my $spec;
64              
65 0 0         if ( $self->is_required ) {
66 0           $spec = uc $self->type;
67             }
68             else {
69 0           $spec = '[' . uc $self->type . ']';
70             }
71              
72 0 0         $spec .= '...' if $self->is_repeatable;
73              
74 0           return $spec;
75             }
76              
77 0     0 0   sub parse ( $self, $from, $to ) {
  0            
  0            
  0            
  0            
78 0 0         if ( !$from->@* ) {
79 0 0         if ( $self->min ) { # argument is required
80 0 0         if ( defined $self->default ) {
81              
82             # apply default value
83 0           $to->{ $self->name } = $self->default;
84             }
85             else {
86 0           return qq[required argument "@{[$self->type]}" is missed];
  0            
87             }
88             }
89             else {
90              
91             # argument not exists and is not required
92 0           return;
93             }
94             }
95             else {
96 0 0         if ( !$self->max ) { # slurpy
    0          
97 0           push $to->{ $self->name }->@*, splice $from->@*, 0, scalar $from->@*, ();
98             }
99             elsif ( $self->max == 1 ) { # not repeatable
100 0           $to->{ $self->name } = shift $from->@*;
101             }
102             else { # repeatable
103 0           push $to->{ $self->name }->@*, splice $from->@*, 0, $self->max, ();
104             }
105             }
106              
107             # min / max check for the repeatable arg
108 0 0         if ( $self->is_repeatable ) {
109              
110             # check min args num
111 0 0         return qq[argument "@{[$self->type]}" must be repeated at least @{[$self->min]} time(s)] if $to->{ $self->name }->@* < $self->min;
  0            
  0            
112              
113             # check max args num
114 0 0 0       return qq[argument "@{[$self->type]}" can be repeated not more, than @{[$self->max]} time(s)] if $self->max && $to->{ $self->name }->@* > $self->max;
  0            
  0            
115             }
116              
117             # validate arg value type
118 0 0 0       if ( defined $self->isa && ( my $error_msg = $self->_validate_isa( $to->{ $self->name } ) ) ) {
119 0           return qq[argument "@{[$self->type]}" $error_msg];
  0            
120             }
121              
122 0           return;
123             }
124              
125             1;
126             __END__
127             =pod
128              
129             =encoding utf8
130              
131             =head1 NAME
132              
133             Pcore::Core::CLI::Arg
134              
135             =head1 SYNOPSIS
136              
137             =head1 DESCRIPTION
138              
139             =head1 ATTRIBUTES
140              
141             =head1 METHODS
142              
143             =head1 SEE ALSO
144              
145             =cut