File Coverage

lib/ChordPro/Songbook.pm
Criterion Covered Total %
statement 62 87 71.2
branch 14 24 58.3
condition 15 37 40.5
subroutine 12 14 85.7
pod 0 4 0.0
total 103 166 62.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package main;
4              
5             our $options;
6             our $config;
7              
8             package ChordPro::Songbook;
9              
10 81     81   597 use strict;
  81         202  
  81         2920  
11 81     81   495 use warnings;
  81         195  
  81         2306  
12              
13 81     81   481 use ChordPro;
  81         201  
  81         1835  
14 81     81   506 use ChordPro::Config;
  81         287  
  81         2278  
15 81     81   52790 use ChordPro::Song;
  81         332  
  81         4132  
16              
17 81     81   668 use Carp;
  81         184  
  81         5158  
18 81     81   616 use List::Util qw(any);
  81         205  
  81         4457  
19 81     81   603 use File::LoadLines;
  81         512  
  81         71525  
20              
21             sub new {
22 161     161 0 135922 my ($pkg) = @_;
23 161         2154 bless { songs => [ ] }, $pkg;
24             }
25              
26             sub parse_file {
27 142     142 0 21230 my ( $self, $filename, $opts ) = @_;
28 142   100     809 $opts //= {};
29 142   50     355 my $meta = { %{$config->{meta}}, %{delete $opts->{meta}//{}} };
  142         639  
  142         1167  
30 142   50     444 my $defs = { %{delete $opts->{defs}//{}} };
  142         934  
31              
32             # Check for PDF embedding.
33 142 50       1159 if ( $filename =~ /\.pdf$/i ) {
34 0         0 return $self->embed_file( $filename, $meta, $defs );
35             }
36              
37             # Loadlines sets $opts->{_filesource}.
38 142         958 my $lines = loadlines( $filename, $opts );
39             # Sense crd input and convert if necessary.
40 142 50 33     44729 if ( !(defined($options->{a2crd}) && !$options->{a2crd}) and
      66        
      33        
      66        
41             !$options->{fragment}
42 141     141   2053 and any { /\S/ } @$lines # non-blank lines
43 146     146   1231 and $options->{crd} || !any { /^{\s*\w+/ } @$lines ) {
44             warn("Converting $filename to ChordPro format\n")
45 0 0 0     0 if $options->{verbose} || !($options->{a2crd}||$options->{crd});
      0        
46 0         0 require ChordPro::A2Crd;
47 0         0 $lines = ChordPro::A2Crd::a2crd( { lines => $lines } );
48             }
49              
50 142   50     926 $opts //= {};
51              
52             # Used by tests.
53 142         584 for ( "transpose", "transcode" ) {
54 284 100       1042 next unless exists $opts->{$_};
55 9         44 $config->{settings}->{$_} = $opts->{$_};
56             }
57 142         449 for ( "no-substitute", "no-transpose" ) {
58 284 100       905 next unless exists $opts->{$_};
59 1         6 $options->{$_} = $opts->{$_};
60             }
61 142 100       805 bless $config => ChordPro::Config:: if ref $config eq 'HASH';
62              
63 142         349 my $linecnt = 0;
64 142         302 my $songs = 0;
65 142         542 while ( @$lines ) {
66             my $song = ChordPro::Song
67             # WxChordPro uses temp file _filesource. Add real filename as well.
68             ->new( $opts->{filesource} || $opts->{_filesource} )
69 170   33     2136 ->parse_song( $lines, \$linecnt, {%$meta}, {%$defs} );
70 170         449 $song->{meta}->{songindex} = 1 + @{ $self->{songs} };
  170         1052  
71 170         360 push( @{ $self->{songs} }, $song );
  170         538  
72              
73             # Copy persistent assets to the songbook.
74 170 100       655 if ( $song->{assets} ) {
75 1   50     11 $self->{assets} //= {};
76 1         3 while ( my ($k,$v) = each %{$song->{assets}} ) {
  2         11  
77 1 50       4 next unless $v->{persist};
78 0         0 $self->{assets}->{$k} = $v;
79             }
80             }
81              
82 170 100       964 $songs++ if $song->{body};
83             }
84              
85 142 50 66     610 warn("Warning: No songs found in ", $opts->{_filesource}, "\n")
86             unless $songs || $::running_under_test;
87              
88 142         939 return 1;
89             }
90              
91             sub embed_file {
92 0     0 0   my ( $self, $filename, $meta, $defs ) = @_;
93              
94 0 0         unless ( -s -r $filename ) {
95 0           warn("$filename: $! (skipped)\n");
96 0           return;
97             }
98 0           my $type = "pdf";
99              
100 0           my $song = ChordPro::Song->new( $filename );
101 0           $song->{meta}->{songindex} = 1 + @{ $self->{songs} };
  0            
102             $song->{source} =
103 0           { file => $filename,
104             line => 1,
105             embedding => $type,
106             };
107 0   0       my $title = $defs->{title} // $filename;
108 0           $song->{title} = $title;
109 0           $song->{meta}->{title} = [ $title ];
110 0           push( @{ $self->{songs} }, $song );
  0            
111 0 0         $song->dump(0) if $config->{debug}->{song};
112 0           return 1;
113             }
114              
115             # Used by HTML backend.
116             sub structurize {
117 0     0 0   my ( $self ) = @_;
118              
119 0           foreach my $song ( @{ $self->{songs} } ) {
  0            
120 0           $song->structurize;
121             }
122             }
123              
124             1;