File Coverage

blib/lib/App/NDTools/NDTool.pm
Criterion Covered Total %
statement 83 94 88.3
branch 15 20 75.0
condition n/a
subroutine 18 21 85.7
pod 0 9 0.0
total 116 144 80.5


line stmt bran cond sub pod time code
1             package App::NDTools::NDTool;
2              
3 16     16   6338 use strict;
  16         39  
  16         586  
4 16     16   323 use warnings FATAL => 'all';
  16         43  
  16         644  
5              
6 16     16   5715 use App::NDTools::INC;
  16         41  
  16         97  
7 16     16   7485 use App::NDTools::Slurp qw(s_dump s_load);
  16         50  
  16         1105  
8 16     16   8073 use Encode::Locale;
  16         222347  
  16         803  
9 16     16   119 use Encode qw(decode);
  16         36  
  16         1113  
10 16     16   12171 use Getopt::Long qw(GetOptionsFromArray :config bundling noignore_case);
  16         180955  
  16         78  
11 16     16   3777 use Log::Log4Cli;
  16         36  
  16         1427  
12 16     16   8179 use Struct::Path 0.80 qw(path);
  16         35712  
  16         16495  
13              
14             our $VERSION = '0.33';
15              
16             sub arg_opts {
17 191     191 0 470 my $self = shift;
18              
19             return (
20             'dump-opts' => \$self->{OPTS}->{'dump-opts'},
21             'help|h' => sub {
22 0     0   0 $self->{OPTS}->{help} = 1;
23 0         0 die "!FINISH";
24             },
25             'ifmt=s' => \$self->{OPTS}->{ifmt},
26             'ofmt=s' => \$self->{OPTS}->{ofmt},
27             'pretty!' => \$self->{OPTS}->{pretty},
28             'verbose|v:+' => \$Log::Log4Cli::LEVEL,
29             'version|V' => sub {
30 3     3   7035 $self->{OPTS}->{version} = 1;
31 3         34 die "!FINISH";
32             },
33 191         6626 );
34             }
35              
36             sub check_args {
37 67     67 0 150 my $self = shift;
38              
39 67 100       203 die_fatal 'At least one argument expected', 1 unless (@_);
40              
41 66         208 return $self;
42             }
43              
44             sub configure {
45 116     116 0 254 my $self = shift;
46              
47 116         189 return $self->check_args(@{$self->{ARGV}});
  116         418  
48             }
49              
50             sub defaults {
51             return {
52 118     118 0 2174 'ofmt' => 'JSON',
53             'pretty' => 1,
54             'verbose' => $Log::Log4Cli::LEVEL,
55             };
56             }
57              
58             sub dump_opts {
59 1     1 0 2177 my $self = shift;
60              
61 1         4 delete $self->{OPTS}->{'dump-opts'};
62 1         5 s_dump(\*STDOUT, undef, undef, $self->{OPTS});
63             }
64              
65             sub grep {
66 15     15 0 2210 my ($self, $spaths, @structs) = @_;
67 15         26 my @out;
68              
69 15         39 for my $struct (@structs) {
70 15         31 my (%map_idx, $path, $ref, $grepped);
71              
72 15         25 for (@{$spaths}) {
  15         34  
73 19         436 my @found = eval { path($struct, $_, deref => 1, paths => 1) };
  19         64  
74              
75 19         4122 while (($path, $ref) = splice @found, 0, 2) {
76             # remap array's indexes
77 34         2880 my $map_key = "";
78 34         56 my $map_path = [];
79              
80 34         92 for my $step (@{$path}) {
  34         68  
81 104 100       202 if (ref $step eq 'ARRAY') {
82 52         99 $map_key .= "[]";
83 52 100       150 unless (exists $map_idx{$map_key}->{$step->[0]}) {
84             $map_idx{$map_key}->{$step->[0]} =
85 37         64 keys %{$map_idx{$map_key}};
  37         147  
86             }
87              
88 52         79 push @{$map_path}, [$map_idx{$map_key}->{$step->[0]}];
  52         134  
89             } else { # HASH
90 52         116 $map_key .= "{$step->{K}->[0]}";
91 52         75 push @{$map_path}, $step;
  52         91  
92             }
93             }
94              
95 34         94 path($grepped, $map_path, assign => $ref, expand => 1);
96             }
97             }
98              
99 15 100       1642 push @out, $grepped if (defined $grepped);
100             }
101              
102 15         93 return @out;
103             }
104              
105             sub load_struct {
106 278     278 0 3299 my ($self, $uri, $fmt) = @_;
107              
108 278 0   0   2119 log_trace { ref $uri ? "Reading from STDIN" : "Loading '$uri'" };
  0         0  
109 278         2120 s_load($uri, $fmt);
110             }
111              
112             sub new {
113 191     191 0 4624 my $self = bless {}, shift;
114              
115 191         798 $self->{OPTS} = $self->defaults();
116             $self->{ARGV} =
117 191 100       810 [ map { decode(locale => "$_", Encode::FB_CROAK) } @_ ? @_ : @ARGV ];
  871         35479  
118              
119 191         10182 $self->{TTY} = -t STDOUT;
120              
121 191 50       1127 unless (GetOptionsFromArray ($self->{ARGV}, $self->arg_opts)) {
122 0         0 $self->usage;
123 0         0 die_fatal "Unsupported opts used", 1;
124             }
125              
126 191 50       257915 if ($self->{OPTS}->{help}) {
127 0         0 $self->usage;
128 0         0 die_info, 0;
129             }
130              
131 191 100       616 if ($self->{OPTS}->{version}) {
132 3         189 print $self->VERSION . "\n";
133 3         40 die_info, 0;
134             }
135              
136 188         898 $self->configure();
137              
138 183 50       625 if ($self->{OPTS}->{'dump-opts'}) {
139 0         0 $self->dump_opts();
140 0         0 die_info, 0;
141             }
142              
143 183         727 return $self;
144             }
145              
146             sub usage {
147 0     0 0   require Pod::Usage;
148 0           Pod::Usage::pod2usage(
149             -exitval => 'NOEXIT',
150             -output => \*STDERR,
151             -sections => 'SYNOPSIS|OPTIONS|EXAMPLES',
152             -verbose => 99
153             );
154             }
155              
156             1; # End of App::NDTools::NDTool