diff options
author | Karl Berry <karl@freefriends.org> | 2017-06-27 21:56:44 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-06-27 21:56:44 +0000 |
commit | 5ac5cca5eec65f2b492169f01406f6954c244142 (patch) | |
tree | e0c3b4c63216f807978b31b102a56c20063963ae /Master/texmf-dist/scripts/texdirflatten | |
parent | 6320e3d204852732e5510f2b0cdd5022fc541091 (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-x | Master/texmf-dist/scripts/texdirflatten/texdirflatten | 226 |
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"]); } } } |