File Coverage

lib/ChordPro.pm
Criterion Covered Total %
statement 210 413 50.8
branch 76 214 35.5
condition 26 110 23.6
subroutine 29 42 69.0
pod 0 7 0.0
total 341 786 43.3


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