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