| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #! perl | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 79 |  |  | 79 |  | 6345 | use v5.26; | 
|  | 79 |  |  |  |  | 323 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | package ChordPro; | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 79 |  |  | 79 |  | 939 | use App::Packager; | 
|  | 79 |  |  |  |  | 2788 |  | 
|  | 79 |  |  |  |  | 476 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 79 |  |  | 79 |  | 40390 | use ChordPro::Version; | 
|  | 79 |  |  |  |  | 343 |  | 
|  | 79 |  |  |  |  | 2609 |  | 
| 10 | 79 |  |  | 79 |  | 32320 | use ChordPro::Utils; | 
|  | 79 |  |  |  |  | 236 |  | 
|  | 79 |  |  |  |  | 9425 |  | 
| 11 | 79 |  |  | 79 |  | 38218 | use ChordPro::Chords; | 
|  | 79 |  |  |  |  | 275 |  | 
|  | 79 |  |  |  |  | 3237 |  | 
| 12 | 79 |  |  | 79 |  | 41687 | use ChordPro::Output::Common; | 
|  | 79 |  |  |  |  | 267 |  | 
|  | 79 |  |  |  |  | 6726 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | our $VERSION = $ChordPro::Version::VERSION; | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 NAME | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | ChordPro - A lyrics and chords formatting program | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | perl -MChordpro -e run -- [ options ] [ file ... ] | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | When the associated B program has been installed correctly: | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | chordpro [ options ] [ file ... ] | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | B will read one or more text files containing the lyrics of | 
| 31 |  |  |  |  |  |  | one or many songs plus chord information. B will then | 
| 32 |  |  |  |  |  |  | generate a photo-ready, professional looking, impress-your-friends | 
| 33 |  |  |  |  |  |  | sheet-music suitable for printing on your nearest printer. | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | Typical ChordPro input: | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | {title: Swing Low Sweet Chariot} | 
| 38 |  |  |  |  |  |  | {subtitle: Traditional} | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | {start_of_chorus} | 
| 41 |  |  |  |  |  |  | Swing [D]low, sweet [G]chari[D]ot, | 
| 42 |  |  |  |  |  |  | Comin’ for to carry me [A7]home. | 
| 43 |  |  |  |  |  |  | Swing [D7]low, sweet [G]chari[D]ot, | 
| 44 |  |  |  |  |  |  | Comin’ for to [A7]carry me [D]home. | 
| 45 |  |  |  |  |  |  | {end_of_chorus} | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | # Verse | 
| 48 |  |  |  |  |  |  | I [D]looked over Jordan, and [G]what did I [D]see, | 
| 49 |  |  |  |  |  |  | Comin’ for to carry me [A7]home. | 
| 50 |  |  |  |  |  |  | A [D]band of angels [G]comin’ after [D]me, | 
| 51 |  |  |  |  |  |  | Comin’ for to [A7]carry me [D]home. | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | {c: Chorus} | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | B is a rewrite of the Chordii program. | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | For more information about the ChordPro file format, see | 
| 58 |  |  |  |  |  |  | L. | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | =cut | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | ################ Common stuff ################ | 
| 63 |  |  |  |  |  |  |  | 
| 64 | 79 |  |  | 79 |  | 624 | use strict; | 
|  | 79 |  |  |  |  | 201 |  | 
|  | 79 |  |  |  |  | 2174 |  | 
| 65 | 79 |  |  | 79 |  | 447 | use warnings; | 
|  | 79 |  |  |  |  | 178 |  | 
|  | 79 |  |  |  |  | 2043 |  | 
| 66 | 79 |  |  | 79 |  | 457 | use Carp; | 
|  | 79 |  |  |  |  | 190 |  | 
|  | 79 |  |  |  |  | 4119 |  | 
| 67 | 79 |  |  | 79 |  | 503 | use Text::ParseWords (); | 
|  | 79 |  |  |  |  | 198 |  | 
|  | 79 |  |  |  |  | 63633 |  | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | ################ The Process ################ | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | package main; | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | our $options; | 
| 74 |  |  |  |  |  |  | our $config; | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | package ChordPro; | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | sub ::run { | 
| 79 | 91 |  |  | 91 |  | 351563 | binmode(STDERR, ':utf8'); | 
| 80 | 91 |  |  |  |  | 376 | binmode(STDOUT, ':utf8'); | 
| 81 | 91 |  |  |  |  | 514 | $options = app_setup( "ChordPro", $VERSION ); | 
| 82 | 91 | 50 |  |  |  | 445 | $options->{trace}   = 1 if $options->{debug}; | 
| 83 | 91 | 50 |  |  |  | 383 | $options->{verbose} = 1 if $options->{trace}; | 
| 84 | 91 | 50 |  |  |  | 359 | $options->{verbose} = 9 if $options->{debug}; | 
| 85 | 91 |  |  |  |  | 373 | main(); | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | sub main { | 
| 89 | 91 |  |  | 91 | 0 | 611 | my ($opts) = @_; | 
| 90 | 91 | 50 |  |  |  | 348 | $options = { %$options, %$opts } if $opts; | 
| 91 | 91 | 50 |  |  |  | 364 | warn("ChordPro invoked: @{$options->{_argv}}\n") if $options->{debug}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 92 | 91 |  |  |  |  | 344 | chordpro(); | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | sub chordpro { | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | # Establish backend. | 
| 99 | 91 |  |  | 91 | 0 | 303 | my $of = $options->{output}; | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 91 | 50 | 33 |  |  | 591 | if ( defined($of) && $of ne "" ) { | 
|  |  | 0 |  |  |  |  |  | 
| 102 | 91 | 100 |  |  |  | 1893 | if ( $of =~ /\.pdf$/i ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 103 | 8 |  | 50 |  |  | 69 | $options->{generate} ||= "PDF"; | 
| 104 |  |  |  |  |  |  | } | 
| 105 |  |  |  |  |  |  | elsif ( $of =~ /\.ly$/i ) { | 
| 106 | 0 |  | 0 |  |  | 0 | $options->{generate} ||= "LilyPond"; | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  | elsif ( $of =~ /\.(tex|ltx)$/i ) { | 
| 109 | 0 |  | 0 |  |  | 0 | $options->{generate} ||= "LaTeX"; | 
| 110 |  |  |  |  |  |  | } | 
| 111 |  |  |  |  |  |  | elsif ( $of =~ /\.cho$/i ) { | 
| 112 | 6 |  | 50 |  |  | 37 | $options->{generate} ||= "ChordPro"; | 
| 113 |  |  |  |  |  |  | } | 
| 114 |  |  |  |  |  |  | elsif ( $of =~ /\.msp$/i ) { | 
| 115 | 0 |  | 0 |  |  | 0 | $options->{generate} ||= "ChordPro"; | 
| 116 | 0 |  |  |  |  | 0 | $options->{'backend-option'}->{variant} = "msp"; | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  | elsif ( $of =~ /\.(crd|txt)$/i ) { | 
| 119 | 9 |  | 50 |  |  | 66 | $options->{generate} ||= "Text"; | 
| 120 |  |  |  |  |  |  | } | 
| 121 |  |  |  |  |  |  | elsif ( $of =~ /\.html?$/i ) { | 
| 122 | 3 |  | 50 |  |  | 18 | $options->{generate} ||= "HTML"; | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  | elsif ( $of =~ /\.mma?$/i ) { | 
| 125 | 0 |  | 0 |  |  | 0 | $options->{generate} ||= "MMA"; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  | elsif ( $of =~ /\.(md|markdown)$/i ) { | 
| 128 | 0 |  | 0 |  |  | 0 | $options->{generate} ||= "Markdown"; | 
| 129 |  |  |  |  |  |  | } | 
| 130 |  |  |  |  |  |  | elsif ( $of =~ /\.(debug)$/i ) { | 
| 131 | 0 |  | 0 |  |  | 0 | $options->{generate} ||= "Debug"; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  | elsif ( -t STDOUT ) { | 
| 135 |  |  |  |  |  |  | # No output, and stdout is terminal. | 
| 136 |  |  |  |  |  |  | # Derive output name from input name. | 
| 137 | 0 | 0 | 0 |  |  | 0 | if ( @ARGV > 1 || ( $options->{'dump-chords'} && !@ARGV ) ) { | 
|  |  |  | 0 |  |  |  |  | 
| 138 |  |  |  |  |  |  | # No default if more than one input document. | 
| 139 | 0 |  |  |  |  | 0 | die("Please use \"--output\" to specify the output file name\n"); | 
| 140 |  |  |  |  |  |  | } | 
| 141 | 0 |  |  |  |  | 0 | my $f = $ARGV[0]; | 
| 142 | 0 |  |  |  |  | 0 | $f =~ s/\.\w+$/.pdf/; | 
| 143 | 0 | 0 |  |  |  | 0 | $f .= ".pdf" if $f eq $ARGV[0]; | 
| 144 | 0 |  |  |  |  | 0 | $options->{output} = $f; | 
| 145 | 0 | 0 |  |  |  | 0 | warn("Writing output to $f\n") if $options->{verbose}; | 
| 146 |  |  |  |  |  |  | } | 
| 147 |  |  |  |  |  |  | else { | 
| 148 |  |  |  |  |  |  | # Write output to stdout. | 
| 149 | 0 |  |  |  |  | 0 | $options->{output} = "-"; | 
| 150 |  |  |  |  |  |  | } | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 91 |  | 50 |  |  | 364 | $options->{generate} ||= "PDF"; | 
| 153 | 91 |  |  |  |  | 362 | my $pkg = "ChordPro::Output::".$options->{generate}; | 
| 154 | 91 |  |  |  |  | 11252 | eval "require $pkg;"; | 
| 155 | 91 | 50 |  |  |  | 548 | die("No backend for ", $options->{generate}, "\n$@") if $@; | 
| 156 | 91 |  |  |  |  | 739 | $options->{backend} = $pkg; | 
| 157 | 91 | 50 | 33 |  |  | 576 | $pkg->version if $options->{verbose} && $pkg->can("version"); | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | # One configurator to bind them all. | 
| 160 | 79 |  |  | 79 |  | 1759 | use ChordPro::Config; | 
|  | 79 |  |  |  |  | 251 |  | 
|  | 79 |  |  |  |  | 4819 |  | 
| 161 | 91 |  |  |  |  | 607 | $config = ChordPro::Config::configurator({}); | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | # Parse the input(s). | 
| 164 | 79 |  |  | 79 |  | 36273 | use ChordPro::Songbook; | 
|  | 79 |  |  |  |  | 308 |  | 
|  | 79 |  |  |  |  | 82838 |  | 
| 165 | 91 |  |  |  |  | 1636 | my $s = ChordPro::Songbook->new; | 
| 166 | 91 |  |  |  |  | 234 | my $res; | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | # Shortcut a2crd conversion. | 
| 169 | 91 | 100 |  |  |  | 563 | if ( $options->{a2crd} ) { | 
| 170 | 19 |  |  |  |  | 258 | require ChordPro::A2Crd; | 
| 171 | 19 |  |  |  |  | 160 | $res = ChordPro::A2Crd::a2crd(); | 
| 172 | 19 |  |  |  |  | 82 | push( @$res, '' ); | 
| 173 | 19 |  |  |  |  | 215 | goto WRITE_OUTPUT; | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | # Check for metadata in filelist. Actually, this works on the | 
| 177 |  |  |  |  |  |  | # command line as well, but don't tell anybody. | 
| 178 | 72 |  |  |  |  | 294 | foreach my $file ( @ARGV ) { | 
| 179 | 72 |  |  |  |  | 141 | my $opts; | 
| 180 | 72 | 50 |  |  |  | 397 | if ( $file =~ /(^|\s)--(?:meta|config|define)\b/ ) { | 
| 181 |  |  |  |  |  |  | # Break into words. | 
| 182 | 0 |  |  |  |  | 0 | my @w = Text::ParseWords::shellwords($file); | 
| 183 | 0 |  |  |  |  | 0 | my %meta; | 
| 184 |  |  |  |  |  |  | my %defs; | 
| 185 | 0 |  |  |  |  | 0 | my @cfg; | 
| 186 | 0 | 0 | 0 |  |  | 0 | die("Error in filelist: $file\n") | 
| 187 |  |  |  |  |  |  | unless Getopt::Long::GetOptionsFromArray | 
| 188 |  |  |  |  |  |  | ( \@w, 'config=s@' => \@cfg, 'meta=s%' => \%meta, | 
| 189 |  |  |  |  |  |  | 'define=s%' => \%defs, | 
| 190 |  |  |  |  |  |  | ) | 
| 191 |  |  |  |  |  |  | && @w == 1; | 
| 192 | 0 |  |  |  |  | 0 | $file = $w[0]; | 
| 193 | 0 |  |  |  |  | 0 | $opts = { meta => { map { $_, [ $meta{$_} ] } keys %meta }, | 
|  | 0 |  |  |  |  | 0 |  | 
| 194 |  |  |  |  |  |  | defs => \%defs }; | 
| 195 | 0 | 0 |  |  |  | 0 | if ( @cfg ) { | 
| 196 | 0 |  |  |  |  | 0 | $opts->{meta}->{__config} = \@cfg; | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  | } | 
| 199 | 72 |  |  |  |  | 508 | $s->parse_file( $file, $opts ); | 
| 200 |  |  |  |  |  |  | } | 
| 201 |  |  |  |  |  |  |  | 
| 202 | 72 | 50 |  |  |  | 403 | if ( $options->{'dump-chords'} ) { | 
| 203 | 0 |  |  |  |  | 0 | my $d = ChordPro::Song->new; | 
| 204 | 0 |  |  |  |  | 0 | $d->{title} = "ChordPro $VERSION Built-in Chords"; | 
| 205 | 0 |  |  |  |  | 0 | $d->{subtitle} = [ "https://www.chordpro.org" ]; | 
| 206 | 0 |  |  |  |  | 0 | my @body; | 
| 207 |  |  |  |  |  |  | my @chords; | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 0 |  |  |  |  | 0 | my $prev = ""; | 
| 210 | 0 |  |  |  |  | 0 | foreach my $c ( @{ ChordPro::Chords::chordnames() } ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 211 | 0 | 0 |  |  |  | 0 | next if $c =~ /^n\.?c\.?$/i; | 
| 212 | 0 | 0 | 0 |  |  | 0 | if ( $c =~ /^(.[b#]?)/ and $1 ne $prev )  { | 
| 213 | 0 |  |  |  |  | 0 | $prev = $1; | 
| 214 | 0 | 0 |  |  |  | 0 | push( @body, { type => "diagrams", | 
| 215 |  |  |  |  |  |  | context => "", | 
| 216 |  |  |  |  |  |  | origin => "__CLI__", | 
| 217 |  |  |  |  |  |  | chords => [ @chords ] | 
| 218 |  |  |  |  |  |  | } ) if @chords; | 
| 219 | 0 |  |  |  |  | 0 | @chords = (); | 
| 220 |  |  |  |  |  |  | } | 
| 221 | 0 |  |  |  |  | 0 | push( @chords, $c ); | 
| 222 | 0 |  |  |  |  | 0 | $d->{chordsinfo}->{$c} = ChordPro::Chords::known_chord($c); | 
| 223 |  |  |  |  |  |  | } | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 0 | 0 |  |  |  | 0 | push( @body, { type => "diagrams", | 
| 226 |  |  |  |  |  |  | context => "", | 
| 227 |  |  |  |  |  |  | origin => "__CLI__", | 
| 228 |  |  |  |  |  |  | chords => [ @chords ] | 
| 229 |  |  |  |  |  |  | } ) if @chords; | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 0 |  |  |  |  | 0 | $d->{body} = \@body; | 
| 232 | 0 | 0 | 0 |  |  | 0 | if ( @{ $s->{songs} } == 1 | 
|  | 0 |  |  |  |  | 0 |  | 
| 233 |  |  |  |  |  |  | && !exists $s->{songs}->[0]->{body} ) { | 
| 234 | 0 |  |  |  |  | 0 | $s->{songs} = [ $d ]; | 
| 235 |  |  |  |  |  |  | } | 
| 236 |  |  |  |  |  |  | else { | 
| 237 | 0 |  |  |  |  | 0 | push( @{ $s->{songs} }, $d ); | 
|  | 0 |  |  |  |  | 0 |  | 
| 238 |  |  |  |  |  |  | } | 
| 239 |  |  |  |  |  |  | } | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | # Try interpolations. | 
| 242 | 72 | 50 |  |  |  | 272 | if ( $of ) { | 
| 243 | 72 |  |  |  |  | 398 | my $f = fmt_subst( $s->{songs}->[0], $of ); | 
| 244 | 72 | 50 |  |  |  | 6910 | if ( $f ne $of ) { | 
| 245 |  |  |  |  |  |  | # Replace most non-alpha by underscore (but keep the extension). | 
| 246 | 0 |  |  |  |  | 0 | $f =~ s;(?!\.\w+$)[^\w/-];_;g; | 
| 247 | 0 | 0 |  |  |  | 0 | warn("Writing output to $f\n") if $options->{verbose}; | 
| 248 | 0 |  |  |  |  | 0 | $options->{output} = $f; | 
| 249 |  |  |  |  |  |  | } | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | # Call backend to produce output. | 
| 253 | 72 |  |  |  |  | 913 | $res = $pkg->generate_songbook($s); | 
| 254 | 72 | 100 |  |  |  | 3752 | return $res if $options->{output} eq '*'; | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | WRITE_OUTPUT: | 
| 257 |  |  |  |  |  |  | # Some backends write output themselves, others return an | 
| 258 |  |  |  |  |  |  | # array of lines to be written. | 
| 259 | 79 | 100 | 66 |  |  | 668 | if ( $res && @$res > 0 ) { | 
| 260 | 71 | 50 | 33 |  |  | 437 | if ( $of && $of ne "-" ) { | 
| 261 | 71 |  |  |  |  | 24136 | open( my $fd, '>', $of ); | 
| 262 | 71 |  |  |  |  | 995 | binmode( $fd, ":utf8" ); | 
| 263 | 71 | 100 |  |  |  | 440 | push( @$res, '' ) unless $res->[-1] eq ''; | 
| 264 | 71 |  |  |  |  | 182 | print { $fd } ( join( "\n", @$res ) ); | 
|  | 71 |  |  |  |  | 2593 |  | 
| 265 | 71 |  |  |  |  | 21498 | close($fd); | 
| 266 |  |  |  |  |  |  | } | 
| 267 |  |  |  |  |  |  | else { | 
| 268 | 0 |  |  |  |  | 0 | binmode( STDOUT, ":utf8" ); | 
| 269 | 0 | 0 |  |  |  | 0 | push( @$res, '' ) unless $res->[-1] eq ''; | 
| 270 | 0 |  |  |  |  | 0 | print( join( "\n", @$res ) ); | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  | # Don't close STDOUT! | 
| 273 |  |  |  |  |  |  | } | 
| 274 |  |  |  |  |  |  | } | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | sub ::dump { | 
| 277 | 79 |  |  | 79 |  | 55801 | use Data::Dumper qw(); | 
|  | 79 |  |  |  |  | 544803 |  | 
|  | 79 |  |  |  |  | 16023 |  | 
| 278 | 0 |  |  | 0 |  | 0 | local $Data::Dumper::Sortkeys  = 1; | 
| 279 | 0 |  |  |  |  | 0 | local $Data::Dumper::Indent    = 1; | 
| 280 | 0 |  |  |  |  | 0 | local $Data::Dumper::Quotekeys = 0; | 
| 281 | 0 |  |  |  |  | 0 | local $Data::Dumper::Deparse   = 1; | 
| 282 | 0 |  |  |  |  | 0 | local $Data::Dumper::Terse     = 1; | 
| 283 | 0 |  |  |  |  | 0 | local $Data::Dumper::Trailingcomma = 1; | 
| 284 | 0 |  |  |  |  | 0 | local $Data::Dumper::Useperl = 1; | 
| 285 | 0 |  |  |  |  | 0 | local $Data::Dumper::Useqq     = 0; # I want unicode visible | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 0 |  |  |  |  | 0 | my $s = Data::Dumper::Dumper @_; | 
| 288 | 0 | 0 |  |  |  | 0 | defined wantarray or warn $s; | 
| 289 | 0 |  |  |  |  | 0 | return $s; | 
| 290 |  |  |  |  |  |  | } | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | ################ Options and Configuration ################ | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | =head1 COMMAND LINE OPTIONS | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | =over 4 | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | =item B<--about> (short: B<-A>) | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | Prints version information about the ChordPro program. No other | 
| 301 |  |  |  |  |  |  | processing will be done. | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | =item B<--back-matter=>I | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | Appends the contents of the named PDF document to the output. This can | 
| 306 |  |  |  |  |  |  | be used to produce documents with back matter pages. | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | =item B<--config=>I (shorter: B<--cfg>) | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | A JSON file that defines the behaviour of the program and the layout | 
| 311 |  |  |  |  |  |  | of the output. See L for details. | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | This option may be specified more than once. Each additional config | 
| 314 |  |  |  |  |  |  | file overrides the corresponding definitions that are currently | 
| 315 |  |  |  |  |  |  | active. | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | =item B<--cover=>I | 
| 318 |  |  |  |  |  |  |  | 
| 319 |  |  |  |  |  |  | See B<--front-matter>. | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | =item B<--csv> | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | When generating PDF output, also write a CSV file with titles and page | 
| 324 |  |  |  |  |  |  | numbers. Some tools, e.g., MobileSheets, can use the CSV to process | 
| 325 |  |  |  |  |  |  | the PDF as a collection of independent songs. | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | The CSV has the same name  as the PDF, with extension C<.pdf> replaced | 
| 328 |  |  |  |  |  |  | by C<.csv>. | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | =item B<--decapo> | 
| 331 |  |  |  |  |  |  |  | 
| 332 |  |  |  |  |  |  | Eliminate capo settings by transposing the song. | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  | =item B<--diagrams=>I | 
| 335 |  |  |  |  |  |  |  | 
| 336 |  |  |  |  |  |  | Prints diagrams of chords used in a song. | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | I can be C to print all chords used, C to only print | 
| 339 |  |  |  |  |  |  | the user-defined chords, and C to suppress printing of chord | 
| 340 |  |  |  |  |  |  | diagrams. | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | =item B<--encoding=>I | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | Specify the encoding for input files. Default is UTF-8. | 
| 345 |  |  |  |  |  |  | ISO-8859.1 (Latin-1) encoding is automatically sensed. | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | =item B<--filelist=>I | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | Read the names of the files to be processed from the named file. | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | This option may be specified multiple times. | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | Song file names listed on the command line are processed I the | 
| 354 |  |  |  |  |  |  | files from the filelist arguments. | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | =item B<--front-matter=>I B<--cover=>I | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | Prepends the contents of the named PDF document to the output. This can | 
| 359 |  |  |  |  |  |  | be used to produce documents with front matter (cover) pages. | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | =item B<--lyrics-only> (short: B<-l>) | 
| 362 |  |  |  |  |  |  |  | 
| 363 |  |  |  |  |  |  | Only prints lyrics. All chords are suppressed. | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | Useful to make prints for singers and other musicians that do not | 
| 366 |  |  |  |  |  |  | require chords. | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | =item B<--no-csv> | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  | Suppresses generating the CSV file. See B<--toc>. | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | =item B<--no-strict> | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | Enables liberal interpretation of the input with regard to the | 
| 375 |  |  |  |  |  |  | ChordPro standard. Most notably, unknown directives will not | 
| 376 |  |  |  |  |  |  | not flagged as warnings but silently ignored. | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | This makes it more convenient to process ChordPro files have custom | 
| 379 |  |  |  |  |  |  | directives. | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | =item B<--no-toc> | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | Suppresses the table of contents. See B<--toc>. | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | =item B<--output=>I (short: B<-o>) | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | Designates the name of the output file where the results are written | 
| 388 |  |  |  |  |  |  | to. | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | The filename extension determines the type of the output. It should | 
| 391 |  |  |  |  |  |  | correspond to one of the backends that are currently supported: | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | =over 6 | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | =item pdf | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | Portable document format (PDF). | 
| 398 |  |  |  |  |  |  |  | 
| 399 |  |  |  |  |  |  | =item txt | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | A textual representation of the input, mostly for visual inspection. | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | =item cho | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | A functional equivalent version of the ChordPro input. | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | =back | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | =item B<--start-page-number=>I (short: B<-p>) | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  | Sets the starting page number for the output. | 
| 412 |  |  |  |  |  |  |  | 
| 413 |  |  |  |  |  |  | =item B<--strict> | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | Requires the input to be strictly compliant to the ChordPro standard. | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  | This is enabled by default. See also B<--nostrict>. | 
| 418 |  |  |  |  |  |  |  | 
| 419 |  |  |  |  |  |  | =item B<--toc> (short: B<-i>) | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | Includes a table of contents. | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | By default a table of contents is included in the PDF output when | 
| 424 |  |  |  |  |  |  | it contains more than one song. | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | =item B<--transpose=>I (short: -x) | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | Transposes all songs by I semi-tones. Note that I may be | 
| 429 |  |  |  |  |  |  | specified as B<+>I to transpose upward, using sharps, or as | 
| 430 |  |  |  |  |  |  | B<->I to transpose downward, using flats. | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | =item B<--version> (short: B<-V>) | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | Prints the program version and exits. | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | =back | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | =head2 Chordii compatibility options | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | The following Chordii command line options are recognized. Note that | 
| 441 |  |  |  |  |  |  | not all of them actually do something. | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | Options marked with * are better specified in the config file. | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  | B Chordii used the term _grid_ for chord diagrams. It | 
| 446 |  |  |  |  |  |  | should not be confused with ChordPro grids. | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | =over 4 | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | =item B<--text-font=>I (short: B<-T>) * | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | Sets the font used to print lyrics and comments. | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | I can be either a full path name to a TrueType font file, or the | 
| 455 |  |  |  |  |  |  | name of one of the standard fonts. See section L for more | 
| 456 |  |  |  |  |  |  | details. | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | =item B<--text-size=>I (short: B<-t>) * | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | Sets the font size for lyrics and comments. | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | =item B<--chord-font=>I (short: B<-C>) * | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | Sets the font used to print the chord names. | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | I can be either a full path name to a TrueType font file, or the | 
| 467 |  |  |  |  |  |  | name of one of the standard fonts. See section L for more | 
| 468 |  |  |  |  |  |  | details. | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | =item B<--chord-size=>I (short: B<-c>) * | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  | Sets the font size for the chord names. | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  | =item B<--chord-grid-size=>I (short: B<-s>) * | 
| 475 |  |  |  |  |  |  |  | 
| 476 |  |  |  |  |  |  | Sets the total width of a chord diagram. | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | =item B<--chord-grids> | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | Prints chord diagrams of all chords used in a song. | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | =item B<--no-chord-grids> (short: B<-G>) * | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  | Disables printing of chord diagrams of the chords used in a song. | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | =item B<--easy-chord-grids> | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | Not supported. | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | =item B<--no-easy-chord-grids> (short: B<-g>) | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  | Not supported. | 
| 493 |  |  |  |  |  |  |  | 
| 494 |  |  |  |  |  |  | =item B<--chord-grids-sorted> (short: B<-S>) * | 
| 495 |  |  |  |  |  |  |  | 
| 496 |  |  |  |  |  |  | Prints chord diagrams of the chords used in a song, ordered by key and | 
| 497 |  |  |  |  |  |  | type. | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | =item B<--no-chord-grids-sorted> * | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | Prints chord diagrams in the order they appear in the song. | 
| 502 |  |  |  |  |  |  |  | 
| 503 |  |  |  |  |  |  | =item B<--user-chord-grids> * | 
| 504 |  |  |  |  |  |  |  | 
| 505 |  |  |  |  |  |  | Prints chord diagrams of all user defined chords used in a song. | 
| 506 |  |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  | =item B<--even-pages-number-left> (short B<-L>) | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | Prints even/odd pages with pages numbers left on even pages. | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  | =item B<--odd-pages-number-left> | 
| 512 |  |  |  |  |  |  |  | 
| 513 |  |  |  |  |  |  | Prints even/odd pages with pages numbers left on odd pages. | 
| 514 |  |  |  |  |  |  |  | 
| 515 |  |  |  |  |  |  | =item B<--page-size=>I (short: B<-P>) * | 
| 516 |  |  |  |  |  |  |  | 
| 517 |  |  |  |  |  |  | Specifies the page size for the PDF output, e.g. C (default), C. | 
| 518 |  |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  | =item B<--single-space> (short B<-a>)) * | 
| 520 |  |  |  |  |  |  |  | 
| 521 |  |  |  |  |  |  | When a lyrics line has no chords associated, suppresses the vertical | 
| 522 |  |  |  |  |  |  | space normally occupied by the chords. | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | =item B<--vertical-space=>I (short: B<-w>) * | 
| 525 |  |  |  |  |  |  |  | 
| 526 |  |  |  |  |  |  | Adds some extra vertical space between the lines. | 
| 527 |  |  |  |  |  |  |  | 
| 528 |  |  |  |  |  |  | =item B<--2-up> (short: B<-2>) | 
| 529 |  |  |  |  |  |  |  | 
| 530 |  |  |  |  |  |  | Not supported. | 
| 531 |  |  |  |  |  |  |  | 
| 532 |  |  |  |  |  |  | =item B<--4-up> (short: B<-4>) | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | Not supported. | 
| 535 |  |  |  |  |  |  |  | 
| 536 |  |  |  |  |  |  | =item B<--page-number-logical> (short: B<-n>) | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | Not supported. | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | =item B<--dump-chords> (short: B<-D>) | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | Dumps a list of built-in chords in a form dependent of the backend used. | 
| 543 |  |  |  |  |  |  | The PDF backend will produce neat pages of chord diagrams. | 
| 544 |  |  |  |  |  |  | The ChordPro backend will produce a list of C directives. | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | =item B<--dump-chords-text> (short: B<-d>) | 
| 547 |  |  |  |  |  |  |  | 
| 548 |  |  |  |  |  |  | Dumps a list of built-in chords in the form of C directives, | 
| 549 |  |  |  |  |  |  | and exits. | 
| 550 |  |  |  |  |  |  |  | 
| 551 |  |  |  |  |  |  | =back | 
| 552 |  |  |  |  |  |  |  | 
| 553 |  |  |  |  |  |  | =head2 Configuration options | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  | See L for details about the configuration | 
| 556 |  |  |  |  |  |  | files. | 
| 557 |  |  |  |  |  |  |  | 
| 558 |  |  |  |  |  |  | Note that missing default configuration files are silently ignored. | 
| 559 |  |  |  |  |  |  | Also, B will never create nor write configuration files. | 
| 560 |  |  |  |  |  |  |  | 
| 561 |  |  |  |  |  |  | =over | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | =item B<--nosongconfig> | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | Don't use song specific config files, even if they exist. | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | =item B<--sysconfig=>I | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | Designates a system specific config file. | 
| 570 |  |  |  |  |  |  |  | 
| 571 |  |  |  |  |  |  | The default system config file depends on the operating system and user | 
| 572 |  |  |  |  |  |  | environment. A common value is C on Linux systems. | 
| 573 |  |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | This is the place where the system manager can put settings like the | 
| 575 |  |  |  |  |  |  | paper size, assuming that all printers use the same size. | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | =item B<--nosysconfig> | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | Don't use the system specific config file, even if it exists. | 
| 580 |  |  |  |  |  |  |  | 
| 581 |  |  |  |  |  |  | =item B<--userconfig=>I | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | Designates the config file for the user. | 
| 584 |  |  |  |  |  |  |  | 
| 585 |  |  |  |  |  |  | The default user config file depends on the operating system and user | 
| 586 |  |  |  |  |  |  | environment. Common values are C<$HOME/.config/chordpro/chordpro.json> | 
| 587 |  |  |  |  |  |  | and C<$HOME/.chordpro/chordpro.json>, where C<$HOME> indicates the | 
| 588 |  |  |  |  |  |  | user home directory. | 
| 589 |  |  |  |  |  |  |  | 
| 590 |  |  |  |  |  |  | Here you can put settings for your preferred fonts and other layout | 
| 591 |  |  |  |  |  |  | parameters that you want to apply to all B runs. | 
| 592 |  |  |  |  |  |  |  | 
| 593 |  |  |  |  |  |  | =item B<--nouserconfig> | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | Don't use the user specific config file, even if it exists. | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | =item B<--config=>I (shorter: B<--cfg>) | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | Designates the config file specific for this run. | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | Default is a file named C in the current directory. | 
| 602 |  |  |  |  |  |  |  | 
| 603 |  |  |  |  |  |  | Here you can put settings that apply to the files in this | 
| 604 |  |  |  |  |  |  | directory only. | 
| 605 |  |  |  |  |  |  |  | 
| 606 |  |  |  |  |  |  | You can specify multiple config files. The settings are accumulated. | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  | =item B<--noconfig> | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | Don't use the specific config file, even if it exists. | 
| 611 |  |  |  |  |  |  |  | 
| 612 |  |  |  |  |  |  | =item B<--define=>I   | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | Sets a configuration item. I  must be in the format of  | 
| 615 |  |  |  |  |  |  | colon-separated configuration keys, an equal sign, and the value. For | 
| 616 |  |  |  |  |  |  | example, the equivalent of B<--diagrams=none> is | 
| 617 |  |  |  |  |  |  | B<--define=diagrams:show=0>. | 
| 618 |  |  |  |  |  |  |  | 
| 619 |  |  |  |  |  |  | B<--define> may be used multiple times to set multiple items. | 
| 620 |  |  |  |  |  |  |  | 
| 621 |  |  |  |  |  |  | =item B<--no-default-configs> (short: B<-X>) | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | Do not use any config files except the ones mentioned explicitly on | 
| 624 |  |  |  |  |  |  | the command line. | 
| 625 |  |  |  |  |  |  |  | 
| 626 |  |  |  |  |  |  | This guarantees that the program is running with the default | 
| 627 |  |  |  |  |  |  | configuration. | 
| 628 |  |  |  |  |  |  |  | 
| 629 |  |  |  |  |  |  | =item B<--print-default-config> | 
| 630 |  |  |  |  |  |  |  | 
| 631 |  |  |  |  |  |  | Prints the default configuration to standard output, and exits. | 
| 632 |  |  |  |  |  |  |  | 
| 633 |  |  |  |  |  |  | The default configuration is commented to explain its contents. | 
| 634 |  |  |  |  |  |  |  | 
| 635 |  |  |  |  |  |  | =item B<--print-final-config> | 
| 636 |  |  |  |  |  |  |  | 
| 637 |  |  |  |  |  |  | Prints the final configuration (after processing all system, user and | 
| 638 |  |  |  |  |  |  | other config files)  to standard output, and exits. | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | The final configuration is not commented. Sorry. | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | =back | 
| 643 |  |  |  |  |  |  |  | 
| 644 |  |  |  |  |  |  | =head2 Miscellaneous options | 
| 645 |  |  |  |  |  |  |  | 
| 646 |  |  |  |  |  |  | =over | 
| 647 |  |  |  |  |  |  |  | 
| 648 |  |  |  |  |  |  | =item B<--help> (short: -h) | 
| 649 |  |  |  |  |  |  |  | 
| 650 |  |  |  |  |  |  | Prints a help message. No other output is produced. | 
| 651 |  |  |  |  |  |  |  | 
| 652 |  |  |  |  |  |  | =item B<--manual> | 
| 653 |  |  |  |  |  |  |  | 
| 654 |  |  |  |  |  |  | Prints the manual page. No other output is produced. | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | =item B<--ident> | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | Shows the program name and version. | 
| 659 |  |  |  |  |  |  |  | 
| 660 |  |  |  |  |  |  | =item B<--verbose> | 
| 661 |  |  |  |  |  |  |  | 
| 662 |  |  |  |  |  |  | Provides more verbose information of what is going on. | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | =back | 
| 665 |  |  |  |  |  |  |  | 
| 666 |  |  |  |  |  |  | =cut | 
| 667 |  |  |  |  |  |  |  | 
| 668 | 79 |  |  | 79 |  | 63456 | use Getopt::Long 2.13 qw( :config no_ignorecase ); | 
|  | 79 |  |  |  |  | 1087565 |  | 
|  | 79 |  |  |  |  | 2430 |  | 
| 669 | 79 |  |  | 79 |  | 16670 | use File::Spec; | 
|  | 79 |  |  |  |  | 237 |  | 
|  | 79 |  |  |  |  | 2560 |  | 
| 670 | 79 |  |  | 79 |  | 487 | use File::LoadLines; | 
|  | 79 |  |  |  |  | 216 |  | 
|  | 79 |  |  |  |  | 157781 |  | 
| 671 |  |  |  |  |  |  |  | 
| 672 |  |  |  |  |  |  | # Package name. | 
| 673 |  |  |  |  |  |  | my $my_package; | 
| 674 |  |  |  |  |  |  | # Program name and version. | 
| 675 |  |  |  |  |  |  | my ($my_name, $my_version); | 
| 676 |  |  |  |  |  |  | my %configs; | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | sub app_setup { | 
| 679 | 91 |  |  | 91 | 0 | 422 | my ($appname, $appversion, %args) = @_; | 
| 680 | 91 |  |  |  |  | 315 | my $help = 0;               # handled locally | 
| 681 | 91 |  |  |  |  | 606 | my $manual = 0;             # handled locally | 
| 682 | 91 |  |  |  |  | 231 | my $ident = 0;              # handled locally | 
| 683 | 91 |  |  |  |  | 205 | my $about = 0;              # handled locally | 
| 684 | 91 |  |  |  |  | 185 | my $version = 0;            # handled locally | 
| 685 | 91 |  |  |  |  | 214 | my $defcfg = 0;		# handled locally | 
| 686 | 91 |  |  |  |  | 248 | my $fincfg = 0;		# handled locally | 
| 687 | 91 |  |  |  |  | 193 | my $deltacfg = 0;		# handled locally | 
| 688 | 91 |  |  |  |  | 233 | my $dump_chords = 0;	# handled locally | 
| 689 |  |  |  |  |  |  |  | 
| 690 |  |  |  |  |  |  | # Package name. | 
| 691 | 91 |  |  |  |  | 277 | $my_package = $args{package}; | 
| 692 |  |  |  |  |  |  | # Program name and version. | 
| 693 | 91 | 50 |  |  |  | 407 | if ( defined $appname ) { | 
| 694 | 91 |  |  |  |  | 367 | ($my_name, $my_version) = ($appname, $appversion); | 
| 695 |  |  |  |  |  |  | } | 
| 696 |  |  |  |  |  |  | else { | 
| 697 | 0 |  |  |  |  | 0 | ($my_name, $my_version) = qw( MyProg 0.01 ); | 
| 698 |  |  |  |  |  |  | } | 
| 699 |  |  |  |  |  |  |  | 
| 700 | 91 |  |  |  |  | 360 | my $app_lc = lc($my_name); | 
| 701 | 91 | 50 |  |  |  | 426 | if ( $app_lc eq "a2crd" ) { | 
| 702 | 0 |  |  |  |  | 0 | $app_lc = "chordpro"; | 
| 703 | 0 |  |  |  |  | 0 | unshift( @ARGV, "--a2crd" ); | 
| 704 |  |  |  |  |  |  | } | 
| 705 |  |  |  |  |  |  |  | 
| 706 |  |  |  |  |  |  | # Config files. | 
| 707 | 91 | 50 |  |  |  | 1881 | if ( -d "/etc" ) {          # some *ux | 
| 708 |  |  |  |  |  |  | $configs{sysconfig} = | 
| 709 | 91 |  |  |  |  | 2480 | File::Spec->catfile( "/", "etc", "$app_lc.json" ); | 
| 710 |  |  |  |  |  |  | } | 
| 711 |  |  |  |  |  |  |  | 
| 712 | 91 | 50 | 33 |  |  | 2447 | if ( $ENV{XDG_CONFIG_HOME} && -d $ENV{XDG_CONFIG_HOME} ) { | 
|  |  | 50 | 33 |  |  |  |  | 
| 713 |  |  |  |  |  |  | $configs{userconfig} = | 
| 714 | 0 |  |  |  |  | 0 | File::Spec->catfile( $ENV{XDG_CONFIG_HOME}, $app_lc, "$app_lc.json" ); | 
| 715 | 0 |  | 0 |  |  | 0 | $ENV{CHORDPRO_LIB} ||= File::Spec->catfile( $ENV{XDG_CONFIG_HOME}, $app_lc); | 
| 716 |  |  |  |  |  |  | } | 
| 717 |  |  |  |  |  |  | elsif ( $ENV{HOME} && -d $ENV{HOME} ) { | 
| 718 | 91 |  |  |  |  | 1157 | my $dir = File::Spec->catfile( $ENV{HOME}, ".config" ); | 
| 719 | 91 | 50 |  |  |  | 1178 | if ( -d $dir ) { | 
| 720 |  |  |  |  |  |  | $configs{userconfig} = | 
| 721 | 0 |  |  |  |  | 0 | File::Spec->catfile( $dir, $app_lc, "$app_lc.json" ); | 
| 722 | 0 |  | 0 |  |  | 0 | $ENV{CHORDPRO_LIB} ||= File::Spec->catfile( $dir, $app_lc ); | 
| 723 |  |  |  |  |  |  | } | 
| 724 |  |  |  |  |  |  | else { | 
| 725 | 91 |  |  |  |  | 1094 | $dir = File::Spec->catfile( $ENV{HOME}, ".$app_lc" ); | 
| 726 |  |  |  |  |  |  | $configs{userconfig} = | 
| 727 | 91 |  |  |  |  | 1006 | File::Spec->catfile( $dir, "$app_lc.json" ); | 
| 728 | 91 |  | 66 |  |  | 817 | $ENV{CHORDPRO_LIB} ||= $dir; | 
| 729 |  |  |  |  |  |  | } | 
| 730 |  |  |  |  |  |  | } | 
| 731 |  |  |  |  |  |  |  | 
| 732 | 91 | 50 |  |  |  | 1285 | if ( -s ".$app_lc.json" ) { | 
| 733 | 0 |  |  |  |  | 0 | $configs{config} = ".$app_lc.json"; | 
| 734 |  |  |  |  |  |  | } | 
| 735 |  |  |  |  |  |  | else { | 
| 736 | 91 |  |  |  |  | 538 | $configs{config} = "$app_lc.json"; | 
| 737 |  |  |  |  |  |  | } | 
| 738 |  |  |  |  |  |  |  | 
| 739 | 91 |  |  |  |  | 1687 | my $options = | 
| 740 |  |  |  |  |  |  | { | 
| 741 |  |  |  |  |  |  | verbose          => 0,           # verbose processing | 
| 742 |  |  |  |  |  |  | encoding         => "",          # input encoding, default UTF-8 | 
| 743 |  |  |  |  |  |  |  | 
| 744 |  |  |  |  |  |  | ### ADDITIONAL CLI OPTIONS ### | 
| 745 |  |  |  |  |  |  |  | 
| 746 |  |  |  |  |  |  | 'vertical-space' => 0,           # extra vertical space between lines | 
| 747 |  |  |  |  |  |  |  | 
| 748 |  |  |  |  |  |  | ### NON-CLI OPTIONS ### | 
| 749 |  |  |  |  |  |  |  | 
| 750 |  |  |  |  |  |  | 'chords-column'  => 0,           # chords in a separate column | 
| 751 |  |  |  |  |  |  |  | 
| 752 |  |  |  |  |  |  | # Development options (not shown with -help). | 
| 753 |  |  |  |  |  |  | debug            => 0,           # debugging | 
| 754 |  |  |  |  |  |  | trace            => 0,           # trace (show process) | 
| 755 |  |  |  |  |  |  |  | 
| 756 |  |  |  |  |  |  | # Service. | 
| 757 |  |  |  |  |  |  | _package         => $my_package, | 
| 758 |  |  |  |  |  |  | _name            => $my_name, | 
| 759 |  |  |  |  |  |  | _version         => $my_version, | 
| 760 |  |  |  |  |  |  | _stdin           => \*STDIN, | 
| 761 |  |  |  |  |  |  | _stdout          => \*STDOUT, | 
| 762 |  |  |  |  |  |  | _stderr          => \*STDERR, | 
| 763 |  |  |  |  |  |  | _argv            => [ @ARGV ], | 
| 764 |  |  |  |  |  |  | }; | 
| 765 |  |  |  |  |  |  |  | 
| 766 |  |  |  |  |  |  | # Colled command line options in a hash, for they will be needed | 
| 767 |  |  |  |  |  |  | # later. | 
| 768 | 91 |  |  |  |  | 285 | my $clo = {}; | 
| 769 |  |  |  |  |  |  |  | 
| 770 |  |  |  |  |  |  | # When running in reference mode, we carefully defeat everything | 
| 771 |  |  |  |  |  |  | # the user could change to the built-in default config. | 
| 772 | 91 |  |  |  |  | 248 | my $reference = 0; | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | # Sorry, layout is a bit ugly... | 
| 775 |  |  |  |  |  |  | my $ok = | 
| 776 |  |  |  |  |  |  | GetOptions | 
| 777 |  |  |  |  |  |  | ($clo, | 
| 778 |  |  |  |  |  |  |  | 
| 779 |  |  |  |  |  |  | ### Options ### | 
| 780 |  |  |  |  |  |  |  | 
| 781 |  |  |  |  |  |  | "a2crd!",			# perform ascii to cho | 
| 782 |  |  |  |  |  |  | "crd",			# input is ascii, not cho | 
| 783 |  |  |  |  |  |  | "output|o=s",                 # Saves the output to FILE | 
| 784 |  |  |  |  |  |  | "generate=s", | 
| 785 |  |  |  |  |  |  | "backend-option|bo=s\%", | 
| 786 |  |  |  |  |  |  | "diagrams=s",			# Prints chord diagrams | 
| 787 |  |  |  |  |  |  | "encoding=s", | 
| 788 |  |  |  |  |  |  | "csv!",			# Generates contents CSV | 
| 789 |  |  |  |  |  |  | "front-matter|cover=s",	# Front matter page(s) | 
| 790 |  |  |  |  |  |  | "back-matter=s",		# Back matter page(s) | 
| 791 |  |  |  |  |  |  | "filelist=s@",		# List of input files | 
| 792 |  |  |  |  |  |  | "meta=s\%",			# Command line meta data | 
| 793 |  |  |  |  |  |  | "decapo",			# remove capo | 
| 794 |  |  |  |  |  |  | "fragment|F",			# partial (incomplete) song | 
| 795 |  |  |  |  |  |  | "strict!",			# strict conformance | 
| 796 |  |  |  |  |  |  |  | 
| 797 |  |  |  |  |  |  | ### Standard Chordii Options ### | 
| 798 |  |  |  |  |  |  |  | 
| 799 |  |  |  |  |  |  | "about|A" => \$about,         # About... | 
| 800 |  |  |  |  |  |  | "chord-font|C=s",             # Sets chord font | 
| 801 |  |  |  |  |  |  | "chord-grid-size|s=f",        # Sets chord diagram size [30] | 
| 802 |  |  |  |  |  |  | "chord-grids-sorted|S!",      # Prints chord diagrams ordered | 
| 803 |  |  |  |  |  |  | "chord-size|c=i",             # Sets chord size [9] | 
| 804 |  |  |  |  |  |  | "dump-chords|D",              # Dumps chords definitions (PostScript) | 
| 805 |  |  |  |  |  |  | "dump-chords-text|d" => \$dump_chords,  # Dumps chords definitions (Text) | 
| 806 | 0 |  |  | 0 |  | 0 | "dump-chords-json" => sub { $dump_chords = 2},  # Dumps instrument defs (json). | 
| 807 |  |  |  |  |  |  | "even-pages-number-left|L",   # Even pages numbers on left | 
| 808 |  |  |  |  |  |  | "odd-pages-number-left",      # Odd pages numbers on left | 
| 809 |  |  |  |  |  |  | "lyrics-only|l",              # Only prints lyrics | 
| 810 | 0 |  |  | 0 |  | 0 | "G" => sub { $clo->{'chord-grids'} = 0 }, | 
| 811 |  |  |  |  |  |  | "chord-grids!",               # En[dis]ables printing of chord diagrams | 
| 812 |  |  |  |  |  |  | "easy-chord-grids|g!",        # Do[esn't] print diagrams for built-in "easy" chords. Ignored. | 
| 813 |  |  |  |  |  |  | "page-number-logical|n",      # Numbers logical pages, not physical | 
| 814 |  |  |  |  |  |  | "page-size|P=s",              # Specifies page size [letter, a4 (default)] | 
| 815 |  |  |  |  |  |  | "single-space|a!",            # Automatic single space lines without chords | 
| 816 |  |  |  |  |  |  | "start-page-number|p=i",      # Starting page number [1] | 
| 817 |  |  |  |  |  |  | "text-size|t=i",              # Sets text size [12] | 
| 818 |  |  |  |  |  |  | "text-font|T=s",              # Sets text font | 
| 819 | 0 |  |  | 0 |  | 0 | "i" => sub { $clo->{toc} = 1 }, | 
| 820 |  |  |  |  |  |  | "toc!",                       # Generates a table of contents | 
| 821 |  |  |  |  |  |  | "transpose|x=i",              # Transposes by N semi-tones | 
| 822 |  |  |  |  |  |  | "transcode|xc=s",             # Transcodes to another notation | 
| 823 |  |  |  |  |  |  | "user-chord-grids!",          # Do[esn't] print diagrams for user defined chords. | 
| 824 |  |  |  |  |  |  | "version|V" => \$version,     # Prints version and exits | 
| 825 |  |  |  |  |  |  | "vertical-space|w=f",         # Extra vertical space between lines | 
| 826 |  |  |  |  |  |  | "2-up|2",                     # 2 pages per sheet | 
| 827 |  |  |  |  |  |  | "4-up|4",                     # 4 pages per sheet | 
| 828 |  |  |  |  |  |  |  | 
| 829 |  |  |  |  |  |  | ### Configuration handling ### | 
| 830 |  |  |  |  |  |  |  | 
| 831 |  |  |  |  |  |  | 'config|cfg=s@', | 
| 832 |  |  |  |  |  |  | 'noconfig|no-config', | 
| 833 |  |  |  |  |  |  | 'sysconfig=s', | 
| 834 |  |  |  |  |  |  | 'nosysconfig|no-sysconfig', | 
| 835 |  |  |  |  |  |  | 'nolegacyconfig|no-legacyconfig',	# legacy | 
| 836 |  |  |  |  |  |  | 'userconfig=s', | 
| 837 |  |  |  |  |  |  | 'nosongconfig|no-songconfig', | 
| 838 |  |  |  |  |  |  | 'nouserconfig|no-userconfig', | 
| 839 |  |  |  |  |  |  | 'nodefaultconfigs|no-default-configs|X', | 
| 840 |  |  |  |  |  |  | 'define=s%', | 
| 841 |  |  |  |  |  |  | 'print-default-config' => \$defcfg, | 
| 842 |  |  |  |  |  |  | 'print-final-config'   => \$fincfg, | 
| 843 |  |  |  |  |  |  | 'print-delta-config'   => \$deltacfg, | 
| 844 |  |  |  |  |  |  |  | 
| 845 |  |  |  |  |  |  | # This aborts option scanning. | 
| 846 | 0 |  |  | 0 |  | 0 | 'reference|R'		 => sub { $reference++; die("!FINISH!"); }, | 
|  | 0 |  |  |  |  | 0 |  | 
| 847 |  |  |  |  |  |  |  | 
| 848 |  |  |  |  |  |  | ### Standard options ### | 
| 849 |  |  |  |  |  |  |  | 
| 850 |  |  |  |  |  |  | 'ident'               => \$ident, | 
| 851 |  |  |  |  |  |  | 'help|h|?'            => \$help, | 
| 852 | 0 |  |  | 0 |  | 0 | 'help-config'         => sub { $manual = 2 }, | 
| 853 | 91 |  |  |  |  | 2354 | 'manual'              => \$manual, | 
| 854 |  |  |  |  |  |  | 'verbose|v+', | 
| 855 |  |  |  |  |  |  | 'trace', | 
| 856 |  |  |  |  |  |  | 'debug+', | 
| 857 |  |  |  |  |  |  |  | 
| 858 |  |  |  |  |  |  | ); | 
| 859 |  |  |  |  |  |  |  | 
| 860 |  |  |  |  |  |  | # If --reference was encountered, retry with a very restricted set | 
| 861 |  |  |  |  |  |  | # of options. | 
| 862 | 91 | 50 |  |  |  | 441897 | if ( $reference ) { | 
| 863 | 0 |  |  |  |  | 0 | @ARGV = @{ $options->{_argv} }; | 
|  | 0 |  |  |  |  | 0 |  | 
| 864 | 0 |  |  |  |  | 0 | warn("Running in reference mode.\n"); | 
| 865 | 0 |  |  |  |  | 0 | $ok = | 
| 866 |  |  |  |  |  |  | GetOptions | 
| 867 |  |  |  |  |  |  | ($clo, | 
| 868 |  |  |  |  |  |  |  | 
| 869 |  |  |  |  |  |  | ### Options for reference run ### | 
| 870 |  |  |  |  |  |  |  | 
| 871 |  |  |  |  |  |  | "output|o=s",                 # Saves the output to FILE | 
| 872 |  |  |  |  |  |  | "strict!",			# strict conformance | 
| 873 |  |  |  |  |  |  | "about|A" => \$about,         # About... | 
| 874 |  |  |  |  |  |  | "version|V" => \$version,     # Prints version and exits | 
| 875 |  |  |  |  |  |  | 'reference|R', | 
| 876 |  |  |  |  |  |  |  | 
| 877 |  |  |  |  |  |  | ### Standard options ### | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | 'ident'               => \$ident, | 
| 880 |  |  |  |  |  |  | 'help|h|?'            => \$help, | 
| 881 |  |  |  |  |  |  | 'verbose|v+', | 
| 882 |  |  |  |  |  |  | 'trace', | 
| 883 |  |  |  |  |  |  | 'debug+', | 
| 884 |  |  |  |  |  |  |  | 
| 885 |  |  |  |  |  |  | ); | 
| 886 | 0 |  |  |  |  | 0 | $clo->{nodefaultconfigs} = 1; | 
| 887 | 0 |  |  |  |  | 0 | $clo->{nosongconfig} = 1; | 
| 888 | 0 |  |  |  |  | 0 | $::options->{reference} = 1; | 
| 889 |  |  |  |  |  |  | } | 
| 890 |  |  |  |  |  |  |  | 
| 891 | 91 |  | 33 |  |  | 759 | $clo->{trace} ||= $clo->{debug}; | 
| 892 | 91 |  | 33 |  |  | 710 | $clo->{verbose} ||= $clo->{trace}; | 
| 893 |  |  |  |  |  |  |  | 
| 894 | 91 | 50 |  |  |  | 319 | unless ( $ok ) { | 
| 895 |  |  |  |  |  |  | # GNU convention: message to STDERR upon failure. | 
| 896 | 0 |  |  |  |  | 0 | app_usage(\*STDERR, 2); | 
| 897 |  |  |  |  |  |  | } | 
| 898 |  |  |  |  |  |  |  | 
| 899 |  |  |  |  |  |  | my $pod2usage = sub { | 
| 900 |  |  |  |  |  |  | # Load Pod::Usage only if needed. | 
| 901 | 0 |  |  | 0 |  | 0 | require Pod::Usage; | 
| 902 | 0 |  |  |  |  | 0 | Pod::Usage->import; | 
| 903 | 0 | 0 |  |  |  | 0 | my $f = $manual == 2 ? "pod/Config.pod" : "pod/ChordPro.pod"; | 
| 904 | 0 |  |  |  |  | 0 | unshift( @_, -input => getresource($f) ); | 
| 905 | 0 |  |  |  |  | 0 | &pod2usage; | 
| 906 | 91 |  |  |  |  | 616 | }; | 
| 907 |  |  |  |  |  |  |  | 
| 908 |  |  |  |  |  |  | # GNU convention: message to STDOUT upon request. | 
| 909 | 91 | 50 | 33 |  |  | 1128 | app_ident(\*STDOUT) if $ident || $clo->{verbose} || $help || $manual; | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 33 |  |  |  |  | 
| 910 | 91 | 50 | 33 |  |  | 633 | if ( $manual or $help ) { | 
| 911 | 0 | 0 |  |  |  | 0 | app_usage(\*STDOUT, 0) if $help; | 
| 912 | 0 | 0 |  |  |  | 0 | $pod2usage->(VERBOSE => 2) if $manual; | 
| 913 |  |  |  |  |  |  | } | 
| 914 | 91 | 50 |  |  |  | 304 | app_ident(\*STDOUT, 0) if $version; | 
| 915 | 91 | 50 |  |  |  | 327 | app_about(\*STDOUT, 0) if $about; | 
| 916 |  |  |  |  |  |  |  | 
| 917 |  |  |  |  |  |  | # If the user specified a config, it must exist. | 
| 918 |  |  |  |  |  |  | # Otherwise, set to a default. | 
| 919 | 91 |  |  |  |  | 362 | for my $config ( qw(sysconfig userconfig) ) { | 
| 920 | 182 |  |  |  |  | 568 | for ( $clo->{$config} ) { | 
| 921 | 182 | 50 |  |  |  | 505 | if ( defined($_) ) { | 
| 922 | 0 | 0 |  |  |  | 0 | die("$_: $!\n") unless -r $_; | 
| 923 | 0 |  |  |  |  | 0 | next; | 
| 924 |  |  |  |  |  |  | } | 
| 925 |  |  |  |  |  |  | # Use default. | 
| 926 | 182 | 50 |  |  |  | 627 | next if $clo->{nodefaultconfigs}; | 
| 927 | 0 | 0 |  |  |  | 0 | next unless $configs{$config}; | 
| 928 | 0 |  |  |  |  | 0 | $_ = $configs{$config}; | 
| 929 | 0 | 0 |  |  |  | 0 | undef($_) unless -r $_; | 
| 930 |  |  |  |  |  |  | } | 
| 931 |  |  |  |  |  |  | } | 
| 932 | 91 |  |  |  |  | 349 | for my $config ( qw(config) ) { | 
| 933 | 91 |  |  |  |  | 348 | for ( $clo->{$config} ) { | 
| 934 | 91 | 50 |  |  |  | 325 | if ( defined($_) ) { | 
| 935 | 0 |  |  |  |  | 0 | foreach my $c ( @$_ ) { | 
| 936 |  |  |  |  |  |  | # Check for resource names. | 
| 937 | 0 | 0 |  |  |  | 0 | if ( $c !~ m;[/.]; ) { | 
| 938 | 0 |  |  |  |  | 0 | $c = ::rsc_or_file( $c, "config" ); | 
| 939 |  |  |  |  |  |  | } | 
| 940 | 0 | 0 |  |  |  | 0 | die("$c: $!\n") unless -r $c; | 
| 941 |  |  |  |  |  |  | } | 
| 942 | 0 |  |  |  |  | 0 | next; | 
| 943 |  |  |  |  |  |  | } | 
| 944 |  |  |  |  |  |  | # Use default. | 
| 945 | 91 | 50 |  |  |  | 420 | next if $clo->{nodefaultconfigs}; | 
| 946 | 0 | 0 |  |  |  | 0 | next unless $configs{$config}; | 
| 947 | 0 |  |  |  |  | 0 | $_ = [ $configs{$config} ]; | 
| 948 | 0 | 0 |  |  |  | 0 | undef($_) unless -r -f $_->[0]; | 
| 949 |  |  |  |  |  |  | } | 
| 950 |  |  |  |  |  |  | } | 
| 951 |  |  |  |  |  |  | # If no config was specified, and no default is available, force no. | 
| 952 | 91 |  |  |  |  | 331 | for my $config ( qw(sysconfig userconfig config ) ) { | 
| 953 | 273 | 50 |  |  |  | 1062 | $clo->{"no$config"} = 1 unless $clo->{$config}; | 
| 954 |  |  |  |  |  |  | } | 
| 955 | 91 |  | 33 |  |  | 759 | $clo->{nosongconfig} ||= $clo->{nodefaultconfigs}; | 
| 956 |  |  |  |  |  |  |  | 
| 957 |  |  |  |  |  |  | # Decode command line strings. | 
| 958 |  |  |  |  |  |  | # File names are dealt with elsewhere. | 
| 959 | 91 |  |  |  |  | 305 | for ( qw(transcode) ) { | 
| 960 | 91 | 50 |  |  |  | 420 | next unless defined $clo->{$_}; | 
| 961 | 0 |  |  |  |  | 0 | $clo->{$_} = decode_utf8($clo->{$_}); | 
| 962 |  |  |  |  |  |  | } | 
| 963 |  |  |  |  |  |  | ####TODO: Should decode all, and remove filename exception. | 
| 964 | 91 |  |  |  |  | 210 | for ( keys %{ $clo->{define} } ) { | 
|  | 91 |  |  |  |  | 450 |  | 
| 965 | 10 |  |  |  |  | 264 | $clo->{define}->{$_} = decode_utf8($clo->{define}->{$_}); | 
| 966 |  |  |  |  |  |  | } | 
| 967 |  |  |  |  |  |  |  | 
| 968 |  |  |  |  |  |  | # Plug in command-line options. | 
| 969 | 91 |  |  |  |  | 848 | @{$options}{keys %$clo} = values %$clo; | 
|  | 91 |  |  |  |  | 648 |  | 
| 970 | 91 |  |  |  |  | 887 | $::options = $options; | 
| 971 |  |  |  |  |  |  | # warn(::dump($options), "\n") if $options->{debug}; | 
| 972 |  |  |  |  |  |  |  | 
| 973 | 91 | 50 | 33 |  |  | 807 | if ( $defcfg || $fincfg || $deltacfg ) { | 
|  |  |  | 33 |  |  |  |  | 
| 974 | 0 | 0 |  |  |  | 0 | print ChordPro::Config::config_default() | 
| 975 |  |  |  |  |  |  | if $defcfg; | 
| 976 | 0 | 0 | 0 |  |  | 0 | print ChordPro::Config::config_final($deltacfg) | 
| 977 |  |  |  |  |  |  | if $fincfg || $deltacfg; | 
| 978 | 0 |  |  |  |  | 0 | exit 0; | 
| 979 |  |  |  |  |  |  | } | 
| 980 |  |  |  |  |  |  |  | 
| 981 | 91 | 50 |  |  |  | 348 | if ( $dump_chords ) { | 
| 982 | 0 |  |  |  |  | 0 | $::config = ChordPro::Config::configurator($options); | 
| 983 | 0 |  |  |  |  | 0 | require ChordPro::Chords; | 
| 984 | 0 |  |  |  |  | 0 | ChordPro::Chords::dump_chords($dump_chords); | 
| 985 | 0 |  |  |  |  | 0 | exit 0; | 
| 986 |  |  |  |  |  |  | } | 
| 987 |  |  |  |  |  |  |  | 
| 988 | 91 | 50 |  |  |  | 385 | if ( $clo->{filelist} ) { | 
| 989 | 0 |  |  |  |  | 0 | my @files; | 
| 990 | 0 |  |  |  |  | 0 | foreach ( @{ $clo->{filelist} } ) { | 
|  | 0 |  |  |  |  | 0 |  | 
| 991 | 0 |  |  |  |  | 0 | my $list = loadlines( $_, $clo ); | 
| 992 | 0 |  |  |  |  | 0 | foreach ( @$list ) { | 
| 993 | 0 | 0 |  |  |  | 0 | next unless /\S/; | 
| 994 | 0 | 0 |  |  |  | 0 | next if /^#/; | 
| 995 | 0 |  |  |  |  | 0 | s/[\r\n]+$//; | 
| 996 | 0 |  |  |  |  | 0 | push( @files, encode_utf8($_) ); | 
| 997 |  |  |  |  |  |  | } | 
| 998 |  |  |  |  |  |  | } | 
| 999 | 0 | 0 |  |  |  | 0 | if ( @files ) { | 
| 1000 | 0 | 0 |  |  |  | 0 | if ( $files[0] =~ /\.pdf$/i ) { | 
| 1001 | 0 |  | 0 |  |  | 0 | $options->{'front-matter'} //= $files[0]; | 
| 1002 | 0 |  |  |  |  | 0 | shift(@files); | 
| 1003 |  |  |  |  |  |  | } | 
| 1004 | 0 | 0 |  |  |  | 0 | if ( $files[-1] =~ /\.pdf$/i ) { | 
| 1005 | 0 |  | 0 |  |  | 0 | $options->{'back-matter'} //= $files[-1]; | 
| 1006 | 0 |  |  |  |  | 0 | pop(@files); | 
| 1007 |  |  |  |  |  |  | } | 
| 1008 |  |  |  |  |  |  | } | 
| 1009 | 0 | 0 |  |  |  | 0 | unshift( @ARGV, @files ) if @files; | 
| 1010 |  |  |  |  |  |  | } | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 |  |  |  |  |  |  | # At this point, there should be filename argument(s) | 
| 1013 |  |  |  |  |  |  | # unless we're embedded or just dumping chords. | 
| 1014 |  |  |  |  |  |  | app_usage(\*STDERR, 1) | 
| 1015 | 91 | 50 | 33 |  |  | 770 | unless $::__EMBEDDED__ || $clo->{'dump-chords'} || @ARGV; | 
|  |  |  | 33 |  |  |  |  | 
| 1016 |  |  |  |  |  |  |  | 
| 1017 |  |  |  |  |  |  | # Return result. | 
| 1018 | 91 |  |  |  |  | 964 | $options; | 
| 1019 |  |  |  |  |  |  | } | 
| 1020 |  |  |  |  |  |  |  | 
| 1021 |  |  |  |  |  |  | sub app_ident { | 
| 1022 | 0 |  |  | 0 | 0 | 0 | my ($fh, $exit) = @_; | 
| 1023 | 0 |  |  |  |  | 0 | print {$fh} ("This is ", ::runtimeinfo("short"), "\n"); | 
|  | 0 |  |  |  |  | 0 |  | 
| 1024 | 0 | 0 |  |  |  | 0 | exit $exit if defined $exit; | 
| 1025 |  |  |  |  |  |  | } | 
| 1026 |  |  |  |  |  |  |  | 
| 1027 |  |  |  |  |  |  | sub app_about { | 
| 1028 | 0 |  |  | 0 | 0 | 0 | my ($fh, $exit) = @_; | 
| 1029 | 0 |  |  |  |  | 0 | print ${fh} < | 
| 1030 |  |  |  |  |  |  |  | 
| 1031 |  |  |  |  |  |  | ChordPro: A lyrics and chords formatting program. | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 |  |  |  |  |  |  | ChordPro will read a text file containing the lyrics of one or many | 
| 1034 |  |  |  |  |  |  | songs plus chord information. ChordPro will then generate a | 
| 1035 |  |  |  |  |  |  | photo-ready, professional looking, impress-your-friends sheet-music | 
| 1036 |  |  |  |  |  |  | suitable for printing on your nearest printer. | 
| 1037 |  |  |  |  |  |  |  | 
| 1038 |  |  |  |  |  |  | To learn more about ChordPro, look for the man page or do | 
| 1039 |  |  |  |  |  |  | "chordpro --help" for the list of options. | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 |  |  |  |  |  |  | For more information, see https://www.chordpro.org . | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 |  |  |  |  |  |  | Run-time information: | 
| 1044 | 0 |  |  |  |  | 0 | @{[::runtimeinfo()]} | 
| 1045 |  |  |  |  |  |  | EndOfAbout | 
| 1046 | 0 | 0 |  |  |  | 0 | exit $exit if defined $exit; | 
| 1047 |  |  |  |  |  |  | } | 
| 1048 |  |  |  |  |  |  |  | 
| 1049 | 79 |  |  | 79 |  | 822 | use Cwd qw(realpath); | 
|  | 79 |  |  |  |  | 249 |  | 
|  | 79 |  |  |  |  | 48510 |  | 
| 1050 |  |  |  |  |  |  |  | 
| 1051 |  |  |  |  |  |  | sub ::runtimeinfo { | 
| 1052 | 8 |  |  | 8 |  | 32 | my $short = shift; | 
| 1053 |  |  |  |  |  |  |  | 
| 1054 | 8 |  |  |  |  | 50 | my $fmt   = "  %-22.22s %s\n"; | 
| 1055 | 8 | 50 |  |  |  | 58 | my $fmtv  = defined($Wx::VERSION) ? "  %s version %s\n" : $fmt; | 
| 1056 | 8 | 50 |  |  |  | 39 | my $fmtvv = defined($Wx::VERSION) ? "  %s %s\n" : $fmt; | 
| 1057 |  |  |  |  |  |  |  | 
| 1058 |  |  |  |  |  |  | # Sometimes version numbers are localized... | 
| 1059 | 8 |  |  | 8 |  | 56 | my $dd = sub { my $v = $_[0]; $v =~ s/,/./g; $v }; | 
|  | 8 |  |  |  |  | 26 |  | 
|  | 8 |  |  |  |  | 30 |  | 
|  | 8 |  |  |  |  | 64 |  | 
| 1060 |  |  |  |  |  |  |  | 
| 1061 | 8 |  |  |  |  | 43 | my $msg = sprintf( $fmtv, "ChordPro core", $dd->($VERSION) ); | 
| 1062 | 8 | 50 |  |  |  | 54 | $msg =~ s/core/reference/ if $::options->{reference}; | 
| 1063 | 8 | 50 |  |  |  | 75 | if ( $VERSION =~ /_/ ) { | 
| 1064 | 8 |  |  |  |  | 56 | $msg =~ s/\n$/ (Unsupported development snapshot)\n/; | 
| 1065 |  |  |  |  |  |  | } | 
| 1066 |  |  |  |  |  |  |  | 
| 1067 | 8 | 50 |  |  |  | 44 | if ( $short ) { | 
| 1068 | 8 |  |  |  |  | 51 | $msg =~ s/^\s+//; | 
| 1069 | 8 |  |  |  |  | 102 | $msg =~ s/\s+/ /g; | 
| 1070 | 8 |  |  |  |  | 51 | $msg =~ s/\s*\n//; | 
| 1071 | 8 |  |  |  |  | 76 | return $msg; | 
| 1072 |  |  |  |  |  |  | } | 
| 1073 |  |  |  |  |  |  |  | 
| 1074 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "Perl", $^V ); | 
| 1075 | 0 |  |  |  |  | 0 | $msg =~ s/\n$/ ($^X)\n/; | 
| 1076 | 0 | 0 |  |  |  | 0 | if ( $App::Packager::PACKAGED ) { | 
| 1077 | 0 |  |  |  |  | 0 | my $p = App::Packager::Packager(); | 
| 1078 | 0 | 0 |  |  |  | 0 | $p .= " Packager" unless $p =~ /packager/i; | 
| 1079 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, $p, $dd->(App::Packager::Version()) ); | 
| 1080 |  |  |  |  |  |  | } | 
| 1081 |  |  |  |  |  |  |  | 
| 1082 |  |  |  |  |  |  | # Determine resource path. | 
| 1083 | 0 |  |  |  |  | 0 | my @p; | 
| 1084 | 0 | 0 |  |  |  | 0 | if ( $ENV{CHORDPRO_LIB} ) { | 
| 1085 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "CHORDPRO_LIB", $ENV{CHORDPRO_LIB} ); | 
| 1086 | 0 |  |  |  |  | 0 | @p = splitpath($ENV{CHORDPRO_LIB}); | 
| 1087 |  |  |  |  |  |  | } | 
| 1088 | 0 |  |  |  |  | 0 | push( @p, realpath( App::Packager::GetResourcePath() ) ); | 
| 1089 | 0 |  |  |  |  | 0 | my $tag = "Resource path"; | 
| 1090 | 0 |  |  |  |  | 0 | for ( @p ) { | 
| 1091 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtvv, $tag, $_ ); | 
| 1092 | 0 |  |  |  |  | 0 | $tag = ""; | 
| 1093 |  |  |  |  |  |  | } | 
| 1094 |  |  |  |  |  |  |  | 
| 1095 | 0 |  |  |  |  | 0 | $msg .= "\nModules and libraries:\n"; | 
| 1096 | 0 | 0 |  |  |  | 0 | if ( defined $Wx::VERSION ) { | 
| 1097 | 79 |  |  | 79 |  | 804 | no strict 'subs'; | 
|  | 79 |  |  |  |  | 300 |  | 
|  | 79 |  |  |  |  | 59880 |  | 
| 1098 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "wxPerl", $dd->($Wx::VERSION) ); | 
| 1099 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "wxWidgets", $dd->(Wx::wxVERSION) ); | 
| 1100 |  |  |  |  |  |  | } | 
| 1101 |  |  |  |  |  |  |  | 
| 1102 | 0 |  |  | 0 |  | 0 | local $SIG{__WARN__} = sub {}; | 
| 1103 | 0 |  |  | 0 |  | 0 | local $SIG{__DIE__} = sub {}; | 
| 1104 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "Storable", $dd->($Storable::VERSION) ); | 
| 1105 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "Object::Pad", $dd->($Object::Pad::VERSION) ); | 
| 1106 | 0 |  |  |  |  | 0 | eval { require Text::Layout; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1107 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "Text::Layout", $dd->($Text::Layout::VERSION) ); | 
| 1108 |  |  |  |  |  |  | }; | 
| 1109 | 0 |  |  |  |  | 0 | eval { require HarfBuzz::Shaper; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1110 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "HarfBuzz::Shaper", $dd->($HarfBuzz::Shaper::VERSION) ); | 
| 1111 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "HarfBuzz library", $dd->(HarfBuzz::Shaper::hb_version_string()) ); | 
| 1112 |  |  |  |  |  |  | }; | 
| 1113 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "File::LoadLines", $dd->($File::LoadLines::VERSION) ); | 
| 1114 | 0 |  |  |  |  | 0 | eval { require PDF::Builder; | 
| 1115 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "PDF::Builder", $dd->($PDF::Builder::VERSION) ); | 
| 1116 |  |  |  |  |  |  | } | 
| 1117 |  |  |  |  |  |  | or | 
| 1118 | 0 | 0 |  |  |  | 0 | eval { require PDF::API2; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1119 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "PDF::API2", $dd->($PDF::API2::VERSION) ); | 
| 1120 |  |  |  |  |  |  | }; | 
| 1121 | 0 |  |  |  |  | 0 | eval { require Font::TTF; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1122 | 0 |  |  |  |  | 0 | $msg .= sprintf( $fmtv, "Font::TTF", $dd->($Font::TTF::VERSION) ); | 
| 1123 |  |  |  |  |  |  | }; | 
| 1124 | 0 |  |  |  |  | 0 | eval { require Image::Magick; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1125 | 0 |  | 0 |  |  | 0 | $msg .= sprintf( $fmtv, "Image::Magick", | 
| 1126 |  |  |  |  |  |  | $dd->( $Image::Magick::VERSION || | 
| 1127 |  |  |  |  |  |  | $Image::Magick::Q16::VERSION || | 
| 1128 |  |  |  |  |  |  | $Image::Magick::Q8::VERSION || "6.x?" ) ); | 
| 1129 |  |  |  |  |  |  | }; | 
| 1130 | 0 |  |  |  |  | 0 | return $msg; | 
| 1131 |  |  |  |  |  |  | } | 
| 1132 |  |  |  |  |  |  |  | 
| 1133 |  |  |  |  |  |  | sub splitpath { | 
| 1134 | 150 |  |  | 150 | 0 | 535 | my ( $path ) = @_; | 
| 1135 | 150 | 50 |  |  |  | 630 | return () unless $path; | 
| 1136 | 150 | 50 |  |  |  | 1360 | if ( $^O =~ /Win/ ) { | 
| 1137 | 0 |  |  |  |  | 0 | return split( /;/, $path ); | 
| 1138 |  |  |  |  |  |  | } | 
| 1139 | 150 |  |  |  |  | 1199 | return split( /;/, $path ); | 
| 1140 |  |  |  |  |  |  | } | 
| 1141 |  |  |  |  |  |  |  | 
| 1142 |  |  |  |  |  |  | sub app_usage { | 
| 1143 | 0 |  |  | 0 | 0 | 0 | my ($fh, $exit) = @_; | 
| 1144 | 0 |  |  |  |  | 0 | my %cfg; | 
| 1145 | 0 |  |  |  |  | 0 | for ( qw( config userconfig sysconfig) ) { | 
| 1146 | 0 |  | 0 |  |  | 0 | $cfg{$_} = $configs{$_} || "no default"; | 
| 1147 |  |  |  |  |  |  | } | 
| 1148 | 0 |  |  |  |  | 0 | print ${fh} < | 
| 1149 |  |  |  |  |  |  | Usage: $0 [ options ] [ file ... ] | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | Options: | 
| 1152 |  |  |  |  |  |  | --a2crd                       Perform text to ChordPro conversion only | 
| 1153 |  |  |  |  |  |  | --noa2crd                     Do not auto-sense text to ChordPro conversion | 
| 1154 |  |  |  |  |  |  | --about  -A                   About ChordPro... | 
| 1155 |  |  |  |  |  |  | --back-matter=FILE            Add back matter pages from PDF document | 
| 1156 |  |  |  |  |  |  | --config=JSON  --cfg          Config definitions (multiple) | 
| 1157 |  |  |  |  |  |  | --cover=FILE                  Add cover pages from PDF document | 
| 1158 |  |  |  |  |  |  | --crd                         Input is text, not ChordPro | 
| 1159 |  |  |  |  |  |  | --csv                         (with PDF) Also generate CSV | 
| 1160 |  |  |  |  |  |  | --decapo                      Eliminate capo settings | 
| 1161 |  |  |  |  |  |  | --diagrams=WHICH		  Prints chord diagrams | 
| 1162 |  |  |  |  |  |  | --encoding=ENC                Encoding for input files (UTF-8) | 
| 1163 |  |  |  |  |  |  | --filelist=FILE               Reads song file names from FILE | 
| 1164 |  |  |  |  |  |  | --fragment -F                 Partial (incomplete) song | 
| 1165 |  |  |  |  |  |  | --front-matter=FILE           Add cover pages from PDF document | 
| 1166 |  |  |  |  |  |  | --lyrics-only  -l             Only prints lyrics | 
| 1167 |  |  |  |  |  |  | --meta KEY=VALUE              Add meta data | 
| 1168 |  |  |  |  |  |  | --output=FILE  -o             Saves the output to FILE | 
| 1169 |  |  |  |  |  |  | --[no]strict                  Strict conformance | 
| 1170 |  |  |  |  |  |  | --start-page-number=N  -p     Starting page number [1] | 
| 1171 |  |  |  |  |  |  | --toc --notoc -i              Generates/suppresses a table of contents | 
| 1172 |  |  |  |  |  |  | --transcode=SYS  -xc          Transcodes to notation system | 
| 1173 |  |  |  |  |  |  | --transpose=N  -x             Transposes by N semi-tones | 
| 1174 |  |  |  |  |  |  | --version  -V                 Prints version and exits | 
| 1175 |  |  |  |  |  |  |  | 
| 1176 |  |  |  |  |  |  | Chordii compatibility. | 
| 1177 |  |  |  |  |  |  | Options marked with * are better specified in the config file. | 
| 1178 |  |  |  |  |  |  | Options marked with - are ignored. | 
| 1179 |  |  |  |  |  |  | --chord-font=FONT  -C         *Sets chord font | 
| 1180 |  |  |  |  |  |  | --chord-grid-size=N  -s       *Sets chord diagram size [30] | 
| 1181 |  |  |  |  |  |  | --chord-grids-sorted  -S      *Prints chord diagrams ordered by key | 
| 1182 |  |  |  |  |  |  | --chord-size=N  -c            *Sets chord size [9] | 
| 1183 |  |  |  |  |  |  | --dump-chords  -D             Dumps chords definitions (PostScript) | 
| 1184 |  |  |  |  |  |  | --dump-chords-text  -d        Dumps chords definitions (Text) | 
| 1185 |  |  |  |  |  |  | --even-pages-number-left  -L  *Even pages numbers on left | 
| 1186 |  |  |  |  |  |  | --odd-pages-number-left       *Odd pages numbers on left | 
| 1187 |  |  |  |  |  |  | --no-chord-grids  -G          *Disables printing of chord diagrams | 
| 1188 |  |  |  |  |  |  | --no-easy-chord-grids  -g     Not supported | 
| 1189 |  |  |  |  |  |  | --page-number-logical  -n     -Numbers logical pages, not physical | 
| 1190 |  |  |  |  |  |  | --page-size=FMT  -P           *Specifies page size [letter, a4 (default)] | 
| 1191 |  |  |  |  |  |  | --single-space  -a            *Automatic single space lines without chords | 
| 1192 |  |  |  |  |  |  | --text-size=N  -t             *Sets text size [12] | 
| 1193 |  |  |  |  |  |  | --text-font=FONT  -T          *Sets text font | 
| 1194 |  |  |  |  |  |  | --user-chord-grids		  *Prints the user defined chords in the song | 
| 1195 |  |  |  |  |  |  | --vertical-space=N  -w        *Extra vertical space between lines | 
| 1196 |  |  |  |  |  |  | --2-up  -2                    Not supported | 
| 1197 |  |  |  |  |  |  | --4-up  -4                    Not supported | 
| 1198 |  |  |  |  |  |  |  | 
| 1199 |  |  |  |  |  |  | Configuration options: | 
| 1200 |  |  |  |  |  |  | --config=CFG        Project specific config file ($cfg{config}) | 
| 1201 |  |  |  |  |  |  | --define=XXX=YYY	Sets config item XXX to value YYY | 
| 1202 |  |  |  |  |  |  | --noconfig          Don't use a project specific config file | 
| 1203 |  |  |  |  |  |  | --nodefaultconfigs  -X  Don't use any default config files | 
| 1204 |  |  |  |  |  |  | --nosongconfig      Don't use song specific configs | 
| 1205 |  |  |  |  |  |  | --nosysconfig       Don't use a system specific config file | 
| 1206 |  |  |  |  |  |  | --nouserconfig      Don't use a user specific config file | 
| 1207 |  |  |  |  |  |  | --print-default-config   Prints the default config and exits | 
| 1208 |  |  |  |  |  |  | --print-delta-config   Prints the diffs for the resultant config and exits | 
| 1209 |  |  |  |  |  |  | --print-final-config   Prints the resultant config and exits | 
| 1210 |  |  |  |  |  |  | --reference  -R     Reference mode (no configs etc.) | 
| 1211 |  |  |  |  |  |  | --sysconfig=CFG     System specific config file ($cfg{sysconfig}) | 
| 1212 |  |  |  |  |  |  | --userconfig=CFG    User specific config file ($cfg{userconfig}) | 
| 1213 |  |  |  |  |  |  | Missing default configuration files are silently ignored. | 
| 1214 |  |  |  |  |  |  |  | 
| 1215 |  |  |  |  |  |  | Miscellaneous options: | 
| 1216 |  |  |  |  |  |  | --help  -h          This message | 
| 1217 |  |  |  |  |  |  | --help-config       Help for ChordPro configuration | 
| 1218 |  |  |  |  |  |  | --ident             Show identification | 
| 1219 |  |  |  |  |  |  | --manual            The full manual. | 
| 1220 |  |  |  |  |  |  | --verbose           Verbose information. Repeat for more. | 
| 1221 |  |  |  |  |  |  | EndOfUsage | 
| 1222 | 0 | 0 |  |  |  | 0 | exit $exit if defined $exit; | 
| 1223 |  |  |  |  |  |  | } | 
| 1224 |  |  |  |  |  |  |  | 
| 1225 |  |  |  |  |  |  | ################ Resources ################ | 
| 1226 |  |  |  |  |  |  |  | 
| 1227 | 79 |  |  | 79 |  | 777 | use Encode qw(decode decode_utf8 encode_utf8); | 
|  | 79 |  |  |  |  | 235 |  | 
|  | 79 |  |  |  |  | 33626 |  | 
| 1228 |  |  |  |  |  |  |  | 
| 1229 |  |  |  |  |  |  | sub ::rsc_or_file { | 
| 1230 | 161 |  |  | 161 |  | 700 | my ( $c, $cfg ) = @_; | 
| 1231 | 161 |  |  |  |  | 455 | my $f = $c; | 
| 1232 | 161 | 100 |  |  |  | 748 | $cfg .= "/" if $cfg; | 
| 1233 |  |  |  |  |  |  |  | 
| 1234 |  |  |  |  |  |  | # Check for resource names. | 
| 1235 | 161 | 100 |  |  |  | 944 | if ( $f !~ m;[/.]; ) { | 
| 1236 | 119 | 50 |  |  |  | 668 | if ( $c =~ /^(.+):(.*)/ ) { | 
| 1237 | 0 |  |  |  |  | 0 | $f = $cfg . lc($1) . "/" . lc($2) . ".json"; | 
| 1238 |  |  |  |  |  |  | } | 
| 1239 |  |  |  |  |  |  | else { | 
| 1240 | 119 |  |  |  |  | 623 | $f = $cfg . lc($c) . ".json"; | 
| 1241 |  |  |  |  |  |  | } | 
| 1242 |  |  |  |  |  |  | } | 
| 1243 | 161 | 100 |  |  |  | 1012 | if ( $ENV{CHORDPRO_LIB} ) { | 
| 1244 | 150 |  |  |  |  | 862 | my @libs = splitpath($ENV{CHORDPRO_LIB}); | 
| 1245 | 150 |  |  |  |  | 598 | foreach my $lib ( @libs ) { | 
| 1246 | 150 |  |  |  |  | 921 | $lib = expand_tilde($lib); | 
| 1247 | 150 | 50 |  |  |  | 826 | warn("RSC1: $lib/$f\n") if $options->{debug}; | 
| 1248 | 150 | 50 |  |  |  | 4554 | return $lib . "/" . $f if -r $lib . "/" . $f; | 
| 1249 |  |  |  |  |  |  | } | 
| 1250 |  |  |  |  |  |  | } | 
| 1251 |  |  |  |  |  |  |  | 
| 1252 | 161 | 50 |  |  |  | 862 | warn("RSC3: $f\n") if $options->{debug}; | 
| 1253 | 161 |  |  |  |  | 1319 | my $t = getresource($f); | 
| 1254 | 161 | 50 |  |  |  | 36936 | return defined($t) ? $t : $c; | 
| 1255 |  |  |  |  |  |  | } | 
| 1256 |  |  |  |  |  |  |  | 
| 1257 | 79 |  |  | 79 |  | 39445 | use lib ( grep { defined } getresource("CPAN") ); | 
|  | 79 |  |  |  |  | 56908 |  | 
|  | 79 |  |  |  |  | 971 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 1258 |  |  |  |  |  |  |  | 
| 1259 |  |  |  |  |  |  | =head1 FONTS | 
| 1260 |  |  |  |  |  |  |  | 
| 1261 |  |  |  |  |  |  | There are two ways to specify fonts: with a font filename, and a | 
| 1262 |  |  |  |  |  |  | built-in font name. | 
| 1263 |  |  |  |  |  |  |  | 
| 1264 |  |  |  |  |  |  | A font filename must be either and absolute filename, or a relative | 
| 1265 |  |  |  |  |  |  | filename which is interpreted relative to the I, which | 
| 1266 |  |  |  |  |  |  | consists of configuration setting C, the C resource | 
| 1267 |  |  |  |  |  |  | dir, and the contents of environment variable C. In any case, | 
| 1268 |  |  |  |  |  |  | the filename should point to a valid TrueType (C<.ttf>) or OpenType | 
| 1269 |  |  |  |  |  |  | (C<.otf>) font. | 
| 1270 |  |  |  |  |  |  |  | 
| 1271 |  |  |  |  |  |  | If it is not a filename, it must be the name one of the built-in fonts. | 
| 1272 |  |  |  |  |  |  |  | 
| 1273 |  |  |  |  |  |  | Built-in 'Adobe Core Fonts': | 
| 1274 |  |  |  |  |  |  |  | 
| 1275 |  |  |  |  |  |  | Courier                             Symbol | 
| 1276 |  |  |  |  |  |  | Courier-Bold                        Times-Bold | 
| 1277 |  |  |  |  |  |  | Courier-BoldOblique                 Times-BoldItalic | 
| 1278 |  |  |  |  |  |  | Courier-Oblique                     Times-Italic | 
| 1279 |  |  |  |  |  |  | Helvetica                           Times-Roman | 
| 1280 |  |  |  |  |  |  | Helvetica-Bold                      ZapfDingbats | 
| 1281 |  |  |  |  |  |  | Helvetica-BoldOblique | 
| 1282 |  |  |  |  |  |  | Helvetica-Oblique | 
| 1283 |  |  |  |  |  |  |  | 
| 1284 |  |  |  |  |  |  | Built-in 'Windows Fonts': | 
| 1285 |  |  |  |  |  |  |  | 
| 1286 |  |  |  |  |  |  | Georgia                             Webdings | 
| 1287 |  |  |  |  |  |  | Georgia,Bold                        Wingdings | 
| 1288 |  |  |  |  |  |  | Georgia,BoldItalic | 
| 1289 |  |  |  |  |  |  | Georgia,Italic | 
| 1290 |  |  |  |  |  |  | Verdana | 
| 1291 |  |  |  |  |  |  | Verdana,Bold | 
| 1292 |  |  |  |  |  |  | Verdana,BoldItalic | 
| 1293 |  |  |  |  |  |  | Verdana,Italic | 
| 1294 |  |  |  |  |  |  |  | 
| 1295 |  |  |  |  |  |  | =head1 MOTIVATION | 
| 1296 |  |  |  |  |  |  |  | 
| 1297 |  |  |  |  |  |  | Why a rewrite of Chordii? | 
| 1298 |  |  |  |  |  |  |  | 
| 1299 |  |  |  |  |  |  | Chordii is the de facto reference implementation of the ChordPro file | 
| 1300 |  |  |  |  |  |  | format standard. It implements ChordPro version 4. | 
| 1301 |  |  |  |  |  |  |  | 
| 1302 |  |  |  |  |  |  | ChordPro version 5 adds a number of new features, and this was pushing | 
| 1303 |  |  |  |  |  |  | the limits of the very old program. Unicode support would have been | 
| 1304 |  |  |  |  |  |  | very hard to add, and the whole program centered around PostScript | 
| 1305 |  |  |  |  |  |  | generation, while nowadays PDF would be a much better alternative. | 
| 1306 |  |  |  |  |  |  |  | 
| 1307 |  |  |  |  |  |  | So I decided to create a new reference implementation from the ground | 
| 1308 |  |  |  |  |  |  | up. I chose a programming language that is flexible and very good at | 
| 1309 |  |  |  |  |  |  | handling Unicode data. And that is fun to program in. | 
| 1310 |  |  |  |  |  |  |  | 
| 1311 |  |  |  |  |  |  | =head1 CURRENT STATUS | 
| 1312 |  |  |  |  |  |  |  | 
| 1313 |  |  |  |  |  |  | This program implements ChordPro version 5. It | 
| 1314 |  |  |  |  |  |  | supports most of the features of Chordii, and a lot more: | 
| 1315 |  |  |  |  |  |  |  | 
| 1316 |  |  |  |  |  |  | * Native PDF generation | 
| 1317 |  |  |  |  |  |  |  | 
| 1318 |  |  |  |  |  |  | * Unicode support (all input is UTF8) | 
| 1319 |  |  |  |  |  |  |  | 
| 1320 |  |  |  |  |  |  | * User defined chords and tuning, not limited to 6 strings. | 
| 1321 |  |  |  |  |  |  |  | 
| 1322 |  |  |  |  |  |  | * Support for Nashville Numbering and Roman Numbering. | 
| 1323 |  |  |  |  |  |  |  | 
| 1324 |  |  |  |  |  |  | * Support for external TrueType and OpenType fonts | 
| 1325 |  |  |  |  |  |  |  | 
| 1326 |  |  |  |  |  |  | * Font kerning (with external TrueType fonts) | 
| 1327 |  |  |  |  |  |  |  | 
| 1328 |  |  |  |  |  |  | * Fully customizable layout, fonts and sizes | 
| 1329 |  |  |  |  |  |  |  | 
| 1330 |  |  |  |  |  |  | * Customizable backends for PDF, ChordPro, LilyPond*, LaTeX* and HTML*. | 
| 1331 |  |  |  |  |  |  |  | 
| 1332 |  |  |  |  |  |  | (* = under development) | 
| 1333 |  |  |  |  |  |  |  | 
| 1334 |  |  |  |  |  |  | =head1 AUTHOR | 
| 1335 |  |  |  |  |  |  |  | 
| 1336 |  |  |  |  |  |  | Johan Vromans C<<  >> | 
| 1337 |  |  |  |  |  |  |  | 
| 1338 |  |  |  |  |  |  | =head1 SUPPORT | 
| 1339 |  |  |  |  |  |  |  | 
| 1340 |  |  |  |  |  |  | ChordPro (the program) development is hosted on GitHub, repository | 
| 1341 |  |  |  |  |  |  | L. | 
| 1342 |  |  |  |  |  |  |  | 
| 1343 |  |  |  |  |  |  | Please report any bugs or feature requests to the GitHub issue tracker, | 
| 1344 |  |  |  |  |  |  | L. | 
| 1345 |  |  |  |  |  |  |  | 
| 1346 |  |  |  |  |  |  | A user community discussing ChordPro can be found at | 
| 1347 |  |  |  |  |  |  | L. | 
| 1348 |  |  |  |  |  |  |  | 
| 1349 |  |  |  |  |  |  | =head1 LICENSE | 
| 1350 |  |  |  |  |  |  |  | 
| 1351 |  |  |  |  |  |  | Copyright (C) 2010,2018 Johan Vromans, | 
| 1352 |  |  |  |  |  |  |  | 
| 1353 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it | 
| 1354 |  |  |  |  |  |  | under the same terms as Perl itself. | 
| 1355 |  |  |  |  |  |  |  | 
| 1356 |  |  |  |  |  |  | =cut | 
| 1357 |  |  |  |  |  |  |  | 
| 1358 |  |  |  |  |  |  | 1; |