summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/texdirflatten
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2017-06-27 21:56:44 +0000
committerKarl Berry <karl@freefriends.org>2017-06-27 21:56:44 +0000
commit5ac5cca5eec65f2b492169f01406f6954c244142 (patch)
treee0c3b4c63216f807978b31b102a56c20063963ae /Master/texmf-dist/scripts/texdirflatten
parent6320e3d204852732e5510f2b0cdd5022fc541091 (diff)
texdirflatten (27jun17)
git-svn-id: svn://tug.org/texlive/trunk@44713 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/texdirflatten')
-rwxr-xr-xMaster/texmf-dist/scripts/texdirflatten/texdirflatten226
1 files changed, 156 insertions, 70 deletions
diff --git a/Master/texmf-dist/scripts/texdirflatten/texdirflatten b/Master/texmf-dist/scripts/texdirflatten/texdirflatten
index c43b489f18e..f67adc77dc6 100755
--- a/Master/texmf-dist/scripts/texdirflatten/texdirflatten
+++ b/Master/texmf-dist/scripts/texdirflatten/texdirflatten
@@ -1,4 +1,9 @@
-#! /usr/bin/perl
+#! /usr/bin/env perl
+
+# Use:
+# $ perldoc texdirflatten
+# to see embedded documentation. Alternatively, you can create manual
+# or HTML pages using pod2man and pod2html.
=pod
@@ -9,7 +14,7 @@ single output directory -- i.e., flattens its hierarchy.
=head1 SYNOPSIS
-texdirflatten -f input.tex [-o outputdir]
+texdirflatten [-1|--onetex] [-f|--file input.tex] [-o outputdir] [-?|--help]
=head1 DESCRIPTION
@@ -24,16 +29,25 @@ Run without parameters to see usage.
=over
-=item B<-f> I<input.tex>
+=item B<--file>, B<-f> I<input.tex>
Specifies input (La)TeX file.
-=item B<-o> I<outputdir>
+=item B<--onetex>, B<-1>
+
+If specified, produces a single TeX file by expanding all \input and
+\include commands in place.
+
+=item B<--output>, B<-o> I<outputdir>
Directory to collect all files. B<texdirflatten> will copy each source
file, graphics and bibliography file to this directory. It will be
created if it is unexistent. If unspecified, it defaults to C<flat/>.
+=item B<--help>, B<-?>
+
+Show this manual page.
+
=back
=head1 EXAMPLES
@@ -48,6 +62,10 @@ and gathers it and all its components in the C<submit_01/> directory:
Please take backups before running this command. No warranties
whatsoever provided.
+You may need to run C<epstopdf> on EPS files if you are using C<pdflatex>:
+
+ $ for i in *.eps; do epstopdf $i; done
+
=head1 BUGS
Bug reports and patches are welcome.
@@ -58,15 +76,13 @@ Cengiz Gunay <cengique<AT>users.sf.net>
=head1 COPYRIGHT AND LICENSE
-Copyleft 2003-2009, Cengiz Gunay
+Copyleft 2003-2017, Cengiz Gunay
This library is free software; you may redistribute it and/or modify
it under the same terms as Perl itself.
=cut
-# $Id: texdirflatten,v 1.1 2009/04/17 14:15:39 cengiz Exp $
-
# TODO:
#
# - parse BIBINPUTS environment variable and search figures and such
@@ -77,10 +93,13 @@ package texdirflatten;
use Getopt::Long qw(GetOptions);
use Pod::Usage;
use strict;
+use warnings;
+use re 'eval';
# Global
-my $outputdir = "flat";
-my $file;
+my $outputdir = "flat"; # Output directory
+my $file = ""; # File to read
+my $onetex = 0; # Indicates all input and include commands be expanded
my $help;
# parse helpers
@@ -88,35 +107,41 @@ my %texfiles;
# GetOpt::Long::
my $result = GetOptions ("output|o=s" => \$outputdir,
- "file|f=s" => \$file,
- "help|?" => \$help );
+ "onetex|1" => \$onetex,
+ "file|f=s" => \$file,
+ "help|?" => \$help );
+# regexp for none or an even number of backslashes (\):
+my $unescaped =
+ '(?<! \\\\)(?(?= \\\\) (?: \\\\\\\\)* )?';
-#print "help: $help, file: $file\n";
+# counter for files translated (like LyX does)
+$::filecount = 0;
+my $DEBUG = 1;
-#print "poop: " . popfile('slkjs/lkjlsjd/saa.abc');
-#{
-# print ;
-#}
+pod2usage( -verbose => 2 ) if ($help);
-pod2usage( -section => "SYNOPSIS") if ($file eq "" || $help);
+pod2usage( -section => "SYNOPSIS") if ($file eq "");
system "mkdir $outputdir" if (not -d $outputdir);
# start recursing
-parseTeX($file, "");
+parseTeX($file, "", popfile($file), 0);
sub parseTeX {
my $file = shift;
my $inputdir = shift;
+ my $outfile = "$outputdir/" . shift;
+ my $level = shift;
+
+ # Add a proper TeX suffix if it's missing
+ $outfile .= '.tex' if ! ($outfile =~ /\.tex\s*$/i );
my @flats;
my @longs;
my $popped;
open my $FILE, $file or die "Cannot find file to read $file\n";
- my $outfile = "$outputdir/" . popfile($file);
- open my $COPY, ">$outfile" or die "Cannot write file $outfile\n";
# Read to whole file first, and then scan for regexps
my $contents = "";
@@ -125,71 +150,70 @@ sub parseTeX {
}
close $FILE;
+ ## First, remove comments so that input commands inside are ignored.
+ # Also remove trailing newline and all whitespace at the beginning
+ # of the following line like TeX does it. Only for %'s following
+ # the proper backslash pattern.
+ $contents =~ s/( $unescaped )\%.*?\n[ \t]*/$1/gx;
+
# Look for graphics include statement
- if ($contents =~ /\\input\@path{{([^}]*)}}/) {
+ if ($contents =~ /\\input\@path\{\{([^}]*)\}\}/) {
$inputdir = $1;
print "Found input directory: $inputdir\n";
}
+ print "Parsing '$file' in directory '$inputdir'\n";
+
# Default value
#$inputdir = './' if (-z $inputdir);
# three cases: graphics, inputs and bibs
# an \includegraphics statement
- @flats = ();
- @longs = ();
+ @::flats = ();
+ @::longs = ();
+ #$::popped = "";
- $contents =~
- s/\\includegraphics(\[[^\]]*\])?\{([^}]*)\}/"\\includegraphics" . $1 .
- "{" . ($popped = popfile($2) and push @longs, $2 and push @flats,$popped and $popped) . "}"/egm;
+ $contents =~
+ s/\\includegraphics(\[[^\]]*\])?\{([^}]*)\}
+ (?{ $::popped = flattenfilename($2);
+ push @::longs, $2; push @::flats, $::popped })
+ /\\includegraphics$1\{$::popped\}/gmx;
- if ($#flats > -1) {
+ if ($#::flats > -1) {
my ($long, $flat);
- foreach $long (@longs) {
- $flat = shift @flats;
- print "Found graphics: '$long'\n";
+ foreach $long (@::longs) {
+ $flat = shift @::flats;
# convert LyX directory dots
$long =~ s/\\lyxdot /./g;
+ $flat =~ s/\\lyxdot /./g;
- my $epsfile = $inputdir . $long;
+ print "Looking for graphics: '$long'\n";
- if (system("cp $epsfile.eps $outputdir/$flat.eps") != 0) {
- print "Cannot find $epsfile.eps!\n";
- # if from figures dir, copy the EPS file as well
- if ($long =~ /figures\//) {
- $epsfile = $inputdir . $long;
- } else {
- $epsfile = $inputdir . '../figures/' . $long;
- }
+ my @exts = ("", ".eps", ".pdf", ".pstex");
+ my @dirs = ("", "$inputdir", $inputdir . '../figures/');
- if (system("cp $epsfile.eps $outputdir/$flat.eps") != 0) {
- print "Cannot find $epsfile.eps!\n";
- if (system("cp $epsfile.pstex $outputdir/$flat.eps") != 0) {
- die "Cannot find figure file '$epsfile'";
- } else {
- print "Found: '$epsfile.pstex'\n";
- }
- }
- } else {
- print "Found: '$epsfile.pstex'\n";
- }
+ seekfile($long, $flat, ["", ".eps", ".pdf", ".pstex"],
+ ["", "$inputdir", $inputdir . '../figures/']);
}
- my $long = $2;
-
}
+ # Must do bibs before input commands because, when expanded, they
+ # add new bibs inside.
+ replacebibs(\$contents, $inputdir);
+
# an \input or \include statement
@flats = ();
@longs = ();
- $contents =~
- s/\\(input|include){([^}]*)}/"\\${1}{" .
- ($popped = popfile($2) and push @longs, $2 and push @flats,$popped and $popped) . "}"/egm;
+ $contents =~
+ s/\\(input|include)\{([^}]*)\}/"\\${1}\{" .
+ ($popped = flattenfilename($2) and push @longs, $2 and push @flats,$popped and $popped)
+ . "\}"/egm;
- if ($#flats > 0) {
+ if ($#flats > -1) {
#print "Found " . scalar @longs . " items on line: '@flats'.\n";
my ($long, $flat);
@@ -208,24 +232,60 @@ sub parseTeX {
}
}
$texfiles{$flat} = $long;
- parseTeX($long, $inputdir); #later
-
+ my $newcontents = parseTeX($long, basedir($long), $flat, $level + 1); #later
+ if ( $onetex ) {
+ # If specified, expand inclusion directives
+ die "Failed to find input/include to expand for '$flat'!\n"
+ if (! ( $contents =~
+ s/\\(input|include) \{ \Q$flat\E \}
+ (?{ print "===Found \\$1\{$flat\} to expand.\n" if $DEBUG; })
+ / ($1 eq 'include' ? "\\clearpage\n" : '') . "$newcontents"/gxem ) );
+ }
}
}
}
- replacebibs(\$contents, $inputdir);
#print "Writing to \"$outfile\"\n" .
# "----------------------------------------\n" .
# "$contents\n" .
# "----------------------------------------\n";
- # write to flat copy
- print $COPY $contents;
+ if (! $onetex || $level == 0) { # do output at zero recurse level
+ # open flat output file
+ open my $COPY, ">$outfile" or die "Cannot write file $outfile\n";
+ # write to flat copy
+ print $COPY $contents;
- close $COPY;
+ close $COPY;
+ } else {
+ return $contents;
+ }
+}
+# Look for file to copy
+sub seekfile {
+ my ($file, $dest, $exts, $dirs) = @_;
+ my @exts = @$exts;
+ my @dirs = @$dirs;
+
+ OUT: foreach my $dir (@dirs) {
+ foreach my $ext (@exts) {
+ my $tryfile = "$dir$file$ext";
+ if (-r $tryfile) {
+ # add the extension to $dest only if it hasn't any dots
+ my $dext = '';
+ $dext = $ext if (! $dest =~ /\./);
+
+ if (system("cp $tryfile $outputdir/$dest$dext") != 0) {
+ die "Cannot copy $tryfile!\n";
+ }
+ # If we found it, then get out of the loop
+ print "Found: '$tryfile'\n";
+ last OUT;
+ }
+ }
+ }
}
# Return everything after the last /
@@ -238,6 +298,35 @@ sub popfile {
pop @a;
}
+# Make a new file by flattening directory names
+sub flattenfilename {
+ local $_ = shift;
+
+ # convert slashes to pluses, dots to Xs
+ tr|/|+|;
+ tr|\.|X|;
+
+ # add a unique number at the beginning so files don't start with a
+ # dot
+ $_ = sprintf("%03d_", ++$::filecount) . "$_";
+
+ print "===Flattened file to '$_'\n" if $DEBUG;
+
+ return $_;
+}
+
+sub basedir {
+ my $file = shift (@_);
+
+ my @a = split /\//, $file;
+
+ #print "Popping $file... split: @a ($#a), pop: " . pop(@a) . "\n";
+ pop @a; # remove file part
+ my $basedir = join('/', @a); # combine the rest with /'s
+ $basedir .= '/' if (! $basedir =~ /^$/); # add a trailing / if not empty
+ $basedir;
+}
+
# get the bibliography files
sub replacebibs {
my ($contentsref, $inputdir) = @_;
@@ -253,13 +342,13 @@ sub replacebibs {
$" = ','; # set list item separator
# search for \bibliography statements
$$contentsref =~
- s/\\bibliography(\[[^\]]*\])? {
+ s/\\bibliography(\[[^\]]*\])? {
(?{ @::refs = (); #print "Found bibliography!\n"; #initialize ref list
}) (?: \s* ([^}, ]+)(?=[,}]),?
(?{ # for each word do:
#local (@_flats, @_longs, @_refs);
#print "Word: \"$+\", ";
- $popped = popfile($+); push @::longs, $+;
+ $popped = flattenfilename($+); push @::longs, $+;
push @::flats,$popped; push @::refs, $popped;
}) )+ \s* }
(?{ #print "\n+++ $#::flats; $#::refs; $#::longs\n";
@@ -270,7 +359,7 @@ sub replacebibs {
#print "\n*** $#::flats; $#::refs; $#::longs\n";
$" = ' '; # restore list item separator
- if ($#::flats > 0) {
+ if ($#::flats > -1) {
#print "Found " . scalar @::longs . " items on line: '@::flats'.\n";
my ($long, $flat);
@@ -283,11 +372,8 @@ sub replacebibs {
# convert LyX directory dots
$long =~ s/\\lyxdot /./g;
- my $bibfile = $inputdir . $long;
-
- if (system("cp $bibfile.bib $outputdir/$flat.bib") != 0) {
- die "Cannot find $bibfile.bib!\n";
- }
+ seekfile($long, "$flat.bib", [".bib"],
+ ["", "$inputdir"]);
}
}
}