File Coverage

blib/lib/Perinci/Sub/Util/Args.pm
Criterion Covered Total %
statement 69 79 87.3
branch 27 38 71.0
condition 12 12 100.0
subroutine 10 10 100.0
pod 5 5 100.0
total 123 144 85.4


line stmt bran cond sub pod time code
1             package Perinci::Sub::Util::Args;
2              
3 1     1   70024 use 5.010001;
  1         13  
4 1     1   6 use strict 'subs', 'vars';
  1         2  
  1         43  
5 1     1   6 use warnings;
  1         13  
  1         51  
6              
7 1     1   7 use Exporter qw(import);
  1         2  
  1         1022  
8              
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2023-07-02'; # DATE
11             our $DIST = 'Perinci-Sub-Util'; # DIST
12             our $VERSION = '0.471'; # VERSION
13              
14             our @EXPORT_OK = qw(
15             args_by_tag
16             argnames_by_tag
17             func_args_by_tag
18             func_argnames_by_tag
19             call_with_its_args
20             );
21              
22             sub args_by_tag {
23 6     6 1 1572 my ($meta, $args, $tag) = @_;
24              
25 6         10 my @res;
26 6 50       17 my $args_prop = $meta->{args} or return ();
27 6         48 my $neg = $tag =~ s/\A!//;
28 6         21 for my $argname (keys %$args_prop) {
29 24         36 my $argspec = $args_prop->{$argname};
30 24 100       38 if ($neg) {
31             next unless !$argspec->{tags} ||
32 4 100 100     11 !(grep {$_ eq $tag} @{$argspec->{tags}});
  5         15  
  3         9  
33             } else {
34             next unless $argspec->{tags} &&
35 20 100 100     48 grep {$_ eq $tag} @{$argspec->{tags}};
  25         73  
  15         36  
36             }
37             push @res, $argname, $args->{$argname}
38 8 100       27 if exists $args->{$argname};
39             }
40 6         43 @res;
41             }
42              
43             sub argnames_by_tag {
44 5     5 1 2677 my ($meta, $tag) = @_;
45              
46 5         9 my @res;
47 5 50       17 my $args_prop = $meta->{args} or return ();
48 5 100       7 my $neg; $neg = 1 if $tag =~ s/\A!//;
  5         17  
49 5         15 for my $argname (keys %$args_prop) {
50 20         31 my $argspec = $args_prop->{$argname};
51 20 100       36 if ($neg) {
52             next unless !$argspec->{tags} ||
53 4 100 100     11 !(grep {$_ eq $tag} @{$argspec->{tags}});
  5         15  
  3         8  
54             } else {
55             next unless $argspec->{tags} &&
56 16 100 100     37 grep {$_ eq $tag} @{$argspec->{tags}};
  20         62  
  12         22  
57             }
58 8         18 push @res, $argname;
59             }
60 5         50 sort @res;
61             }
62              
63             sub _find_meta {
64 2     2   6 my $caller = shift;
65 2         3 my $func_name = shift;
66              
67 2 50       16 if ($func_name =~ /(.+)::(.+)/) {
68 2         5 return ${"$1::SPEC"}{$2};
  2         16  
69             } else {
70 0         0 return ${"$caller->[0]::SPEC"}{$func_name};
  0         0  
71             }
72             }
73              
74             sub func_args_by_tag {
75 1     1 1 2433 my ($func_name, $args, $tag) = @_;
76 1 50       8 my $meta = _find_meta([caller(1)], $func_name)
77             or die "Can't find Rinci function metadata for $func_name";
78 1         5 args_by_tag($meta, $args, $tag);
79             }
80              
81             sub func_argnames_by_tag {
82 1     1 1 2441 my ($func_name, $tag) = @_;
83 1 50       8 my $meta = _find_meta([caller(1)], $func_name)
84             or die "Can't find Rinci function metadata for $func_name";
85 1         7 argnames_by_tag($meta, $tag);
86             }
87              
88             sub call_with_its_args {
89 1     1 1 2409 my ($func_name, $args) = @_;
90              
91 1         2 my ($meta, $func);
92 1 50       9 if ($func_name =~ /(.+)::(.+)/) {
93 1 50       2 defined &{$func_name}
  1         6  
94             or die "Function $func_name not defined";
95 1         1 $func = \&{$func_name};
  1         3  
96 1         2 $meta = ${"$1::SPEC"}{$2};
  1         5  
97             } else {
98 0         0 my @caller = caller(1);
99 0         0 my $fullname = "$caller[0]::$func_name";
100 0 0       0 defined &{$fullname}
  0         0  
101             or die "Function $fullname not defined";
102 0         0 $func = \&{$fullname};
  0         0  
103 0         0 $meta = ${"$caller[0]::SPEC"}{$func_name};
  0         0  
104             }
105 1 50       4 $meta or die "Can't find Rinci function metadata for $func_name";
106              
107 1         2 my @args;
108 1 50       3 if ($meta->{args}) {
109 1         3 for my $argname (keys %{ $meta->{args} }) {
  1         5  
110             push @args, $argname, $args->{$argname}
111 4 100       12 if exists $args->{$argname};
112             }
113             }
114 1         4 $func->(@args);
115             }
116              
117             1;
118             # ABSTRACT: Utility routines related to Rinci arguments
119              
120             __END__