File Coverage

script/jsonfold.pl
Criterion Covered Total %
statement 72 100 72.0
branch 9 28 32.1
condition 0 11 0.0
subroutine 16 20 80.0
pod n/a
total 97 159 61.0


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2 1     1   3710 use strict;
  1         1  
  1         30  
3 1     1   3 use warnings;
  1         1  
  1         39  
4 1     1   12 use 5.014 ;
  1         2  
5              
6 1     1   609 use FindBin;
  1         1029  
  1         60  
7 1     1   443 use lib "$FindBin::RealBin/../lib";
  1         618  
  1         8  
8 1     1   728 use Getopt::Long qw(GetOptions);
  1         11720  
  1         4  
9 1     1   828 use JSON::PP ;
  1         13510  
  1         67  
10 1     1   577 use JSON::JSONFold qw(jsonfold_config write_json) ;
  1         3  
  1         59  
11 1     1   516 use Data::Dumper;
  1         7497  
  1         57  
12              
13 1     1   5 use Carp qw(confess cluck);
  1         0  
  1         158  
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         1824 };
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   1 my %cfg ;
35              
36 1         9 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       21 ) or die "Try --help\n";
70              
71 1         1334 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         2 my $json_text;
96 1 50       3 if (defined $input) {
97 0 0       0 open my $fh, '<:encoding(UTF-8)', $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         5 binmode STDIN, ":encoding(UTF-8)" ;
103 1         30 local $/;
104 1         19 $json_text = ;
105             }
106              
107 1         13 return JSON::PP->new->allow_nonref->decode($json_text);
108             }
109              
110             sub get_config {
111 1     1   2 my ($opt) = @_;
112              
113 1         1 my %cfg = %{$opt->{cfg}} ;
  1         8  
114              
115 1         2 for my $phase (qw(pack fold join)) {
116 3         3 my $k = "${phase}_items";
117 3         4 my $v = delete($cfg{$k}) ;
118 3 50       6 next unless defined($v) ;
119              
120 0   0     0 $cfg{"${phase}_array_items"} //= $v ;
121 0   0     0 $cfg{"${phase}_obj_items"} //= $v ;
122             }
123             # Get only set options
124 1         3 %cfg = map { ($_ => $cfg{$_}) } grep { defined $cfg{$_} } keys(%cfg) ;
  0         0  
  11         13  
125             # Temporary hack until we figure sort order.
126              
127 1         2 $cfg{sort_keys} = 1 ;
128              
129 1         6 my $config = jsonfold_config($opt->{compact}, $opt->{width}, %cfg);
130 1         2 return $config ;
131             }
132              
133             sub show_verbose {
134 0     0   0 my ($label) = shift ;
135 0         0 my $dumper = new Data::Dumper([])->Terse(1)->Indent(1)->Sortkeys(1)->Pair('=')->Quotekeys(0) ;
136              
137 0         0 my $s = $dumper->Values( \@_)->Dump ;
138 0         0 $s =~ s/\s+/ /gsm ;
139              
140 0         0 print STDERR "$label: $s\n" ;
141              
142             }
143              
144             sub stdout_width {
145 0 0   0   0 return unless -t STDOUT;
146              
147 0         0 eval {
148 0         0 require Term::ReadKey;
149 0         0 my ($cols) = Term::ReadKey::GetTerminalSize(*STDOUT);
150 0 0       0 return $cols if $cols;
151             };
152              
153 0         0 return $ENV{COLUMNS} ;
154             }
155              
156              
157             sub main {
158 1     1   3 my $opt = parse_options();
159              
160 1 50       4 if ($opt->{help}) {
161 0         0 usage();
162 0         0 return 0;
163             }
164              
165 1     1   648 binmode STDOUT, ':encoding(UTF-8)' ;
  1         13  
  1         5  
  1         26  
166 1         929 my $verose = $opt->{verbose} ;
167              
168 1 50       6 my $data = $opt->{demo} ? demo_data() : read_input($opt->{input});
169 1 50 0     415 $opt->{cfg}{width} //= stdout_width() if -t STDOUT ;
170              
171 1         5 my $cfg = get_config($opt);
172 1         2 my $verbose = $opt->{verbose} ;
173 1         2 my $native = $opt->{native} ;
174              
175 1 50 0     3 print STDERR "Backend: ", $JSON::JSONFold::BACKEND || "-", "\n" if $verbose ;
176 1 50       4 show_verbose("config", { $cfg->as_hash }) if $verbose ;
177            
178 1         6 my $info = write_json($data, \*STDOUT, $opt->{width}, $cfg, sort_keys => $opt->{sort_keys}, gold => !$native);
179              
180 1 50       3 show_verbose("stats", { % $info }) if $verbose ;
181 1           return 0;
182             }
183              
184 1         90385 main() ;