paperstack-cli 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,736 @@
1
+ #!/usr/bin/env perl
2
+ # Inspired by latexpand by D. Musliner, University of Michigan
3
+ # 2012-2026: Matthieu Moy <git@matthieu-moy.fr>
4
+ # BSD License, see LICENCE file.
5
+
6
+ use strict;
7
+ use Cwd;
8
+ use Getopt::Long;
9
+ use IO::Handle;
10
+ use File::Spec;
11
+
12
+ my $TEXINPUTS = $ENV{'TEXINPUTS'};
13
+ # By default, search in current directory. We use '.' and not getcwd()
14
+ # to avoid issues if the working directory contains a ':' character.
15
+ if (!$TEXINPUTS) { $TEXINPUTS = '.'; }
16
+
17
+ my $verbose;
18
+ my $keep_comments;
19
+ my $keep_includes;
20
+ my $empty_comments;
21
+ my $help;
22
+ my $long_help;
23
+ my %defines = ();
24
+ my $output;
25
+ my $explain;
26
+ my $show_graphics;
27
+ my $graphics_extensions = ":.pdf:.png:.jpg:.eps";
28
+ my $expand_usepackage;
29
+ my $expand_bbl;
30
+ my $biber;
31
+ my $fatal;
32
+ my $version;
33
+ my $makeatletter;
34
+ my $inside_import;
35
+ my $in_enc = "bytes";
36
+ my $out_enc = "bytes";
37
+
38
+ GetOptions (
39
+ 'h' => \$help,
40
+ 'help' => \$long_help,
41
+ 'verbose|v' => \$verbose,
42
+ 'keep-comments' => \$keep_comments,
43
+ 'keep-includes' => \$keep_includes,
44
+ 'empty-comments' => \$empty_comments,
45
+ 'define|d=s%' => \%defines,
46
+ 'output|o=s' => \$output,
47
+ 'explain' => \$explain,
48
+ 'show-graphics' => \$show_graphics,
49
+ 'graphics-extensions=s' => \$graphics_extensions,
50
+ 'expand-usepackage' => \$expand_usepackage,
51
+ 'expand-bbl=s' => \$expand_bbl,
52
+ 'biber=s' => \$biber,
53
+ 'fatal' => \$fatal,
54
+ 'version' => \$version,
55
+ 'makeatletter' => \$makeatletter,
56
+ 'in-encoding=s' => \$in_enc,
57
+ 'out-encoding=s' => \$out_enc,
58
+ ) or pod2usage_wrapper(2);
59
+ version() if $version;
60
+ pod2usage_wrapper(0) if $help;
61
+ pod2usage_wrapper(-exitstatus => 0, -output => \*STDOUT, -verbose => 2) if $long_help;
62
+
63
+ sub pod2usage_wrapper
64
+ {
65
+ # Like pod2usage, but fall back to a simpler implem in case
66
+ # pod2usage can't be found.
67
+ if (eval {require Pod::Usage;1;} ne 1) {
68
+ print "Please install perldoc and Pod::Usage to get proper help.\n";
69
+ my $started = 0;
70
+ open (my $in, '<', "$0") or die $!;
71
+ while (<$in>) {
72
+ if ($started) {
73
+ print;
74
+ }
75
+ if (/^__END__$/) {
76
+ $started = 1;
77
+ }
78
+ }
79
+ } else {
80
+ Pod::Usage->import();
81
+ pod2usage(@_);
82
+ }
83
+ }
84
+
85
+ sub get_version
86
+ {
87
+ # $VERSION's value will be substituted by 'make dist', but the
88
+ # next line won't (the string has to be broken to avoid it).
89
+ my $VERSION = '@LATEXPAND_VERSION@';
90
+ if ($VERSION eq '@LATEXPAND' . '_VERSION@') {
91
+ my($vol,$dir,$file) = File::Spec->splitpath($0);
92
+ chdir($dir);
93
+ $VERSION = `git describe --tags HEAD 2>/dev/null`;
94
+ }
95
+ if ($VERSION eq '') {
96
+ $VERSION = '<unknown version>';
97
+ }
98
+ $VERSION =~ s/^\s+|\s+$//g;
99
+ return $VERSION;
100
+ }
101
+
102
+ sub version
103
+ {
104
+ print "latexpand version ". get_version() .".\n";
105
+ exit(0);
106
+ }
107
+
108
+ my $nl = "";
109
+ if ($empty_comments) {
110
+ $nl = "%\n";
111
+ }
112
+
113
+ if ($output && $output ne "-") {
114
+ open (my $OUTPUT, '>', "$output") or die $!;
115
+ STDOUT->fdopen(\*$OUTPUT, 'w') or die $!;
116
+ }
117
+
118
+ sub say
119
+ {
120
+ if ($verbose) {
121
+ print STDERR "$_[0]";
122
+ }
123
+ }
124
+
125
+ my $makeatletter_found;
126
+ my $in_preamble;
127
+
128
+ use open IN => ":$in_enc", OUT => ":$out_enc";
129
+
130
+ foreach my $file (@ARGV)
131
+ {
132
+ say "processing $file\n";
133
+ $makeatletter_found = 0;
134
+ $in_preamble = 1;
135
+ $inside_import = "";
136
+ if ($file =~ /\.bib$/) {
137
+ warn "WARNING: latexpand is not meant to be used on BibTeX files like '$file'.\n" .
138
+ " Run latexpand on your main .tex file, using '--expand-bbl FILE'\n" .
139
+ " or '--biber FILE' if needed to inline the generated bbl file.\n";
140
+ } elsif (not $file =~ /\.tex$/) {
141
+ warn "WARNING: latexpand is meant to be used on .tex files, which $file isn't.\n";
142
+ }
143
+ process_file($file, " ");
144
+ }
145
+
146
+ sub cat_file
147
+ {
148
+ my $file = shift;
149
+ open (my $INFILE, "<", $file) || die "could not open input file '$file'\n";
150
+ while (<$INFILE>) {
151
+ print;
152
+ }
153
+ close ($INFILE);
154
+ }
155
+
156
+ sub process_file
157
+ {
158
+ my $file = shift;
159
+ my $prefix = (shift || "");
160
+ my $in_comment = 0;
161
+ open(my $FILE, "<", $file) or die "could not open input file '$file'\n";
162
+ my $commented_newline = 0;
163
+ while (my $line = <$FILE>) {
164
+ if ($line =~ /^[ \t]*\\endinput/) {
165
+ # Surprisingly, text after \endinput on the
166
+ # same line is kept in output. Also, add a
167
+ # space (before %), automatically inserted by
168
+ # TeX at the end of file.
169
+ $line =~ s/\\endinput(.*)\n?/$1 % /;
170
+ $in_comment = 1;
171
+ process_line($line, $prefix, \$commented_newline);
172
+ last;
173
+ }
174
+ while (my ($k, $v) = each (%defines))
175
+ {
176
+ $line=~s!\\$k!$v!g;
177
+ }
178
+ process_line($line, $prefix, \$commented_newline, $file);
179
+ if ($line =~ /^%.*[^\n]\z/ || $line =~ /[^\\]%.*[^\n]\z/) {
180
+ # file ends with a comment not ending with a newline
181
+ print "\n";
182
+ }
183
+ # Garbage at end of line after \end{document} is
184
+ # ignored by LaTeX, but we don't allow anything before
185
+ # to avoid e.g. \verb|\end{document}| from terminating
186
+ # the file.
187
+ if (!$keep_comments && $line =~ /^[ \t]*\\end\{document\}/) {
188
+ last;
189
+ }
190
+ }
191
+ close($FILE);
192
+ return $in_comment;
193
+ }
194
+
195
+ # process_import_command("include|input", ___)
196
+ # "include" prepends and appends a \clearpage{} similar to \include
197
+ sub process_import_command
198
+ {
199
+ my ($kind, $before, $dir, $full_filename, $after, $prefix) = @_;
200
+ if ($explain) {
201
+ print "% dir " . $dir ."\n";
202
+ print "% full_filename " . $full_filename ."\n";
203
+ print "% after " . $after ."\n";
204
+ print "% inside_import $inside_import\n";
205
+ }
206
+ $full_filename = $dir . $full_filename;
207
+ if ($inside_import) {
208
+ $full_filename = $inside_import . $full_filename;
209
+ }
210
+ print "% cat(inside_import,dir,full_filename) " . $full_filename ."\n" if ($explain);
211
+ $full_filename = find_tex_file($full_filename, ":.tex");
212
+ if (!$full_filename) {
213
+ return 0;
214
+ }
215
+
216
+ say $prefix . "Found $kind for file: $full_filename\n";
217
+ print $before . $nl;
218
+ if ($kind eq "include") {
219
+ print '\clearpage{}' . $nl;
220
+ }
221
+ print "% start $kind $full_filename\n" if ($explain);
222
+ my $previous_import_dir = $inside_import;
223
+ $inside_import = $inside_import . $dir;
224
+ my $in_comment = process_file($full_filename, $prefix . " ");
225
+ $inside_import = $previous_import_dir;
226
+ if ($explain) {
227
+ print " % end $kind $full_filename\n";
228
+ } elsif ($in_comment) {
229
+ print "\n";
230
+ }
231
+ if ($kind eq "include") {
232
+ print '\clearpage{}' . $nl;
233
+ print $nl . $after . "\n";
234
+ } elsif ($after =~ /[^\s]/) {
235
+ # LaTeX produces this space, so let's do it also
236
+ print " " . $nl . $after . "\n";
237
+ } else {
238
+ print " ";
239
+ }
240
+ return 1;
241
+ }
242
+
243
+ sub process_line
244
+ {
245
+ my ($line, $prefix, $commented_newline, $file) = @_;
246
+ $_ = $line;
247
+ if ($$commented_newline) {
248
+ # Leading whitespaces after a comment is ignored.
249
+ # There's no space in:
250
+ # Line 1%
251
+ # Line 2.
252
+ # Match just space and tabs (\s would match \n)
253
+ s/^[ \t]*//;
254
+ if (/^$/) {
255
+ # Deal with:
256
+ #
257
+ # Line 1 % comment
258
+ #
259
+ # Line 2
260
+ #
261
+ # The newline after Line 1 is commented, but we still
262
+ # want a new paragraph. We strip the comment together
263
+ # with its newline, but re-add a newline to chnge
264
+ # paragraph here if needed:
265
+ print "\n";
266
+ }
267
+ }
268
+ $$commented_newline = 0;
269
+ # Consider \makeatletter only in preamble, because we do want
270
+ # to warn on \someCommand{\makeatletter\command@with@arobase}.
271
+ if ($in_preamble && /^[^%]*\\makeatletter/) {
272
+ $makeatletter_found = 1;
273
+ }
274
+ if ($in_preamble && /^[^%]*\\makeatother/) {
275
+ $makeatletter_found = 0;
276
+ }
277
+ my $command;
278
+ if (!$makeatletter && !$makeatletter_found
279
+ && (($command) = /^[^%]*(\\[[:alpha:]]*@[[:alpha:]]*)/)
280
+ && ($command ne '\@')) {
281
+ print STDERR "Warning: command $command containing @ found in\n";
282
+ print STDERR "Warning: $file.\n";
283
+ print STDERR "Warning: consider using --makeatletter if the result is not compilable.\n";
284
+ }
285
+
286
+ # non-comment is a sequence of:
287
+ # - escaped character (\\.), including \% and \\
288
+ # - neither '%' nor '\'.
289
+ my $NON_COMMENT = '([^\\\\%]|\\\\.)*';
290
+
291
+ unless ($keep_comments) {
292
+ # Special-case for \url{} commands, which may contain '%'
293
+ # characters. It's hard to catch them in $NON_COMMENT since we'd
294
+ # need a regexp so that "\url{foo" can't match as non-comment in
295
+ # the line \url{foo%bar}, but "\url{foo%bar}" would match.
296
+ # Escaping these '%' is not mandatory, but allowed, hence we can
297
+ # pre-process the line by escaping them, and let latexpand work
298
+ # as normal afterwards.
299
+ # Known limitation: latexpand doesn't do balanced braces
300
+ # recognition, and just refuses both { and } within \url{}
301
+ # argument for %-detection to work ([^{}%] below). Fix should be
302
+ # possible using
303
+ # https://stackoverflow.com/questions/15301708/perl-regular-expression-match-nested-brackets
304
+ # but is it worth the trouble? (file an issue or send a merge
305
+ # request if you think it is)
306
+
307
+ # While there are \url{URL} with unescaped % in URL ...
308
+ my $NON_PERCENT = '([^\\}]%|[^{}%])*';
309
+ while (/^(?<before>.*\\url\{)(?<url>$NON_PERCENT[^\\}]%$NON_PERCENT)(?<after>\}.*)$/) {
310
+ my ($before, $url, $after) = ($+{before}, $+{url}, $+{after});
311
+ # escape unescaped % in URL, if any
312
+ $url =~ s/([^\\])%/$1\\%/g;
313
+ $_ = $before . $url . $after ."\n";
314
+ }
315
+ if (!$empty_comments) {
316
+ # Include \n in pattern to avoid matching
317
+ # comments at end of files
318
+
319
+ # remove comments + whitespace-only lines completely
320
+ if (s/^\s*%.*\n//) {
321
+ $$commented_newline = 1;
322
+ }
323
+
324
+ # Special-case commands at end of line. We
325
+ # don't want "\\foo%\nbar" to become
326
+ # "\\foobar" (but we still want \@% to result
327
+ # in no space!)
328
+ if (s/^($NON_COMMENT\\([[:alpha:]]|[[:alpha:]@]{2,}))%.*\n/$1 /) {
329
+ $$commented_newline = 1;
330
+ } elsif (s/^($NON_COMMENT)%.*\n/$1/) {
331
+ # remove only the comment if the line has actual content
332
+ $$commented_newline = 1;
333
+ }
334
+ }
335
+ # Apply the "empty comments" treatment unconditionally
336
+ # for comments not matched above (it doesn't harm to
337
+ # keep an empty comment sometimes, but it may harm to
338
+ # leave a real comment if the goal was to strip them).
339
+ s/^(([^\\%]|\\.)*)%.*$/$1%/;
340
+ }
341
+
342
+ unless ($keep_includes) {
343
+ # \input{foo.tex}
344
+ my $ARGBRACES = '\{\\s*([^"}\\s][^}]*)(\\s*)\}';
345
+ # \input{"foo bar.tex"}
346
+ my $ARGQUOTED = '\{\\s*"([^"]*)"(\\s*)\}';
347
+ # \input foo.tex
348
+ my $ARGSPACES = '\\s([^\{\\s][^\\s]+?)\\s()';
349
+ my $ARGUMENT = "\\s*?(?|$ARGBRACES|$ARGQUOTED|$ARGSPACES)";
350
+
351
+ if (my ($before, $ignored, $full_filename, $trailing, $after)
352
+ = /^($NON_COMMENT)\\include$ARGUMENT(.*)$/) {
353
+ $full_filename = find_tex_file($full_filename . ".tex");
354
+ if ($full_filename) {
355
+ say $prefix . "Found include for file: $full_filename\n";
356
+ print $before . $nl;
357
+ print '\clearpage{}' . $nl;
358
+ print "% start include $full_filename\n" if ($explain);
359
+ my $in_comment = process_file($full_filename, $prefix . " ");
360
+ if ($explain) {
361
+ print " % end include $full_filename\n";
362
+ } elsif ($in_comment) {
363
+ print "\n";
364
+ }
365
+ print '\clearpage{}' . $nl;
366
+ print $nl . $after . "\n";
367
+ $_ = "";
368
+ }
369
+ } elsif (my ($before, $ignored, $full_filename, $trailing, $after)
370
+ = /^($NON_COMMENT)\\input$ARGUMENT(.*)$/) {
371
+ if ($inside_import) {
372
+ $full_filename = $inside_import . $full_filename;
373
+ }
374
+ $full_filename = find_tex_file($full_filename, ":.tex");
375
+ if ($full_filename) {
376
+ say $prefix . "Found input for file: $full_filename\n";
377
+ # Apparently, in some versions of LaTeX, a space
378
+ # after filename in \input{foo.tex } is inserted
379
+ # _before_ the inclusion. That was the case for
380
+ # me when 31fa806 (deal with space after
381
+ # filename in \input and \include, 2019-12-11)
382
+ # was written, but is not anymore, hence we just
383
+ # throw $trailing away.
384
+ print $before . $nl;
385
+ print "% start input $full_filename\n" if ($explain);
386
+ my $in_comment = process_file($full_filename, $prefix . " ");
387
+ if ($explain) {
388
+ print " % end input $full_filename\n";
389
+ } elsif ($in_comment) {
390
+ print "\n";
391
+ }
392
+ if ($after =~ /[^\s]/) {
393
+ # LaTeX produces this space, so let's do it also
394
+ print " " . $nl . $after . "\n";
395
+ } else {
396
+ print " ";
397
+ }
398
+ $_ = "";
399
+ }
400
+ } elsif (my ($before, $ignored, $dir, $ignored, $full_filename, $ignored, $after)
401
+ = /^($NON_COMMENT)\\(?:import\*?|subimport\*?|inputfrom|subinputfrom)$ARGUMENT$ARGUMENT(.*)$/) {
402
+ if (process_import_command("input", $before, $dir, $full_filename, $after, $prefix)) {
403
+ $_ = "";
404
+ }
405
+ } elsif (my ($before, $ignored, $dir, $ignored, $full_filename, $ignored, $after)
406
+ = /^($NON_COMMENT)\\(?:includefrom|subincludefrom)$ARGUMENT$ARGUMENT(.*)$/) {
407
+ if (process_import_command("include", $before, $dir, $full_filename, $after, $prefix)) {
408
+ $_ = "";
409
+ }
410
+ } elsif (my ($before, $ignored, $args, $full_filename, $ignored, $after)
411
+ = /^($NON_COMMENT)\\includegraphics(\[[^\]]*?\]|)$ARGUMENT(.*)$/) {
412
+ if ($explain) {
413
+ print "% inside_import " . $inside_import ."\n";
414
+ print "% before " . $before ."\n";
415
+ print "% ignored " . $ignored ."\n";
416
+ print "% args " . $args ."\n";
417
+ print "% full_filename " . $full_filename ."\n";
418
+ print "% after " . $after ."\n";
419
+ }
420
+ if ($inside_import) {
421
+ $full_filename = $inside_import . $full_filename;
422
+ print "$before\\includegraphics" . "$args" . "{$full_filename}$after\n";
423
+ $_ = "";
424
+ }
425
+ } elsif (my ($before, $ignored, $args, $full_filename, $ignored, $after)
426
+ = /^($NON_COMMENT)\\lstinputlisting(\[[^\]]*?\]|)$ARGUMENT(.*)$/) {
427
+ if ($explain) {
428
+ print "% inside_import " . $inside_import ."\n";
429
+ print "% before " . $before ."\n";
430
+ print "% ignored " . $ignored ."\n";
431
+ print "% args " . $args ."\n";
432
+ print "% full_filename " . $full_filename ."\n";
433
+ print "% after " . $after ."\n";
434
+ }
435
+ if ($inside_import) {
436
+ $full_filename = $inside_import . $full_filename;
437
+ print "$before\\lstinputlisting" . "$args" . "{$full_filename}$after\n";
438
+ $_ = "";
439
+ }
440
+ }
441
+ }
442
+ if ($expand_usepackage) {
443
+ # Don't bother with before and after text, we just require the
444
+ # usepackage to be alone on its line.
445
+ if (my ($package_name) = /^\s*\\usepackage\{([^\}]*)\}\s*(%.*)?$/) {
446
+ my $full = find_file($package_name . ".sty", $TEXINPUTS);
447
+ if ($full) {
448
+ say $prefix . "Found package file: $full\n";
449
+ process_file($full, $prefix . " ");
450
+ $_ = "";
451
+ # Forget about any commented newline
452
+ # before the \usepackage:
453
+ $$commented_newline = 0;
454
+ } else {
455
+ say $prefix . "Not including external package $package_name\n";
456
+ }
457
+ }
458
+ }
459
+ if ($expand_bbl) {
460
+ if (my ($before, $bib_name, $after)
461
+ = /^(.*)\\(?:bibliography|bibselect)\{([^\}]*)\}(.*)$/) {
462
+ # The BBL file is not necessarily $bib_name.
463
+ # Take it from the command-line.
464
+ print $before . $nl;
465
+ say $prefix . "Expanding BBL file: $expand_bbl\n";
466
+ process_file($expand_bbl, $prefix . " ");
467
+ print " " . $nl . $after . "\n";
468
+ $_ = "";
469
+ }
470
+ }
471
+ if ($biber) {
472
+ if (my ($before, $after)
473
+ = /^(.*)\\(?:addbibresource)\{[^\}]*\}(.*)$/) {
474
+ # See https://tex.stackexchange.com/questions/166518/biblatex-include-bbl-problem-with-verb-field/166526#166526
475
+ my $biber_noext = $biber;
476
+ $biber_noext =~ s/.bbl//;
477
+ print $before . $nl;
478
+ say $prefix . "Expanding Biber BBL file: $biber\n";
479
+ print '\begin{filecontents*}{' . $biber . '}' . "\n";
480
+ cat_file($biber);
481
+ print "\n";
482
+ print '\end{filecontents*}
483
+
484
+ \usepackage{xpatch}
485
+
486
+ %Patch the biblatex input command.
487
+ %replace "testinput-bbl" if you change the name above.
488
+ %disable if you want to run biblatex/biber normally
489
+ \makeatletter
490
+ \patchcmd\blx@bblinput{\blx@blxinit}
491
+ {\blx@blxinit
492
+ \def\jobname{' . $biber_noext . '}%new jobname
493
+ }{}{\fail}
494
+ \makeatother
495
+ ';
496
+ say $prefix . "End expansion of Biber BBL file: $biber\n";
497
+ print " " . $nl . $after . "\n";
498
+ $_ = "";
499
+ }
500
+ }
501
+ if ($show_graphics) {
502
+ if (/\\includegraphics(\[[^\]]*\])?{([^}]*)}/) {
503
+ my $full_filename = $2;
504
+ if ($inside_import) {
505
+ $full_filename = $inside_import . $full_filename;
506
+ }
507
+ my $full = find_tex_file($full_filename, $graphics_extensions);
508
+ say $prefix . "needs graphics file: ";
509
+ print STDERR "$full\n";
510
+ }
511
+ }
512
+ if (/^[ \t]*\\begin\{document\}/) {
513
+ $in_preamble = 0;
514
+ if ($makeatletter) {
515
+ print '\makeatletter' . $nl;
516
+ }
517
+ }
518
+ print;
519
+ }
520
+
521
+ sub unquote
522
+ {
523
+ my $str = shift;
524
+ my $x = substr($str, 0, 1);
525
+ my $y = substr($str, -1, 1);
526
+ if ($x eq $y && ($x eq '"' || $x eq "'")) {
527
+ $str = substr($str, 1, -1);
528
+ }
529
+ # There's a weird LaTeX syntax: \include{"file\space
530
+ # with\space spaces"}, so remove these \space when unquoting.
531
+ $str =~ s/\\space / /g;
532
+ return $str;
533
+ }
534
+
535
+ # search $1 in $TEXINPUTS, with possible extensions in $2
536
+ sub find_tex_file
537
+ {
538
+ my $file = unquote(shift);
539
+ my $extensions = (shift || ":");
540
+ foreach my $ext (split(':', $extensions, -1)) {
541
+ my $full = find_file_global($file . $ext);
542
+ if ($full) {
543
+ return $full;
544
+ }
545
+ }
546
+ if ($fatal) {
547
+ die "ERROR: Could not find file [$file]\n";
548
+ } else {
549
+ print STDERR "Warning: Could not find file [$file]\n";
550
+ return;
551
+ }
552
+ }
553
+
554
+ sub find_file_global
555
+ {
556
+ my $file = shift;
557
+ if (open(my $fh, "-|", "kpsewhich", $file)) {
558
+ my $full = <$fh>;
559
+ $full =~ s/\s+$//;
560
+ close($fh);
561
+ if ($full) {
562
+ return $full;
563
+ }
564
+ }
565
+ # Should be useless, but fall-back in case kpsewhich fails (or is not installed, or ...):
566
+ return find_file($file, $TEXINPUTS);
567
+ }
568
+
569
+ # Find files, not searching for global files (to allow not expanding global .sty packages)
570
+ sub find_file
571
+ {
572
+ my ($file, $path) = @_;
573
+ if (File::Spec->file_name_is_absolute($file)) {
574
+ if (-e "$file" && ! -d "$file") {
575
+ return $file;
576
+ } else {
577
+ return;
578
+ }
579
+ }
580
+
581
+ # TEXINPUTS=...: (trailing :) means "append default search
582
+ # directories". We don't want global directories here, but
583
+ # still add . that may be needed.
584
+ if (substr($path, -1) eq ':') {
585
+ $path .= '.';
586
+ }
587
+ foreach my $dir (split(':', $path)) {
588
+ if (-e "$dir/$file" && ! -d "$dir/$file") {
589
+ return("$dir/$file");
590
+ }
591
+ }
592
+ return;
593
+ }
594
+
595
+
596
+ __END__
597
+
598
+ =head1 NAME
599
+
600
+ latexpand - Flatten LaTeX file by expanding \include and \input, ... and remove comments
601
+
602
+ =head1 SYNOPSIS
603
+
604
+ latexpand [options] FILE...
605
+
606
+ =head2 Options:
607
+
608
+ --verbose show what's going on
609
+ --keep-comments don't strip comments (comments are lines
610
+ starting with %, and anything below
611
+ \end{document})
612
+ --empty-comments keep empty comments (i.e. % at end of lines) for clarity
613
+ --keep-includes don't expand \input and \include directives
614
+ --expand-usepackage
615
+ Expand \usepackage{...} directives if the
616
+ corresponding .sty file is found in
617
+ $TEXINPUTS (or the current directory if
618
+ $TEXINPUTS is not set)
619
+ --expand-bbl FILE
620
+ Expand the bibliography by inlining FILE
621
+ (should be a *.bbl file)
622
+ --biber FILE Include \bibliography{} with FILE's content,
623
+ as needed by biblatex with the biber backend.
624
+ (similar to --expand-bbl FILE, but for
625
+ biber+biblatex).
626
+ --help this help message
627
+ --define <key>=<val>, -d <key>=<val>
628
+ defines a macro key to be replaced by value, e.g.,
629
+ when called with -d foo=bar would replace all occurences
630
+ of \foo in the code with bar. Can be supplied multiple times.
631
+ --output <file>, -o <file>
632
+ generate output in <file>
633
+ --explain generate explanatory comments in output
634
+ --show-graphics show included graphics
635
+ --graphics-extensions LIST
636
+ colon-separated list of possible graphics extensions
637
+ (used by --show-graphics to find the actual graphics files)
638
+ --fatal Die in case a file can't be found.
639
+ --makeatletter Insert a \makeatletter in the preamble. In some
640
+ rare cases it may break your document, but it
641
+ may help fixing bad interactions between
642
+ @-commands and inclusion (see BUGS section).
643
+ --in-encoding FMT, --out-encoding FMT
644
+ File encoding used by input and output files.
645
+ This uses the same syntax as PerlIO's layers.
646
+ Example:
647
+ --in-encoding 'encoding(UTF-8)'
648
+ The default is 'bytes' and should always work.
649
+
650
+ =head1 USES
651
+
652
+ The most common use of latexpand is to simplify distribution of source
653
+ LaTeX files, typically to satisfy the requirement of editors and
654
+ archival sites (springer, arXiv.org, ...) who force the authors to
655
+ submit sources. One does not necessarily want to submit sources with
656
+ comments, and uploading a document made of several files including
657
+ each other is a bit painful. By default, latexpand answers both
658
+ problems by outputing a single LaTeX file that contain no comment.
659
+
660
+ =head1 GETTING LATEXPAND
661
+
662
+ The latest version of latexpand is available here:
663
+
664
+ https://gitlab.com/latexpand/latexpand
665
+
666
+ Versions are uploaded to ctan.org from time to time:
667
+
668
+ http://www.ctan.org/pkg/latexpand
669
+
670
+ =head1 BUGS
671
+
672
+ Please, report bugs on the issue tracker on the project site:
673
+
674
+ https://gitlab.com/latexpand/latexpand/issues
675
+
676
+ =head2 Known bugs
677
+
678
+ =head3 Verbatim
679
+
680
+ latexpand currently ignores \begin{verbatim} ... \end{verbatim}, and
681
+ will therefore process any \include, \input, ... directives that
682
+ appear within verbatim environments (while it shouldn't).
683
+
684
+ LaTeX comments inside verbatim environments are also incorrectly
685
+ stripped. You can use --keep-comments as a workaround to avoid this.
686
+
687
+ =head3 Comment environment
688
+
689
+ It would be nice to remove code between \begin{comment} and
690
+ \end{comment} too if \usepackage{comment} is used.
691
+
692
+ Code like
693
+
694
+ foo%
695
+ \begin{comment}
696
+
697
+ will produce the incorrect
698
+
699
+ foo\begin{comment}
700
+
701
+ A workaround is to use --empty-comments when such tricky usage of the
702
+ comments package is done.
703
+
704
+ =head3 \makeatletter and use with transfig/xfig with \scalebox{}
705
+
706
+ If \input{} or \include{} appears as argument to a command, and the
707
+ file included contains \makeatletter, then after expansion, the
708
+ \makeatletter and the @-command appear as argument to the command,
709
+ which is forbidden because the argument is parsed (and the @-command
710
+ badly tokenized) before being executed.
711
+
712
+ This happens with
713
+
714
+ \scalebox{ \input{file-generated-by-xfig.pdf_t} }
715
+
716
+ Workaround: add \makeatletter before the scalebox manually in your
717
+ code, like
718
+
719
+ \makeatletter{}
720
+ \scalebox{ \input{file-generated-by-xfig.pdf_t} }
721
+ \makeatother{}
722
+
723
+ In the case of xfig generated files, it is necessary only for the
724
+ first occurence.
725
+
726
+ A more brute-force workaround is to use latexpand --makeatletter.
727
+
728
+ =head1 SEE ALSO
729
+
730
+ Instructions to include only the relevant .bib items (french):
731
+
732
+ https://lacl.fr/~caubert/notes/portabilite-du-tex.html#dependances
733
+
734
+ =head1 VERSION
735
+
736
+ This is latexpand version @LATEXPAND_VERSION@.