File Coverage

bin/yto
Criterion Covered Total %
statement 57 61 93.4
branch 20 26 76.9
condition 3 3 100.0
subroutine 9 9 100.0
pod n/a
total 89 99 89.9


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             package yto;
3             # ABSTRACT: Change YAML to another format (like JSON)
4             $yto::VERSION = '0.013';
5 1     1   584 use App::YAML::Filter::Base;
  1         3  
  1         17  
6 1     1   1004 use Pod::Usage::Return qw( pod2usage );
  1         43809  
  1         71  
7 1     1   912 use Getopt::Long qw( GetOptionsFromArray );
  1         9424  
  1         6  
8 1     1   165 use YAML;
  1         1  
  1         54  
9 1     1   5 use Module::Runtime qw( use_module );
  1         1  
  1         7  
10              
11             $|++; # no buffering
12              
13             sub main {
14 4     4   33925 my ( $class, @argv ) = @_;
15 4         7 my %opt;
16 4         22 GetOptionsFromArray( \@argv, \%opt,
17             'help|h',
18             'version',
19             );
20 4 50       710 return pod2usage(0) if $opt{help};
21 4 50       14 if ( $opt{version} ) {
22 0         0 print "yto version $yto::VERSION (Perl $^V)\n";
23 0         0 return 0;
24             }
25              
26 4         8 my $format = shift @argv;
27 4 100       12 return pod2usage("ERROR: Must give a format") unless $format;
28 3 100       27 return pod2usage("ERROR: Unknown format '$format'")
29             unless $class->format_modules( $format );
30              
31 2 100       7 push @argv, "-" unless @argv;
32 2         3 for $ARGV ( @argv ) {
33             # We're doing a similar behavior to <>, but manually for easier testing.
34 2         3 my $fh;
35 2 100       5 if ( $ARGV eq '-' ) {
36             # Use the existing STDIN so tests can fake it
37 1         5 $fh = \*STDIN;
38             }
39             else {
40 1 50       30 unless ( open $fh, '<', $ARGV ) {
41 0         0 warn "Could not open file '$ARGV' for reading: $!\n";
42 0         0 next;
43             }
44             }
45              
46 2         4 my $buffer;
47 2         3 my $scope = {};
48 2         17 while ( my $line = <$fh> ) {
49             # --- is the start of a new document
50 12 100 100     44 if ( $buffer && $line =~ /^---/ ) {
51             # Flush the previous document
52 2         8 print $class->format( $format, YAML::Load( $buffer ) );
53 2         15 $buffer = '';
54             }
55 12         53 $buffer .= $line;
56             }
57             # Flush the buffer in the case of a single document with no ---
58 2 50       9 if ( $buffer =~ /\S/ ) {
59             #print STDERR "Buffer is: $buffer\n";
60 2         7 print $class->format( $format, YAML::Load( $buffer ) );
61             }
62             }
63              
64 2         11 return 0;
65             }
66              
67             # Hash of "format" => Formatter sub we chose
68             # This is after we choose a formatter module
69             my %formatter = ();
70              
71             # Hash of "format" => [ MODULE... ]
72             # The modules are in order we should try to load them, so put the better ones first
73             my %FORMAT_MODULES = (
74             json => [qw( JSON::XS JSON::PP )],
75             );
76              
77             # Hash of MODULE => formatter sub
78             my %FORMAT_SUB = (
79             'JSON::XS' => sub {
80             state $json = JSON::XS->new->canonical->pretty->allow_nonref;
81             return join( "\n", map { $json->encode( $_ ) } @_ );
82             },
83             'JSON::PP' => sub {
84             state $json = JSON::PP->new->canonical->pretty->indent_length(3)->allow_nonref;
85             return join "\n", map { $json->encode( $_ ) } @_;
86             },
87             );
88              
89             sub format_modules {
90 4     4   6 my ( $class, $format ) = @_;
91 4 100       18 return unless $FORMAT_MODULES{ $format };
92 3         3 return @{ $FORMAT_MODULES{ $format } };
  3         9  
93             }
94              
95             sub can_format {
96 5     5   10068 my ( $class, $format ) = @_;
97 5         8 my $f = $formatter{ $format };
98 5 100       14 if ( !$f ) {
99 1         4 my @modules = $class->format_modules( $format );
100 1         2 for my $module ( @modules ) {
101 1 50       2 if ( eval { use_module( $module ); 1 } ) {
  1         5  
  1         34  
102 1         4 $f = $formatter{ $format } = $FORMAT_SUB{ $module };
103 1         2 last;
104             }
105             }
106             }
107 5         9 return $f;
108             }
109              
110             sub format {
111 4     4   4310 my ( $class, $format, @docs ) = @_;
112 4 50       7 my $f = $class->can_format( $format )
113             or die "Could not load format module for '$format' (tried: "
114             . ( join ", ", $class->format_modules( $format ) )
115             . ")\n";
116 4         9 return $f->( @docs );
117             }
118              
119             exit __PACKAGE__->main( @ARGV ) unless caller(0);
120              
121             __END__