File Coverage

blib/lib/Perinci/Sub/Util/Args.pm
Criterion Covered Total %
statement 68 78 87.1
branch 27 38 71.0
condition 10 12 83.3
subroutine 10 10 100.0
pod 5 5 100.0
total 120 143 83.9


line stmt bran cond sub pod time code
1             package Perinci::Sub::Util::Args;
2              
3             our $DATE = '2017-01-31'; # DATE
4             our $VERSION = '0.46'; # VERSION
5              
6 1     1   13548 use 5.010001;
  1         3  
7 1     1   4 use strict 'subs', 'vars';
  1         1  
  1         23  
8 1     1   3 use warnings;
  1         1  
  1         25  
9              
10 1     1   3 use Exporter qw(import);
  1         1  
  1         596  
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 802 my ($meta, $args, $tag) = @_;
21              
22 6         7 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         20 my $argspec = $args_prop->{$argname};
27 24 100       22 if ($neg) {
28             next unless !$argspec->{tags} ||
29 4 100 66     9 !(grep {$_ eq $tag} @{$argspec->{tags}});
  5         11  
  3         5  
30             } else {
31             next unless $argspec->{tags} &&
32 20 100 100     37 grep {$_ eq $tag} @{$argspec->{tags}};
  25         58  
  15         15  
33             }
34             push @res, $argname, $args->{$argname}
35 8 100       18 if exists $args->{$argname};
36             }
37 6         28 @res;
38             }
39              
40             sub argnames_by_tag {
41 5     5 1 1455 my ($meta, $tag) = @_;
42              
43 5         5 my @res;
44 5 50       11 my $args_prop = $meta->{args} or return ();
45 5 100       17 my $neg = 1 if $tag =~ s/\A!//;
46 5         11 for my $argname (keys %$args_prop) {
47 20         14 my $argspec = $args_prop->{$argname};
48 20 100       22 if ($neg) {
49             next unless !$argspec->{tags} ||
50 4 100 66     10 !(grep {$_ eq $tag} @{$argspec->{tags}});
  5         11  
  3         4  
51             } else {
52             next unless $argspec->{tags} &&
53 16 100 100     26 grep {$_ eq $tag} @{$argspec->{tags}};
  20         45  
  12         17  
54             }
55 8         9 push @res, $argname;
56             }
57 5         30 sort @res;
58             }
59              
60             sub _find_meta {
61 2     2   3 my $caller = shift;
62 2         2 my $func_name = shift;
63              
64 2 50       12 if ($func_name =~ /(.+)::(.+)/) {
65 2         13 return ${"$1::SPEC"}{$2};
  2         18  
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 1253 my ($func_name, $args, $tag) = @_;
73 1 50       9 my $meta = _find_meta([caller(1)], $func_name)
74             or die "Can't find Rinci function metadata for $func_name";
75 1         3 args_by_tag($meta, $args, $tag);
76             }
77              
78             sub func_argnames_by_tag {
79 1     1 1 1246 my ($func_name, $tag) = @_;
80 1 50       8 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 1221 my ($func_name, $args) = @_;
87              
88 1         1 my ($meta, $func);
89 1 50       6 if ($func_name =~ /(.+)::(.+)/) {
90 1 50       2 defined &{$func_name}
  1         5  
91             or die "Function $func_name not defined";
92 1         1 $func = \&{$func_name};
  1         1  
93 1         2 $meta = ${"$1::SPEC"}{$2};
  1         4  
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         1 my @args;
105 1 50       3 if ($meta->{args}) {
106 1         1 for my $argname (keys %{ $meta->{args} }) {
  1         4  
107             push @args, $argname, $args->{$argname}
108 4 100       9 if exists $args->{$argname};
109             }
110             }
111 1         3 $func->(@args);
112             }
113              
114             1;
115             # ABSTRACT: Utility routines related to Rinci arguments
116              
117             __END__