File Coverage

blib/lib/ChordPro.pm
Criterion Covered Total %
statement 206 397 51.8
branch 76 210 36.1
condition 25 110 22.7
subroutine 28 40 70.0
pod 0 7 0.0
total 335 764 43.8


line stmt bran cond sub pod time code
1             #! perl
2              
3 79     79   6267 use v5.26;
  79         315  
4              
5             package ChordPro;
6              
7 79     79   1014 use App::Packager;
  79         2735  
  79         476  
8              
9 79     79   40247 use ChordPro::Utils;
  79         208  
  79         7800  
10 79     79   38489 use ChordPro::Chords;
  79         320  
  79         3549  
11 79     79   41819 use ChordPro::Output::Common;
  79         238  
  79         5085  
12              
13             # Single line for stupid tools.
14 79     79   33527 use ChordPro::Version; our $VERSION = $ChordPro::Version::VERSION;
  79         359  
  79         4352  
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   506 use strict;
  79         173  
  79         1876  
65 79     79   395 use warnings;
  79         156  
  79         1903  
66 79     79   429 use Carp;
  79         160  
  79         3970  
67 79     79   488 use Text::ParseWords ();
  79         187  
  79         63249  
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   342278 binmode(STDERR, ':utf8');
80 91         338 binmode(STDOUT, ':utf8');
81 91         499 $options = app_setup( "ChordPro", $VERSION );
82 91 50       424 $options->{trace} = 1 if $options->{debug};
83 91 50       349 $options->{verbose} = 1 if $options->{trace};
84 91 50       338 $options->{verbose} = 9 if $options->{debug};
85 91         329 main();
86             }
87              
88             sub main {
89 91     91 0 282 my ($opts) = @_;
90 91 50       278 $options = { %$options, %$opts } if $opts;
91 91 50       393 warn("ChordPro invoked: @{$options->{_argv}}\n") if $options->{debug};
  0         0  
92 91         354 chordpro();
93              
94             }
95              
96             sub chordpro {
97              
98             # Establish backend.
99 91     91 0 295 my $of = $options->{output};
100              
101 91 50 33     614 if ( defined($of) && $of ne "" ) {
    0          
102 91 100       2059 if ( $of =~ /\.pdf$/i ) {
    50          
    50          
    100          
    50          
    100          
    100          
    50          
    50          
    50          
103 8   50     73 $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     38 $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     67 $options->{generate} ||= "Text";
120             }
121             elsif ( $of =~ /\.html?$/i ) {
122 3   50     22 $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     517 $options->{generate} ||= "PDF";
153 91         372 my $pkg = "ChordPro::Output::".$options->{generate};
154 91         10643 eval "require $pkg;";
155 91 50       609 die("No backend for ", $options->{generate}, "\n$@") if $@;
156 91         379 $options->{backend} = $pkg;
157 91 50 33     622 $pkg->version if $options->{verbose} && $pkg->can("version");
158              
159             # One configurator to bind them all.
160 79     79   1763 use ChordPro::Config;
  79         193  
  79         4503  
161 91         579 $config = ChordPro::Config::configurator({});
162              
163             # Parse the input(s).
164 79     79   34990 use ChordPro::Songbook;
  79         299  
  79         82409  
165 91         1328 my $s = ChordPro::Songbook->new;
166 91         228 my $res;
167              
168             # Shortcut a2crd conversion.
169 91 100       495 if ( $options->{a2crd} ) {
170 19         250 require ChordPro::A2Crd;
171 19         129 $res = ChordPro::A2Crd::a2crd();
172 19         92 push( @$res, '' );
173 19         211 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         322 foreach my $file ( @ARGV ) {
179 72         140 my $opts;
180 72 50       423 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         492 $s->parse_file( $file, $opts );
200             }
201              
202 72 50       387 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       283 if ( $of ) {
243 72         345 my $f = fmt_subst( $s->{songs}->[0], $of );
244 72 50       6701 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         920 $res = $pkg->generate_songbook($s);
254 72 100       3500 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     693 if ( $res && @$res > 0 ) {
260 71 50 33     430 if ( $of && $of ne "-" ) {
261 71         10684 open( my $fd, '>', $of );
262 71         1038 binmode( $fd, ":utf8" );
263 71 100       447 push( @$res, '' ) unless $res->[-1] eq '';
264 71         167 print { $fd } ( join( "\n", @$res ) );
  71         2800  
265 71         22003 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   55426 use Data::Dumper qw();
  79         541972  
  79         16215  
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   63818 use Getopt::Long 2.13 qw( :config no_ignorecase );
  79         1097680  
  79         2317  
669 79     79   16582 use File::Spec;
  79         240  
  79         2468  
670 79     79   489 use File::LoadLines;
  79         199  
  79         155700  
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 400 my ($appname, $appversion, %args) = @_;
680 91         248 my $help = 0; # handled locally
681 91         209 my $manual = 0; # handled locally
682 91         208 my $ident = 0; # handled locally
683 91         192 my $about = 0; # handled locally
684 91         181 my $version = 0; # handled locally
685 91         185 my $defcfg = 0; # handled locally
686 91         186 my $fincfg = 0; # handled locally
687 91         190 my $deltacfg = 0; # handled locally
688 91         201 my $dump_chords = 0; # handled locally
689              
690             # Package name.
691 91         312 $my_package = $args{package};
692             # Program name and version.
693 91 50       357 if ( defined $appname ) {
694 91         331 ($my_name, $my_version) = ($appname, $appversion);
695             }
696             else {
697 0         0 ($my_name, $my_version) = qw( MyProg 0.01 );
698             }
699              
700 91         305 my $app_lc = lc($my_name);
701 91 50       432 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       1925 if ( -d "/etc" ) { # some *ux
708             $configs{sysconfig} =
709 91         2426 File::Spec->catfile( "/", "etc", "$app_lc.json" );
710             }
711              
712 91 50 33     2408 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         1252 my $dir = File::Spec->catfile( $ENV{HOME}, ".config" );
719 91 50       1151 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         1148 $dir = File::Spec->catfile( $ENV{HOME}, ".$app_lc" );
726             $configs{userconfig} =
727 91         967 File::Spec->catfile( $dir, "$app_lc.json" );
728 91   66     767 $ENV{CHORDPRO_LIB} ||= $dir;
729             }
730             }
731              
732 91 50       1202 if ( -s ".$app_lc.json" ) {
733 0         0 $configs{config} = ".$app_lc.json";
734             }
735             else {
736 91         553 $configs{config} = "$app_lc.json";
737             }
738              
739 91         1644 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         292 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         234 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         2448 '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       436153 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     819 $clo->{trace} ||= $clo->{debug};
892 91   33     589 $clo->{verbose} ||= $clo->{trace};
893              
894 91 50       324 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         648 };
907              
908             # GNU convention: message to STDOUT upon request.
909 91 50 33     1148 app_ident(\*STDOUT) if $ident || $clo->{verbose} || $help || $manual;
      33        
      33        
910 91 50 33     573 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       336 app_ident(\*STDOUT, 0) if $version;
915 91 50       321 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         360 for my $config ( qw(sysconfig userconfig) ) {
920 182         543 for ( $clo->{$config} ) {
921 182 50       526 if ( defined($_) ) {
922 0 0       0 die("$_: $!\n") unless -r $_;
923 0         0 next;
924             }
925             # Use default.
926 182 50       608 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         362 for my $config ( qw(config) ) {
933 91         349 for ( $clo->{$config} ) {
934 91 50       352 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       445 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         300 for my $config ( qw(sysconfig userconfig config ) ) {
953 273 50       1106 $clo->{"no$config"} = 1 unless $clo->{$config};
954             }
955 91   33     708 $clo->{nosongconfig} ||= $clo->{nodefaultconfigs};
956              
957             # Decode command line strings.
958             # File names are dealt with elsewhere.
959 91         284 for ( qw(transcode) ) {
960 91 50       396 next unless defined $clo->{$_};
961 0         0 $clo->{$_} = decode_utf8($clo->{$_});
962             }
963             ####TODO: Should decode all, and remove filename exception.
964 91         231 for ( keys %{ $clo->{define} } ) {
  91         505  
965 10         246 $clo->{define}->{$_} = decode_utf8($clo->{define}->{$_});
966             }
967              
968             # Plug in command-line options.
969 91         847 @{$options}{keys %$clo} = values %$clo;
  91         650  
970 91         1292 $::options = $options;
971             # warn(::dump($options), "\n") if $options->{debug};
972              
973 91 50 33     913 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       383 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       391 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     746 unless $::__EMBEDDED__ || $clo->{'dump-chords'} || @ARGV;
      33        
1016              
1017             # Return result.
1018 91         924 $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   859 use Cwd qw(realpath);
  79         244  
  79         47211  
1050              
1051             sub ::runtimeinfo {
1052 8     8   33 my $short = shift;
1053              
1054 8         26 my $fmt = " %-22.22s %s\n";
1055 8 50       48 my $fmtv = defined($Wx::VERSION) ? " %s version %s\n" : $fmt;
1056 8 50       40 my $fmtvv = defined($Wx::VERSION) ? " %s %s\n" : $fmt;
1057              
1058             # Sometimes version numbers are localized...
1059 8     8   81 my $dd = sub { my $v = $_[0]; $v =~ s/,/./g; $v };
  8         38  
  8         32  
  8         65  
1060              
1061 8         43 my $msg = sprintf( $fmtv, "ChordPro core", $dd->($VERSION) );
1062 8 50       45 $msg =~ s/core/reference/ if $::options->{reference};
1063 8 50       44 if ( $VERSION =~ /_/ ) {
1064 0         0 $msg =~ s/\n$/ (Unsupported development snapshot)\n/;
1065             }
1066              
1067 8 50       32 if ( $short ) {
1068 8         56 $msg =~ s/^\s+//;
1069 8         63 $msg =~ s/\s+/ /g;
1070 8         34 $msg =~ s/\s*\n//;
1071 8         59 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( $fmtvv, "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   717 no strict 'subs';
  79         234  
  79         60787  
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 544 my ( $path ) = @_;
1135 150 50       562 return () unless $path;
1136 150 50       1154 if ( $^O =~ /Win/ ) {
1137 0         0 return split( /;/, $path );
1138             }
1139 150         1085 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   764 use Encode qw(decode decode_utf8 encode_utf8);
  79         232  
  79         33342  
1228              
1229             sub ::rsc_or_file {
1230 161     161   691 my ( $c, $cfg ) = @_;
1231 161         428 my $f = $c;
1232 161 100       745 $cfg .= "/" if $cfg;
1233              
1234             # Check for resource names.
1235 161 100       933 if ( $f !~ m;[/.]; ) {
1236 119 50       769 if ( $c =~ /^(.+):(.*)/ ) {
1237 0         0 $f = $cfg . lc($1) . "/" . lc($2) . ".json";
1238             }
1239             else {
1240 119         650 $f = $cfg . lc($c) . ".json";
1241             }
1242             }
1243 161 100       1005 if ( $ENV{CHORDPRO_LIB} ) {
1244 150         879 my @libs = splitpath($ENV{CHORDPRO_LIB});
1245 150         559 foreach my $lib ( @libs ) {
1246 150         929 $lib = expand_tilde($lib);
1247 150 50       792 warn("RSC1: $lib/$f\n") if $options->{debug};
1248 150 50       4311 return $lib . "/" . $f if -r $lib . "/" . $f;
1249             }
1250             }
1251              
1252 161 50       955 warn("RSC3: $f\n") if $options->{debug};
1253 161         1251 my $t = getresource($f);
1254 161 50       39057 return defined($t) ? $t : $c;
1255             }
1256              
1257 79     79   39003 use lib ( grep { defined } getresource("CPAN") );
  79         57131  
  79         868  
  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;