File Coverage

blib/script/jsonfold.pl
Criterion Covered Total %
statement 66 94 70.2
branch 8 26 30.7
condition 0 9 0.0
subroutine 15 19 78.9
pod n/a
total 89 148 60.1


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2 1     1   3546 use strict;
  1         1  
  1         29  
3 1     1   2 use warnings;
  1         1  
  1         40  
4 1     1   14 use 5.014 ;
  1         2  
5              
6 1     1   657 use FindBin;
  1         1025  
  1         55  
7 1     1   429 use lib "$FindBin::RealBin/../lib";
  1         591  
  1         5  
8 1     1   791 use Getopt::Long qw(GetOptions);
  1         11089  
  1         5  
9 1     1   765 use JSON::PP ;
  1         12885  
  1         69  
10 1     1   528 use JSON::JSONFold qw(jsonfold_config write_json) ;
  1         2  
  1         64  
11 1     1   543 use Data::Dumper;
  1         6064  
  1         55  
12              
13 1     1   5 use Carp qw(confess cluck);
  1         1  
  1         131  
14              
15             BEGIN {
16             $SIG{__DIE__} = sub {
17 0 0       0 return if $^S;
18 0         0 local $SIG{__DIE__};
19 0         0 Carp::confess(@_);
20 1     1   6 };
21              
22              
23             $SIG{__WARN__} = sub {
24 0         0 local $SIG{__WARN__};
25 0         0 Carp::cluck(@_);
26 1         1918 };
27             }
28              
29             sub demo_data {
30 0     0   0 return JSON::JSONFold::CLI::demo_data() ;
31             }
32              
33             sub parse_options {
34 1     1   31 my %cfg ;
35              
36 1         15 my %opt = (
37             compact => 'default',
38             indent => 2,
39             demo => 0,
40             verbose => 0,
41             sort_keys => 1,
42             help => 0,
43             cfg => \%cfg,
44             );
45              
46             GetOptions(
47             'demo' => \$opt{demo},
48             'verbose|v' => \$opt{verbose},
49             'help|h' => \$opt{help},
50             'input|i=s' => \$opt{input},
51             'compact=s' => \$opt{compact},
52             'indent=i' => \$opt{indent},
53             'native' => \$opt{native},
54             'sort-keys!' => \$cfg{sort_keys},
55              
56             'width=i' => \$cfg{width},
57             'pack-items=i' => \$cfg{pack_items},
58             'pack-array-items=i' => \$cfg{pack_array_items},
59             'pack-obj-items=i' => \$cfg{pack_obj_items},
60             'pack-nesting=i' => \$cfg{pack_nesting},
61             'fold-items=i' => \$cfg{fold_items},
62             'fold-array-items=i' => \$cfg{fold_array_items},
63             'fold-obj-items=i' => \$cfg{fold_obj_items},
64             'fold-nesting=i' => \$cfg{fold_nesting},
65             'join-items=i' => \$cfg{join_items},
66             'join-array-items=i' => \$cfg{join_array_items},
67             'join-obj-items=i' => \$cfg{join_obj_items},
68             'join-nesting=i' => \$cfg{join_nesting},
69 1 50       26 ) or die "Try --help\n";
70              
71 1         2157 return \%opt;
72             }
73              
74             sub usage {
75 0     0   0 my $out = shift ;
76 0         0 $out->print(<<___
77             Usage: json-jsonfold [options] < input.json
78              
79             --demo
80             --compact=default|none|low|med|high|max|pack|fold|join|off
81             --width=N
82             --indent=N
83             --sort-keys
84             --input=FILE
85             --pack-items=N / --pack-array-items=N / --pack-obj-items=N / --pack-nesting=N
86             --fold-items=N / --fold-array-items=N / --fold-obj-items=N / --fold-nesting=N
87             --join-items=N / --join-array-items=N / --join-obj-items=N / --join-nesting=N
88             ___
89             ) ;
90             }
91              
92             sub read_input {
93 1     1   2 my ($input) = @_ ;
94              
95 1         1 my $json_text;
96 1 50       2 if (defined $input) {
97 0 0       0 open my $fh, '<', $input or die "$input: $!\n";
98 0         0 local $/;
99 0         0 $json_text = <$fh>;
100 0 0       0 close $fh or die "$input: $!\n";
101             } else {
102 1         4 local $/;
103 1         22 $json_text = ;
104             }
105              
106 1         5 return JSON::PP->new->allow_nonref->decode($json_text);
107             }
108              
109             sub get_config {
110 1     1   3 my ($opt) = @_;
111              
112 1         2 my %cfg = %{$opt->{cfg}} ;
  1         10  
113              
114 1         5 for my $phase (qw(pack fold join)) {
115 3         6 my $k = "${phase}_items";
116 3         7 my $v = delete($cfg{$k}) ;
117 3 50       8 next unless defined($v) ;
118              
119 0   0     0 $cfg{"${phase}_array_items"} //= $v ;
120 0   0     0 $cfg{"${phase}_obj_items"} //= $v ;
121             }
122             # Get only set options
123 1         5 %cfg = map { ($_ => $cfg{$_}) } grep { defined $cfg{$_} } keys(%cfg) ;
  0         0  
  11         20  
124             # Temporary hack until we figure sort order.
125              
126 1         4 $cfg{sort_keys} = 1 ;
127              
128 1         10 my $config = jsonfold_config($opt->{compact}, $opt->{width}, %cfg);
129 1         5 return $config ;
130             }
131              
132             sub show_verbose {
133 0     0   0 my ($label) = shift ;
134 0         0 my $dumper = new Data::Dumper([])->Terse(1)->Indent(1)->Sortkeys(1)->Pair('=')->Quotekeys(0) ;
135              
136 0         0 my $s = $dumper->Values( \@_)->Dump ;
137 0         0 $s =~ s/\s+/ /gsm ;
138              
139 0         0 print STDERR "$label: $s\n" ;
140              
141             }
142              
143             sub stdout_width {
144 0 0   0   0 return unless -t STDOUT;
145              
146 0         0 eval {
147 0         0 require Term::ReadKey;
148 0         0 my ($cols) = Term::ReadKey::GetTerminalSize(*STDOUT);
149 0 0       0 return $cols if $cols;
150             };
151              
152 0         0 return $ENV{COLUMNS} ;
153             }
154              
155              
156             sub main {
157 1     1   5 my $opt = parse_options();
158              
159 1 50       3 if ($opt->{help}) {
160 0         0 usage();
161 0         0 return 0;
162             }
163              
164 1         2 my $verose = $opt->{verbose} ;
165              
166 1 50       5 my $data = $opt->{demo} ? demo_data() : read_input($opt->{input});
167 1 50 0     570 $opt->{cfg}{width} //= stdout_width() if -t STDOUT ;
168              
169 1         6 my $cfg = get_config($opt);
170 1         3 my $verbose = $opt->{verbose} ;
171 1         2 my $native = $opt->{native} ;
172              
173 1 50       3 show_verbose("config", { $cfg->as_hash }) if $verbose ;
174            
175 1         7 my $info = write_json($data, \*STDOUT, $opt->{width}, $cfg, sort_keys => $opt->{sort_keys}, gold => !$native);
176              
177 1 50       6 show_verbose("stats", { % $info }) if $verbose ;
178 1           return 0;
179             }
180              
181 1         101950 main() ;