line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Amuse::Compile; |
2
|
|
|
|
|
|
|
|
3
|
57
|
|
|
57
|
|
2167051
|
use strict; |
|
57
|
|
|
|
|
446
|
|
|
57
|
|
|
|
|
1658
|
|
4
|
57
|
|
|
57
|
|
266
|
use warnings FATAL => 'all'; |
|
57
|
|
|
|
|
126
|
|
|
57
|
|
|
|
|
2883
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use constant { |
7
|
|
|
|
|
|
|
DEBUG => $ENV{AMW_DEBUG}, |
8
|
57
|
|
|
57
|
|
322
|
}; |
|
57
|
|
|
|
|
90
|
|
|
57
|
|
|
|
|
4881
|
|
9
|
|
|
|
|
|
|
|
10
|
57
|
|
|
57
|
|
357
|
use File::Basename; |
|
57
|
|
|
|
|
100
|
|
|
57
|
|
|
|
|
5795
|
|
11
|
57
|
|
|
57
|
|
30089
|
use File::Temp; |
|
57
|
|
|
|
|
862089
|
|
|
57
|
|
|
|
|
3486
|
|
12
|
57
|
|
|
57
|
|
385
|
use File::Find; |
|
57
|
|
|
|
|
99
|
|
|
57
|
|
|
|
|
2603
|
|
13
|
57
|
|
|
57
|
|
302
|
use File::Spec; |
|
57
|
|
|
|
|
111
|
|
|
57
|
|
|
|
|
1306
|
|
14
|
|
|
|
|
|
|
|
15
|
57
|
|
|
57
|
|
20969
|
use Text::Amuse::Functions qw/muse_fast_scan_header/; |
|
57
|
|
|
|
|
2019230
|
|
|
57
|
|
|
|
|
3744
|
|
16
|
57
|
|
|
57
|
|
30912
|
use Text::Amuse::Compile::File; |
|
57
|
|
|
|
|
194
|
|
|
57
|
|
|
|
|
2111
|
|
17
|
57
|
|
|
57
|
|
26390
|
use Text::Amuse::Compile::Merged; |
|
57
|
|
|
|
|
203
|
|
|
57
|
|
|
|
|
1820
|
|
18
|
57
|
|
|
57
|
|
409
|
use Text::Amuse::Compile::MuseHeader; |
|
57
|
|
|
|
|
133
|
|
|
57
|
|
|
|
|
1284
|
|
19
|
57
|
|
|
57
|
|
22397
|
use Text::Amuse::Compile::FileName; |
|
57
|
|
|
|
|
160
|
|
|
57
|
|
|
|
|
1780
|
|
20
|
57
|
|
|
57
|
|
399
|
use Text::Amuse::Compile::Fonts; |
|
57
|
|
|
|
|
122
|
|
|
57
|
|
|
|
|
1083
|
|
21
|
57
|
|
|
57
|
|
21939
|
use Text::Amuse::Compile::Fonts::Selected; |
|
57
|
|
|
|
|
200
|
|
|
57
|
|
|
|
|
4920
|
|
22
|
|
|
|
|
|
|
|
23
|
57
|
|
|
57
|
|
436
|
use Cwd; |
|
57
|
|
|
|
|
126
|
|
|
57
|
|
|
|
|
5732
|
|
24
|
57
|
|
|
57
|
|
468
|
use Fcntl qw/:flock/; |
|
57
|
|
|
|
|
105
|
|
|
57
|
|
|
|
|
7429
|
|
25
|
57
|
|
|
57
|
|
359
|
use Moo; |
|
57
|
|
|
|
|
108
|
|
|
57
|
|
|
|
|
290
|
|
26
|
57
|
|
|
57
|
|
18951
|
use Types::Standard qw/Int Maybe Bool Str HashRef CodeRef Object ArrayRef InstanceOf/; |
|
57
|
|
|
|
|
121
|
|
|
57
|
|
|
|
|
427
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 NAME |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
Text::Amuse::Compile - Compiler for Text::Amuse |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 VERSION |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Version 1.87 |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=cut |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
our $VERSION = '1.87'; |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 SYNOPSIS |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
use Text::Amuse::Compile; |
43
|
|
|
|
|
|
|
my $compiler = Text::Amuse::Compile->new; |
44
|
|
|
|
|
|
|
$compiler->compile($file1, $file2, $file3) |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 METHODS/ACCESSORS |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head2 CONSTRUCTOR |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head3 new(ttdir => '.', pdf => 1, ...); |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
Constructor. It will accept the following options |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Format options (by default all of them are activated); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=over 4 |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item cleanup |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
Remove auxiliary files after compilation (.status) |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item fontspec |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Argument for L constructor. Passing these |
65
|
|
|
|
|
|
|
triggers a new way to select fonts. The validation happens against a |
66
|
|
|
|
|
|
|
list of font you can provide. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=item epub_embed_fonts |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Boolean (default to true) which triggers the epub font embedding. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=item luatex |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Use lualatex instead of xelatex. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=item tex |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
LaTeX output. Compatible with C and C (see below |
79
|
|
|
|
|
|
|
for the packages needed). |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=item pdf |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Plain PDF without any imposition. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=item a4_pdf |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
PDF imposed on A4 paper |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=item lt_pdf |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
PDF imposed on Letter paper |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item html |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Full HTML output |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item epub |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
The EPUB |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=item bare_html |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
The bare HTML, non |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=item zip |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
The zipped sources |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=item sl_tex |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
The Beamer LaTeX output, if the muse headers say so. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=item sl_pdf |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
The Beamer PDF output, if the muse headers say so. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
If the header has a C<#slides> header with some value (e.g., 1, yes, |
118
|
|
|
|
|
|
|
ok, whatever) and if there some sectioning, create a pdf presentation |
119
|
|
|
|
|
|
|
out of it. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
E.g., the following will not produce slides: |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
#title Foo |
124
|
|
|
|
|
|
|
#slides |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
But this would |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
#title Foo |
129
|
|
|
|
|
|
|
#slides 1 |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
The value of the header is totally insignificant, as long is not |
132
|
|
|
|
|
|
|
C or C or C<0> or empty, which disable them. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Sections which contain the comment C<; noslide> are ignored. LaTeX |
135
|
|
|
|
|
|
|
source is left in the tree with C<.sl.tex> extension, and the output |
136
|
|
|
|
|
|
|
will have C<.sl.pdf> extension. |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=item slides |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Alias for sl_pdf. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=item selected_font_main |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
The selected main font (from the C hashref) |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=item selected_font_sans |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
The selected sans font (from the C hashref) |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=item selected_font_mono |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
The selected mono font (from the C hashref) |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item selected_font_size |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
The selected font size (from the C hashref) |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item extra_opts |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
An hashref of key/value pairs to pass to each template in the |
161
|
|
|
|
|
|
|
C namespace. This is internal |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=item coverpage_only_if_toc |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
Generate a cover page only if there is a ToC in the document. |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
When compiling a virtual file (a collection) the option is ignored, |
168
|
|
|
|
|
|
|
because L C always returns |
169
|
|
|
|
|
|
|
true. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item include_paths |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
Arrayref of absolute paths to look into for included files. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
=item extra |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
In the constructor arguments, a shallow copy will be stored in |
178
|
|
|
|
|
|
|
C. Using it as an accessor will return an hash with the |
179
|
|
|
|
|
|
|
copy of C |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=item standalone |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Do not force bcor=0 and oneside for plain tex and pdf |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=back |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
Template directory: |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=over 4 |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=item ttdir |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
The directory where to look for templates, named as format.tt |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=back |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
You can retrieve the value by calling them on the object. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head3 available_methods |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
Return a list of all the available compilation methods |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=head3 compile_methods |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
Return the list of the methods which are going to be used. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=cut |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
has sl_tex => (is => 'ro', isa => Bool, default => sub { 0 }); |
210
|
|
|
|
|
|
|
has sl_pdf => (is => 'ro', isa => Bool, default => sub { 0 }); |
211
|
|
|
|
|
|
|
has luatex => (is => 'ro', isa => Bool, default => sub { 0 }); |
212
|
|
|
|
|
|
|
has zip => (is => 'ro', isa => Bool, default => sub { 0 }); |
213
|
|
|
|
|
|
|
has tex => (is => 'ro', isa => Bool, default => sub { 0 }); |
214
|
|
|
|
|
|
|
has pdf => (is => 'ro', isa => Bool, default => sub { 0 }); |
215
|
|
|
|
|
|
|
has a4_pdf => (is => 'ro', isa => Bool, default => sub { 0 }); |
216
|
|
|
|
|
|
|
has lt_pdf => (is => 'ro', isa => Bool, default => sub { 0 }); |
217
|
|
|
|
|
|
|
has epub => (is => 'ro', isa => Bool, default => sub { 0 }); |
218
|
|
|
|
|
|
|
has html => (is => 'ro', isa => Bool, default => sub { 0 }); |
219
|
|
|
|
|
|
|
has bare_html => (is => 'ro', isa => Bool, default => sub { 0 }); |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
has cleanup => (is => 'ro', isa => Bool, default => sub { 0 }); |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
has ttdir => (is => 'ro', isa => Maybe[Str]); |
224
|
|
|
|
|
|
|
has templates => (is => 'lazy', isa => Object); |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
has fontspec => (is => 'ro'); |
227
|
|
|
|
|
|
|
has fonts => (is => 'lazy', isa => InstanceOf['Text::Amuse::Compile::Fonts::Selected']); |
228
|
|
|
|
|
|
|
has epub_embed_fonts => (is => 'ro', isa => Bool, default => sub { 1 }); |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
has include_paths => (is => 'ro', |
231
|
|
|
|
|
|
|
default => sub { return [] }, |
232
|
|
|
|
|
|
|
isa => sub { |
233
|
|
|
|
|
|
|
die "include_paths must be an arrayref" unless ref($_[0]) eq 'ARRAY'; |
234
|
|
|
|
|
|
|
foreach my $path (@{$_[0]}) { |
235
|
|
|
|
|
|
|
die "include_paths must be defined" unless defined $path; |
236
|
|
|
|
|
|
|
die "include_paths $path is empty" unless length($path); |
237
|
|
|
|
|
|
|
die "include_paths $path must be absolute" unless File::Spec->file_name_is_absolute($path); |
238
|
|
|
|
|
|
|
die "include_paths $path must exist" unless -d $path; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
}); |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub _build_fonts { |
243
|
224
|
|
|
224
|
|
12821
|
my $self = shift; |
244
|
224
|
|
|
|
|
807
|
my $specs = $self->fontspec; |
245
|
224
|
|
|
|
|
4334
|
my $fonts = Text::Amuse::Compile::Fonts->new($specs); |
246
|
222
|
|
100
|
|
|
34075
|
my %args = ( |
247
|
|
|
|
|
|
|
size => $self->selected_font_size || 10, |
248
|
|
|
|
|
|
|
all_fonts => $fonts, |
249
|
|
|
|
|
|
|
); |
250
|
222
|
|
|
|
|
1445
|
my @all_fonts = $fonts->all_fonts; |
251
|
222
|
|
|
|
|
844
|
foreach my $type (qw/sans mono serif/) { |
252
|
664
|
|
|
|
|
1694
|
my $method = $type . '_fonts'; |
253
|
664
|
|
|
|
|
3761
|
my @all = $fonts->$method; |
254
|
664
|
100
|
|
|
|
2077
|
die "Missing $type font in the specification" unless @all; |
255
|
663
|
100
|
|
|
|
1971
|
my $store = $type eq 'serif' ? 'main' : $type; |
256
|
663
|
|
|
|
|
1373
|
my $smethod = "selected_font_${store}"; |
257
|
663
|
100
|
|
|
|
3087
|
if (my $selected = $self->$smethod) { |
258
|
44
|
|
|
|
|
99
|
my ($got) = grep { $_->name eq $selected } @all_fonts; |
|
1149
|
|
|
|
|
1830
|
|
259
|
44
|
|
|
|
|
148
|
$args{$store} = $got; |
260
|
|
|
|
|
|
|
} |
261
|
663
|
100
|
|
|
|
1638
|
unless ($args{$store}) { |
262
|
621
|
|
|
|
|
12855
|
$self->logger->("$store font not found, using the default\n"); |
263
|
621
|
|
|
|
|
7105
|
$args{$store} = $all[0]; # if everything fails |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
} |
266
|
221
|
|
|
|
|
6569
|
return Text::Amuse::Compile::Fonts::Selected->new(%args); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
has selected_font_main => (is => 'ro', isa => Maybe[Str]); |
270
|
|
|
|
|
|
|
has selected_font_sans => (is => 'ro', isa => Maybe[Str]); |
271
|
|
|
|
|
|
|
has selected_font_mono => (is => 'ro', isa => Maybe[Str]); |
272
|
|
|
|
|
|
|
has selected_font_size => (is => 'ro', isa => Maybe[Int]); |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
has standalone => (is => 'lazy', isa => Bool); |
275
|
|
|
|
|
|
|
has extra_opts => (is => 'ro', isa => HashRef, default => sub { +{} }); |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub slides { |
278
|
0
|
|
|
0
|
1
|
0
|
return shift->sl_pdf; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
has coverpage_only_if_toc => (is => 'ro', isa => Bool, default => sub { 0 }); |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub BUILDARGS { |
284
|
245
|
|
|
245
|
1
|
1750997
|
my ($class, %params) = @_; |
285
|
245
|
100
|
|
|
|
770
|
$params{extra_opts} = { %{ delete $params{extra} || {} } }; |
|
245
|
|
|
|
|
2142
|
|
286
|
245
|
|
|
|
|
785
|
my $all = 1; |
287
|
245
|
100
|
|
|
|
1137
|
if (exists $params{slides}) { |
288
|
15
|
|
|
|
|
36
|
my $slides = delete $params{slides}; |
289
|
15
|
|
100
|
|
|
60
|
$params{sl_pdf} ||= $slides; |
290
|
|
|
|
|
|
|
} |
291
|
245
|
|
|
|
|
1198
|
foreach my $format ($class->available_methods) { |
292
|
1249
|
100
|
|
|
|
2552
|
if (exists $params{$format}) { |
293
|
235
|
|
|
|
|
602
|
$all = 0; |
294
|
235
|
|
|
|
|
660
|
last; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
} |
297
|
245
|
100
|
|
|
|
1030
|
if ($all) { |
298
|
10
|
|
|
|
|
23
|
foreach my $format ($class->available_methods) { |
299
|
100
|
|
|
|
|
151
|
$params{$format} = 1; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
} |
302
|
245
|
|
|
|
|
767
|
foreach my $dir (qw/ttdir/) { |
303
|
245
|
50
|
66
|
|
|
1511
|
if (exists $params{$dir} and defined $params{$dir} and -d $params{$dir}) { |
|
|
|
66
|
|
|
|
|
304
|
1
|
|
|
|
|
22
|
my $abs = File::Spec->rel2abs($params{$dir}); |
305
|
1
|
|
|
|
|
4
|
$params{$dir} = $abs; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
} |
308
|
|
|
|
|
|
|
# take out the fonts from the extra, for backcomp. |
309
|
245
|
|
|
|
|
796
|
foreach my $type (qw/main sans mono/) { |
310
|
735
|
|
|
|
|
2562
|
$params{"selected_font_$type"} = delete $params{extra_opts}{"${type}font"}; |
311
|
|
|
|
|
|
|
} |
312
|
245
|
|
|
|
|
857
|
$params{selected_font_size} = delete $params{extra_opts}{fontsize}; |
313
|
245
|
|
|
|
|
4466
|
return \%params; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
sub available_methods { |
317
|
573
|
|
|
573
|
1
|
2544
|
return (qw/bare_html |
318
|
|
|
|
|
|
|
html |
319
|
|
|
|
|
|
|
epub |
320
|
|
|
|
|
|
|
a4_pdf |
321
|
|
|
|
|
|
|
lt_pdf |
322
|
|
|
|
|
|
|
tex |
323
|
|
|
|
|
|
|
zip |
324
|
|
|
|
|
|
|
pdf |
325
|
|
|
|
|
|
|
sl_tex |
326
|
|
|
|
|
|
|
sl_pdf |
327
|
|
|
|
|
|
|
/); |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
sub compile_methods { |
330
|
318
|
|
|
318
|
1
|
927
|
my $self = shift; |
331
|
318
|
|
|
|
|
935
|
return grep { $self->$_ } $self->available_methods; |
|
3180
|
|
|
|
|
8222
|
|
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
sub extra { |
337
|
300
|
|
|
300
|
1
|
2152
|
return %{ shift->extra_opts }; |
|
300
|
|
|
|
|
8205
|
|
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
sub _build_standalone { |
342
|
218
|
|
|
218
|
|
7104
|
my $self = shift; |
343
|
218
|
100
|
66
|
|
|
1940
|
if ($self->a4_pdf || $self->lt_pdf) { |
344
|
2
|
|
|
|
|
29
|
return 0; |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
else { |
347
|
216
|
|
|
|
|
3226
|
return 1; |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
has logger => (is => 'rw', |
352
|
|
|
|
|
|
|
isa => CodeRef, |
353
|
|
|
|
|
|
|
default => sub { return sub { print @_ }; }); |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
has report_failure_sub => (is => 'rw', |
356
|
|
|
|
|
|
|
isa => CodeRef, |
357
|
|
|
|
|
|
|
default => sub { |
358
|
|
|
|
|
|
|
return sub { |
359
|
|
|
|
|
|
|
print "Failure to compile $_[0]\n"; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
}); |
362
|
|
|
|
|
|
|
has errors => (is => 'rwp', isa => ArrayRef, default => sub { [] }); |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head2 BUILDARGS routine |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
The C key is passed instead to C. Directories are |
368
|
|
|
|
|
|
|
made absolute. If no formats are required explicitely, set them all to |
369
|
|
|
|
|
|
|
true. |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=cut |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
=head2 METHODS |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head3 fonts |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
The L object, constructed from |
378
|
|
|
|
|
|
|
the fontspec argument and eventual C font keys passed. |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=head3 version |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
Report version information |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
=cut |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub version { |
387
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
388
|
0
|
|
|
|
|
0
|
my $musev = $Text::Amuse::VERSION; |
389
|
0
|
|
|
|
|
0
|
my $selfv = $VERSION; |
390
|
0
|
|
|
|
|
0
|
my $pdfv = $PDF::Imposition::VERSION; |
391
|
0
|
|
|
|
|
0
|
return "Using Text::Amuse $musev, Text::Amuse::Compiler $selfv, " . |
392
|
|
|
|
|
|
|
"PDF::Imposition $pdfv\n"; |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
=head3 logger($sub) |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
Accessor/setter for the subroutine which will handle the logging. |
398
|
|
|
|
|
|
|
Defaults to printing to the standard output. |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=head3 recursive_compile($directory) |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
Compile recursive a directory, comparing the timestamps of the status |
403
|
|
|
|
|
|
|
file with the muse file. If the status file is newer, the file is |
404
|
|
|
|
|
|
|
ignored. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
Return a list of absolute path to the files processed. To infer the |
407
|
|
|
|
|
|
|
success or the failure of each file look at the status file or at the |
408
|
|
|
|
|
|
|
logs. |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=head3 find_muse_files($directory) |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
Return a sorted list of files with extension .muse excluding illegal |
413
|
|
|
|
|
|
|
names (including hidden files and directories). |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=head3 find_new_muse_files($directory) |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
As above, but check the age of the status file and skip already |
418
|
|
|
|
|
|
|
processed files. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=cut |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub find_muse_files { |
423
|
5
|
|
|
5
|
1
|
2686
|
my ($self, $dir) = @_; |
424
|
5
|
|
|
|
|
10
|
my @files; |
425
|
5
|
50
|
33
|
|
|
89
|
die "$dir is not a dir" unless ($dir && -d $dir); |
426
|
|
|
|
|
|
|
find( sub { |
427
|
80
|
|
|
80
|
|
194
|
my $file = $_; |
428
|
|
|
|
|
|
|
# file only |
429
|
80
|
100
|
|
|
|
3129
|
return unless -f $file; |
430
|
40
|
100
|
|
|
|
552
|
return unless $file =~ m/^[0-9a-z][0-9a-z-]+[0-9a-z]+\.muse$/; |
431
|
|
|
|
|
|
|
# exclude hidden directories |
432
|
20
|
100
|
|
|
|
59
|
if ($File::Find::dir =~ m/\./) { |
433
|
8
|
|
|
|
|
70
|
my @dirs = File::Spec->splitdir($File::Find::dir); |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# for the purpose of filtering, the leading . is harmless |
436
|
8
|
100
|
33
|
|
|
57
|
if (@dirs && $dirs[0] && $dirs[0] eq '.') { |
|
|
|
66
|
|
|
|
|
437
|
4
|
|
|
|
|
9
|
shift(@dirs); |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
8
|
|
|
|
|
20
|
my @dots = grep { m/^\./ } @dirs; |
|
24
|
|
|
|
|
58
|
|
441
|
8
|
100
|
|
|
|
125
|
return if @dots; |
442
|
|
|
|
|
|
|
} |
443
|
15
|
|
|
|
|
622
|
push @files, File::Spec->rel2abs($file); |
444
|
5
|
|
|
|
|
415
|
}, $dir); |
445
|
5
|
|
|
|
|
77
|
return sort @files; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub find_new_muse_files { |
449
|
4
|
|
|
4
|
1
|
5178
|
my ($self, $dir) = @_; |
450
|
4
|
|
|
|
|
15
|
my @candidates = $self->find_muse_files($dir); |
451
|
4
|
|
|
|
|
9
|
my @newf; |
452
|
4
|
|
|
|
|
9
|
my $mtime = 9; |
453
|
4
|
|
|
|
|
16
|
while (@candidates) { |
454
|
12
|
|
|
|
|
27
|
my $f = shift(@candidates); |
455
|
12
|
50
|
33
|
|
|
160
|
die "I was expecting a file here" unless $f && -f $f; |
456
|
12
|
|
|
|
|
31
|
my $status = $f; |
457
|
12
|
|
|
|
|
58
|
$status =~ s/\.muse$/.status/; |
458
|
12
|
100
|
|
|
|
557
|
if (! -f $status) { |
|
|
50
|
|
|
|
|
|
459
|
7
|
|
|
|
|
25
|
push @newf, $f; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
elsif ((stat($f))[$mtime] > (stat($status))[$mtime]) { |
462
|
0
|
|
|
|
|
0
|
push @newf, $f; |
463
|
|
|
|
|
|
|
} |
464
|
|
|
|
|
|
|
} |
465
|
4
|
|
|
|
|
22
|
return @newf; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub recursive_compile { |
469
|
2
|
|
|
2
|
1
|
1859
|
my ($self, $dir) = @_; |
470
|
2
|
|
|
|
|
9
|
return $self->compile($self->find_new_muse_files($dir)); |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=head3 compile($file1, $file2, ...); |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
Main method to get the job done, passing the list of muse files. You |
477
|
|
|
|
|
|
|
can inspect the errors calling C. It does produce some output. |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
The file may also be an hash reference. In this case, the compile will |
480
|
|
|
|
|
|
|
act on a list of files and will merge them. Beware that so far only |
481
|
|
|
|
|
|
|
the C and C options will work, while the other html methods |
482
|
|
|
|
|
|
|
will throw exceptions or (worse probably) produce empty files. This |
483
|
|
|
|
|
|
|
will be fixed soon. This feature is marked as B and |
484
|
|
|
|
|
|
|
could change in the future. |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=head4 virtual file hashref |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
The hash reference should have those mandatory fields: |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=over 4 |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=item files |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
An B of filenames without extension. |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=item path |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
A mandatory directory where to find the above files. |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=back |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
Optional keys |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=over 4 |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=item name |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
Default to virtual. This is the basename of the files which will be |
509
|
|
|
|
|
|
|
produced. It's up to you to provide a sensible name we don't do any |
510
|
|
|
|
|
|
|
check on that. |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
=item suffix |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
Defaults to '.muse' and you have no reason to change this. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=back |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
Every other key is the metadata of the new document, so usually you |
519
|
|
|
|
|
|
|
want to set C and optionally C. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Example: |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
$c->compile({ |
524
|
|
|
|
|
|
|
# mandatory |
525
|
|
|
|
|
|
|
path => File::Spec->catdir(qw/t merged-dir/), |
526
|
|
|
|
|
|
|
files => [qw/first second/], |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
# recommended |
529
|
|
|
|
|
|
|
name => 'my-new-test', |
530
|
|
|
|
|
|
|
title => 'My new shiny test', |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
# optional |
533
|
|
|
|
|
|
|
subtitle => 'Another one', |
534
|
|
|
|
|
|
|
date => 'Today!', |
535
|
|
|
|
|
|
|
source => 'Text::Amuse::Compile', |
536
|
|
|
|
|
|
|
}); |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
You can pass as many hashref you want. |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
=cut |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
sub compile { |
543
|
295
|
|
|
295
|
1
|
193882
|
my ($self, @files) = @_; |
544
|
295
|
|
|
|
|
1523
|
$self->reset_errors; |
545
|
295
|
|
|
|
|
12125
|
my $cwd = getcwd; |
546
|
295
|
|
|
|
|
878
|
my @compiled; |
547
|
295
|
|
|
|
|
952
|
foreach my $file (@files) { |
548
|
297
|
50
|
|
|
|
4208
|
chdir $cwd or die "Couldn't chdir into $cwd $!"; |
549
|
297
|
100
|
|
|
|
1385
|
if (ref($file)) { |
550
|
16
|
|
|
|
|
41
|
eval { $self->_compile_virtual_file($file); }; |
|
16
|
|
|
|
|
184
|
|
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
else { |
553
|
281
|
|
|
|
|
700
|
eval { $self->_compile_file($file); }; |
|
281
|
|
|
|
|
1287
|
|
554
|
|
|
|
|
|
|
} |
555
|
297
|
|
|
|
|
1394
|
my $fatal = $@; |
556
|
297
|
50
|
|
|
|
5837
|
chdir $cwd or die "Couldn't chdir into $cwd $!"; |
557
|
297
|
100
|
|
|
|
1641
|
if ($fatal) { |
558
|
3
|
|
|
|
|
77
|
$self->logger->($fatal); |
559
|
3
|
|
|
|
|
52
|
$self->add_errors("$file $fatal"); |
560
|
3
|
|
|
|
|
64
|
$self->report_failure_sub->($file); |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
else { |
563
|
294
|
|
|
|
|
1718
|
push @compiled, $file; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
} |
566
|
295
|
|
|
|
|
2078
|
return @compiled; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
sub _compile_virtual_file { |
570
|
16
|
|
|
16
|
|
56
|
my ($self, $vfile) = @_; |
571
|
|
|
|
|
|
|
# check if the reference is good |
572
|
16
|
50
|
|
|
|
74
|
die "Virtual file is not a hashref" unless ref($vfile) eq 'HASH'; |
573
|
16
|
|
|
|
|
128
|
my %virtual = %$vfile; |
574
|
16
|
|
|
|
|
59
|
my $files = delete $virtual{files}; |
575
|
16
|
50
|
33
|
|
|
133
|
die "No file list found" unless $files && @$files; |
576
|
16
|
|
|
|
|
41
|
my $path = delete $virtual{path}; |
577
|
16
|
50
|
33
|
|
|
338
|
die "No directory path" unless $path && -d $path; |
578
|
16
|
50
|
|
|
|
167
|
chdir $path or die "Couldn't chdir into $path $!"; |
579
|
16
|
|
50
|
|
|
117
|
my $suffix = delete($virtual{suffix}) || '.muse'; |
580
|
16
|
|
50
|
|
|
67
|
my $name = delete($virtual{name}) || 'virtual'; |
581
|
16
|
|
|
|
|
507
|
$self->logger->("Working on virtual file in " . getcwd(). "\n"); |
582
|
16
|
|
|
|
|
119
|
my @filelist = map { Text::Amuse::Compile::FileName->new($_) } @$files; |
|
53
|
|
|
|
|
300
|
|
583
|
|
|
|
|
|
|
my $doc = Text::Amuse::Compile::Merged->new(files => \@filelist, |
584
|
16
|
|
|
|
|
63
|
include_paths => [ @{$self->include_paths} ], |
|
16
|
|
|
|
|
245
|
|
585
|
|
|
|
|
|
|
%virtual); |
586
|
|
|
|
|
|
|
my $muse = Text::Amuse::Compile::File->new( |
587
|
|
|
|
|
|
|
name => $name, |
588
|
|
|
|
|
|
|
suffix => $suffix, |
589
|
|
|
|
|
|
|
luatex => $self->luatex, |
590
|
|
|
|
|
|
|
ttdir => $self->ttdir, |
591
|
|
|
|
|
|
|
options => { $self->extra }, |
592
|
|
|
|
|
|
|
document => $doc, |
593
|
|
|
|
|
|
|
logger => $self->logger, |
594
|
|
|
|
|
|
|
virtual => 1, |
595
|
|
|
|
|
|
|
standalone => $self->standalone, |
596
|
|
|
|
|
|
|
fonts => $self->fonts, |
597
|
|
|
|
|
|
|
epub_embed_fonts => $self->epub_embed_fonts, |
598
|
16
|
|
|
|
|
214
|
include_paths => [ @{$self->include_paths} ], |
|
16
|
|
|
|
|
9279
|
|
599
|
|
|
|
|
|
|
); |
600
|
16
|
|
|
|
|
1503
|
$self->_muse_compile($muse); |
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
sub _compile_file { |
605
|
281
|
|
|
281
|
|
955
|
my ($self, $file) = @_; |
606
|
281
|
|
|
|
|
3238
|
my $fileobj = Text::Amuse::Compile::FileName->new($file); |
607
|
281
|
100
|
66
|
|
|
2406
|
die "$file is not a file" unless $fileobj && -f $fileobj->full_path; |
608
|
|
|
|
|
|
|
|
609
|
280
|
50
|
|
|
|
1580
|
if (my $path = $fileobj->path) { |
610
|
280
|
50
|
|
|
|
2708
|
chdir $path or die "Cannot chdir into $path from " . getcwd() . "\n" ; |
611
|
|
|
|
|
|
|
}; |
612
|
|
|
|
|
|
|
|
613
|
280
|
|
|
|
|
1349
|
my $filename = $fileobj->filename; |
614
|
280
|
|
|
|
|
8984
|
$self->logger->("Working on $filename file in " . getcwd(). "\n"); |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
my %args = ( |
617
|
|
|
|
|
|
|
name => $fileobj->name, |
618
|
|
|
|
|
|
|
suffix => $fileobj->suffix, |
619
|
|
|
|
|
|
|
ttdir => $self->ttdir, |
620
|
|
|
|
|
|
|
options => { $self->extra }, |
621
|
|
|
|
|
|
|
logger => $self->logger, |
622
|
|
|
|
|
|
|
standalone => $self->standalone, |
623
|
|
|
|
|
|
|
fonts => $self->fonts, |
624
|
|
|
|
|
|
|
epub_embed_fonts => $self->epub_embed_fonts, |
625
|
|
|
|
|
|
|
luatex => $self->luatex, |
626
|
|
|
|
|
|
|
fileobj => $fileobj, |
627
|
|
|
|
|
|
|
coverpage_only_if_toc => $self->coverpage_only_if_toc, |
628
|
280
|
|
|
|
|
4692
|
include_paths => [ @{$self->include_paths} ], |
|
279
|
|
|
|
|
180430
|
|
629
|
|
|
|
|
|
|
); |
630
|
|
|
|
|
|
|
|
631
|
279
|
|
|
|
|
6592
|
my $muse = Text::Amuse::Compile::File->new(%args); |
632
|
279
|
|
|
|
|
8952
|
$self->_muse_compile($muse); |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
# write the status file and unlock it after that. |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
sub _write_status_file { |
638
|
295
|
|
|
295
|
|
1470
|
my ($self, $fh, $status, @diagnostics) = @_; |
639
|
295
|
|
|
|
|
12912
|
my $localtime = localtime(); |
640
|
295
|
|
|
|
|
2710
|
my %avail = ( |
641
|
|
|
|
|
|
|
FAILED => 1, |
642
|
|
|
|
|
|
|
DELETED => 1, |
643
|
|
|
|
|
|
|
OK => 1, |
644
|
|
|
|
|
|
|
); |
645
|
295
|
50
|
|
|
|
1768
|
die unless $avail{$status}; |
646
|
295
|
|
|
|
|
4197
|
print $fh "$status $$ $localtime\n"; |
647
|
295
|
100
|
|
|
|
1318
|
if (@diagnostics) { |
648
|
1
|
|
|
|
|
3
|
print $fh "\n"; |
649
|
1
|
|
|
|
|
3
|
foreach my $diag (@diagnostics) { |
650
|
1
|
|
|
|
|
4
|
print $fh "$diag\n"; |
651
|
|
|
|
|
|
|
} |
652
|
|
|
|
|
|
|
} |
653
|
295
|
50
|
|
|
|
13102
|
flock($fh, LOCK_UN) or die "Cannot unlock status file\n"; |
654
|
295
|
|
|
|
|
11229
|
close $fh; |
655
|
|
|
|
|
|
|
} |
656
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
sub _muse_compile { |
658
|
295
|
|
|
295
|
|
1047
|
my ($self, $muse) = @_; |
659
|
295
|
|
|
|
|
1507
|
my $statusfile = $muse->status_file; |
660
|
295
|
50
|
|
19
|
|
37676
|
open (my $fhlock, '>:encoding(utf-8)', $statusfile) |
|
19
|
|
|
|
|
147
|
|
|
19
|
|
|
|
|
39
|
|
|
19
|
|
|
|
|
184
|
|
661
|
|
|
|
|
|
|
or die "Cannot open $statusfile\n!"; |
662
|
295
|
50
|
|
|
|
49246
|
flock($fhlock, LOCK_EX | LOCK_NB) or die "Cannot acquire lock on $statusfile"; |
663
|
|
|
|
|
|
|
|
664
|
295
|
|
|
|
|
5001187
|
sleep 5 if DEBUG; |
665
|
|
|
|
|
|
|
|
666
|
295
|
|
|
|
|
898
|
my @fatals; |
667
|
|
|
|
|
|
|
my @warnings; |
668
|
|
|
|
|
|
|
|
669
|
295
|
|
|
|
|
1908
|
$muse->purge_all unless DEBUG; |
670
|
295
|
100
|
|
|
|
9070
|
if ($muse->is_deleted) { |
671
|
1
|
|
|
|
|
60
|
$self->_write_status_file($fhlock, 'DELETED'); |
672
|
1
|
|
|
|
|
28
|
return; |
673
|
|
|
|
|
|
|
} |
674
|
294
|
|
|
|
|
20436
|
foreach my $method ($self->compile_methods) { |
675
|
434
|
100
|
66
|
|
|
3414
|
if ($method eq 'sl_pdf' or $method eq 'sl_tex') { |
676
|
16
|
100
|
|
|
|
303
|
unless ($muse->wants_slides) { |
677
|
7
|
|
|
|
|
424
|
$self->logger->("* Slides not required\n"); |
678
|
7
|
|
|
|
|
33
|
next; |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
} |
681
|
427
|
|
|
|
|
1478
|
my $output = eval { |
682
|
|
|
|
|
|
|
local $SIG{__WARN__} = sub { |
683
|
1
|
|
|
1
|
|
308
|
push @warnings, @_; |
684
|
427
|
|
|
|
|
3898
|
}; |
685
|
427
|
|
|
|
|
2702
|
$muse->$method |
686
|
|
|
|
|
|
|
}; |
687
|
427
|
100
|
|
|
|
85678
|
if ($@) { |
|
|
50
|
|
|
|
|
|
688
|
1
|
|
|
|
|
3
|
push @fatals, $@; |
689
|
1
|
|
|
|
|
3
|
last; |
690
|
|
|
|
|
|
|
} |
691
|
|
|
|
|
|
|
elsif ($output) { |
692
|
426
|
|
|
|
|
18948
|
$self->logger->("* Created $output\n"); |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
else { |
695
|
0
|
|
|
|
|
0
|
$self->logger->("* $method skipped\n"); |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
} |
698
|
294
|
100
|
|
|
|
6582
|
if (@fatals) { |
699
|
1
|
|
|
|
|
6
|
$self->_write_status_file($fhlock, 'FAILED', @fatals); |
700
|
1
|
|
|
|
|
138
|
die join(" ", @fatals); |
701
|
|
|
|
|
|
|
} |
702
|
|
|
|
|
|
|
else { |
703
|
293
|
|
|
|
|
1955
|
$self->_write_status_file($fhlock, 'OK'); |
704
|
|
|
|
|
|
|
} |
705
|
293
|
100
|
|
|
|
3068
|
$muse->cleanup if $self->cleanup; |
706
|
293
|
|
|
|
|
118443
|
foreach my $warn (@warnings) { |
707
|
1
|
50
|
|
|
|
27
|
$self->logger->("Warning: $warn") if $warn; |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
sub _suffix_for_method { |
712
|
27
|
|
|
27
|
|
58
|
my ($self, $method) = @_; |
713
|
27
|
50
|
|
|
|
57
|
return unless $method; |
714
|
27
|
|
|
|
|
40
|
my $ext = $method; |
715
|
27
|
|
|
|
|
77
|
$ext =~ s/_/./g; |
716
|
27
|
|
|
|
|
52
|
$ext = '.' . $ext; |
717
|
27
|
|
|
|
|
69
|
return $ext; |
718
|
|
|
|
|
|
|
} |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
=head3 file_needs_compilation |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
Returns true if the file has already been compiled, false if some |
723
|
|
|
|
|
|
|
output file is missing or stale. |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
=head3 parse_muse_header($file) |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
Return a L object for the given |
728
|
|
|
|
|
|
|
file. |
729
|
|
|
|
|
|
|
|
730
|
|
|
|
|
|
|
=cut |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
sub _check_file_basename { |
733
|
29
|
|
|
29
|
|
55
|
my ($self, $file) = @_; |
734
|
29
|
|
|
|
|
148
|
my $fileobj = Text::Amuse::Compile::FileName->new($file); |
735
|
29
|
|
|
|
|
95
|
return File::Spec->catfile($fileobj->path, $fileobj->name); |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
sub parse_muse_header { |
739
|
53
|
|
|
53
|
1
|
310
|
my ($self, $file) = @_; |
740
|
53
|
|
|
|
|
391
|
my $path = Text::Amuse::Compile::FileName->new($file)->full_path; |
741
|
53
|
|
|
|
|
299
|
return Text::Amuse::Compile::MuseHeader->new(muse_fast_scan_header($path)); |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
sub file_needs_compilation { |
746
|
16
|
|
|
16
|
1
|
5016
|
my ($self, $file) = @_; |
747
|
16
|
|
|
|
|
31
|
my $need = 0; |
748
|
16
|
|
|
|
|
25
|
my $mtime = 9; |
749
|
16
|
|
|
|
|
40
|
my $basename = $self->_check_file_basename($file); |
750
|
16
|
|
|
|
|
49
|
my $header = $self->parse_muse_header($file); |
751
|
16
|
|
|
|
|
1863
|
foreach my $m ($self->compile_methods) { |
752
|
22
|
|
|
|
|
70
|
my $outsuffix = $self->_suffix_for_method($m); |
753
|
22
|
|
|
|
|
44
|
my $outfile = $basename . $outsuffix; |
754
|
22
|
100
|
66
|
|
|
77
|
if ($m eq 'sl_tex' or $m eq 'sl_pdf') { |
755
|
11
|
100
|
|
|
|
197
|
next unless $header->wants_slides; |
756
|
|
|
|
|
|
|
} |
757
|
15
|
100
|
66
|
|
|
445
|
if (-f $outfile and (stat($outfile))[$mtime] >= (stat($file))[$mtime]) { |
758
|
11
|
|
|
|
|
24
|
print "$outfile is OK\n" if DEBUG; |
759
|
11
|
|
|
|
|
32
|
next; |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
else { |
762
|
4
|
|
|
|
|
18
|
print "$outfile is NOT OK\n" if DEBUG; |
763
|
4
|
|
|
|
|
12
|
$need = 1; |
764
|
4
|
|
|
|
|
9
|
last; |
765
|
|
|
|
|
|
|
} |
766
|
|
|
|
|
|
|
} |
767
|
16
|
|
|
|
|
290
|
return $need; |
768
|
|
|
|
|
|
|
} |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
=head2 purge(@files) |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
Remove all the files produced by the compilation of the files passed |
773
|
|
|
|
|
|
|
as arguments. |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
=cut |
776
|
|
|
|
|
|
|
|
777
|
|
|
|
|
|
|
sub purge { |
778
|
13
|
|
|
13
|
1
|
2231
|
my ($self, @files) = @_; |
779
|
13
|
|
|
|
|
34
|
foreach my $file (@files) { |
780
|
13
|
|
|
|
|
33
|
my $basename = $self->_check_file_basename($file); |
781
|
13
|
|
|
|
|
101
|
foreach my $ext (Text::Amuse::Compile::File->purged_extensions) { |
782
|
351
|
50
|
|
|
|
760
|
die "?" if $ext eq '.muse'; |
783
|
351
|
|
|
|
|
581
|
my $produced = $basename . $ext; |
784
|
351
|
100
|
|
|
|
3604
|
if (-f $produced) { |
785
|
5
|
|
|
|
|
147
|
$self->logger->("Purging $produced\n"); |
786
|
5
|
50
|
|
|
|
296
|
unlink $produced or warn "Cannot unlink $produced $!"; |
787
|
|
|
|
|
|
|
} |
788
|
|
|
|
|
|
|
} |
789
|
|
|
|
|
|
|
} |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
=head3 report_failure_sub(sub { push @problems, $_[0] }); |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
You can set the sub to be used to report problems using this accessor. |
796
|
|
|
|
|
|
|
It will receive as first argument the file which led to failure. |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
The actual errors are logged by the C sub. |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
=head3 errors |
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
Accessor to the catched errors. It returns a list of strings. |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
=head3 add_errors($error1, $error2,...) |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
Add an error. [Internal] |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=head3 reset_errors |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
Reset the errors |
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=head3 has_errors |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
Return the number of errors (handy to use as a boolean). |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
=cut |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
sub add_errors { |
819
|
3
|
|
|
3
|
1
|
12
|
my ($self, @args) = @_; |
820
|
3
|
|
|
|
|
7
|
push @{$self->errors}, @args; |
|
3
|
|
|
|
|
22
|
|
821
|
|
|
|
|
|
|
} |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
sub reset_errors { |
824
|
295
|
|
|
295
|
1
|
834
|
my $self = shift; |
825
|
295
|
|
|
|
|
8179
|
$self->_set_errors([]); |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
sub has_errors { |
829
|
0
|
|
|
0
|
1
|
0
|
return scalar(@{ shift->errors }); |
|
0
|
|
|
|
|
0
|
|
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
|
832
|
|
|
|
|
|
|
=head1 TeX live packages needed. |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
You need the xetex scheme plus the following packages: fontspec, |
835
|
|
|
|
|
|
|
polyglossia, pzdr, wrapfig, footmisc, ulem, microtype, zapfding. |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
For the luatex options, same as above plus luatex (and the lualatex |
838
|
|
|
|
|
|
|
format), luatexbase, luaotfload. |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
The luatex option could give better microtypography results but is |
841
|
|
|
|
|
|
|
slower (x4) and requires more memory (x2). |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
=head1 INTERNAL CONSTANTS |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
=head2 DEBUG |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
Set from AMW_DEBUG environment. |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
=head1 AUTHOR |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
Marco Pessotto, C<< >> |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
=head1 BUGS |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
Please mail the author and provide a minimal example to add to the |
856
|
|
|
|
|
|
|
test suite. |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
=head1 SUPPORT |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
perldoc Text::Amuse::Compile |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
=head1 LICENSE |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
867
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
868
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
See L for more information. |
871
|
|
|
|
|
|
|
|
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
=cut |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
1; # End of Text::Amuse::Compile |