File Coverage

blib/lib/OptArgs2/Arg.pm
Criterion Covered Total %
statement 76 85 89.4
branch 22 42 52.3
condition 13 26 50.0
subroutine 13 14 92.8
pod 0 8 0.0
total 124 175 70.8


line stmt bran cond sub pod time code
1             package OptArgs2::Arg;
2 6     6   65 use strict;
  6         11  
  6         236  
3 6     6   29 use warnings;
  6         11  
  6         384  
4 6     6   43 use parent 'OptArgs2::OptArgBase';
  6         20  
  6         80  
5              
6             my %isa2name = (
7             'ArrayRef' => 'Str',
8             'HashRef' => 'Str',
9             'Input' => 'Str',
10             'Int' => 'Int',
11             'Num' => 'Num',
12             'Str' => 'Str',
13             'SubCmd' => 'Str',
14             );
15              
16             my %arg2getopt = (
17             'Str' => '=s',
18             'Input' => '=s',
19             'Int' => '=i',
20             'Num' => '=f',
21             'ArrayRef' => '=s@',
22             'HashRef' => '=s%',
23             'SubCmd' => '=s',
24             );
25              
26             ### START Class::Inline ### v0.0.1 Wed Dec 3 10:44:53 2025
27             require Scalar::Util;
28             require Carp;
29             our ( @_CLASS, $_FIELDS, %_NEW );
30              
31             sub new {
32 7     7 0 14 my $class = shift;
33 7   33     32 my $CLASS = ref $class || $class;
34 7   66     39 $_NEW{$CLASS} //= do {
35 4         11 my ( %seen, @new, @build );
36 4         10 my @possible = ($CLASS);
37 4         20 while (@possible) {
38 8         13 my $c = shift @possible;
39 6     6   1306 no strict 'refs';
  6         11  
  6         7915  
40 8 50       16 push @new, $c . '::_NEW' if exists &{ $c . '::_NEW' };
  8         41  
41 8 100       13 push @build, $c . '::BUILD' if exists &{ $c . '::BUILD' };
  8         31  
42 8         18 $seen{$c}++;
43 8 50       10 if ( exists &{ $c . '::DOES' } ) {
  8         26  
44 0         0 push @possible, grep { not $seen{$_}++ } $c->DOES('*');
  0         0  
45             }
46 8         14 push @possible, grep { not $seen{$_}++ } @{ $c . '::ISA' };
  4         32  
  8         66  
47             }
48 4         83 [ [ reverse(@new) ], [ reverse(@build) ] ];
49             };
50 7 50       50 my $self = { @_ ? @_ > 1 ? @_ : %{ $_[0] } : () };
  0 50       0  
51 7         16 bless $self, $CLASS;
52 7         52 my $attrs = { map { ( $_ => 1 ) } keys %$self };
  41         78  
53 7         16 map { $self->$_($attrs) } @{ $_NEW{$CLASS}->[0] };
  14         59  
  7         21  
54             {
55 7         9 local $Carp::CarpLevel = 3;
  7         14  
56 7         22 Carp::carp("OptArgs2::Arg: unexpected argument '$_'") for keys %$attrs
57             }
58 7         9 map { $self->$_ } @{ $_NEW{$CLASS}->[1] };
  7         24  
  7         18  
59 7         24 $self;
60             }
61              
62             sub _NEW {
63 7     7   15 CORE::state $fix_FIELDS = do {
64 4 50       27 $_FIELDS = { @_CLASS > 1 ? @_CLASS : %{ $_CLASS[0] } };
  0         0  
65 4 50       24 $_FIELDS = $_FIELDS->{'FIELDS'} if exists $_FIELDS->{'FIELDS'};
66             };
67 7 50       15 if ( my @missing = grep { not exists $_[0]->{$_} } 'isa' ) {
  7         40  
68 0         0 Carp::croak( 'OptArgs2::Arg required initial argument(s): '
69             . join( ', ', @missing ) );
70             }
71             Scalar::Util::weaken( $_[0]{'cmd'} )
72 7 50 33     41 if exists $_[0]{'cmd'} && ref $_[0]{'cmd'};
73 7         20 $_[0]{'isa'} = eval { $_FIELDS->{'isa'}->{'isa'}->( $_[0]{'isa'} ) };
  7         32  
74 7 50       25 Carp::confess( 'OptArgs2::Arg isa: ' . $@ ) if $@;
75 7         13 map { delete $_[1]->{$_} } 'cmd', 'fallthru', 'greedy', 'isa', 'isa_name';
  35         57  
76             }
77              
78             sub __RO {
79 0     0   0 my ( undef, undef, undef, $sub ) = caller(1);
80 0         0 Carp::confess("attribute $sub is read-only");
81             }
82              
83             sub cmd {
84 4 50   4 0 10 if ( @_ > 1 ) {
85 0         0 $_[0]{'cmd'} = $_[1];
86 0 0       0 Scalar::Util::weaken( $_[0]{'cmd'} ) if ref $_[0]{'cmd'};
87             }
88 4   50     39 $_[0]{'cmd'} // undef;
89             }
90 3 50 100 3 0 10 sub fallthru { __RO() if @_ > 1; $_[0]{'fallthru'} // undef }
  3         46  
91 18 50 50 18 0 37 sub greedy { __RO() if @_ > 1; $_[0]{'greedy'} // undef }
  18         128  
92 20 50 50 20 0 39 sub isa { __RO() if @_ > 1; $_[0]{'isa'} // undef }
  20         74  
93              
94             sub isa_name {
95 4 50   4 0 20 __RO() if @_ > 1;
96 4   33     22 $_[0]{'isa_name'} //= $_FIELDS->{'isa_name'}->{'default'}->( $_[0] );
97             }
98             @_CLASS = grep 1, ### END Class::Inline ###
99             cmd => { is => 'rw', weaken => 1, },
100             fallthru => {},
101             greedy => {},
102             isa => {
103             required => 1,
104             isa => sub {
105             $isa2name{ $_[0] }
106             // OptArgs2::croak( 'InvalidIsa', 'invalid isa type: ' . $_[0] );
107             $_[0];
108             },
109             },
110             isa_name => {
111             default => sub {
112             '(' . $isa2name{ $_[0]->isa } . ')';
113             },
114             },
115             ;
116              
117             our @CARP_NOT = @OptArgs2::CARP_NOT;
118              
119             sub BUILD {
120 7     7 0 11 my $self = shift;
121              
122 7 50 66     42 OptArgs2::croak( 'Conflict', q{'default' and 'required' conflict} )
123             if $self->required and defined $self->default;
124              
125 7 50 33     25 OptArgs2::croak( 'Conflict', q{'isa SubCmd' and 'greedy' conflict} )
126             if $self->greedy and $self->isa eq 'SubCmd';
127             }
128              
129             sub name_alias_type_comment {
130 4     4 0 8 my $self = shift;
131 4         6 my $value = shift;
132              
133 4 50       17 my $deftype = ( defined $value ) ? '[' . $value . ']' : $self->isa_name;
134 4         15 my $comment = $self->comment;
135              
136 4 100       10 if ( $self->required ) {
137 3 50       10 $comment .= ' ' if length $comment;
138 3         69 $comment .= '*required*';
139             }
140              
141 4         18 return $self->name, '', $deftype, $comment;
142             }
143              
144             1;
145              
146             __END__