texlive[44713] trunk: texdirflatten (27jun17)

commits+karl at tug.org commits+karl at tug.org
Tue Jun 27 23:56:44 CEST 2017


Revision: 44713
          http://tug.org/svn/texlive?view=revision&revision=44713
Author:   karl
Date:     2017-06-27 23:56:44 +0200 (Tue, 27 Jun 2017)
Log Message:
-----------
texdirflatten (27jun17)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/texdirflatten/texdirflatten
    trunk/Master/texmf-dist/doc/man/man1/texdirflatten.1
    trunk/Master/texmf-dist/doc/man/man1/texdirflatten.man1.pdf
    trunk/Master/texmf-dist/scripts/texdirflatten/texdirflatten
    trunk/Master/tlpkg/tlpsrc/texdirflatten.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/support/texdirflatten/
    trunk/Master/texmf-dist/doc/support/texdirflatten/README

Modified: trunk/Build/source/texk/texlive/linked_scripts/texdirflatten/texdirflatten
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/texdirflatten/texdirflatten	2017-06-27 21:56:10 UTC (rev 44712)
+++ trunk/Build/source/texk/texlive/linked_scripts/texdirflatten/texdirflatten	2017-06-27 21:56:44 UTC (rev 44713)
@@ -1,5 +1,10 @@
-#! /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
 
 =head1 NAME
@@ -9,7 +14,7 @@
 
 =head1 SYNOPSIS
 
-texdirflatten -f input.tex [-o outputdir]
+texdirflatten [-1|--onetex] [-f|--file input.tex] [-o outputdir] [-?|--help]
 
 =head1 DESCRIPTION
 
@@ -24,16 +29,25 @@
 
 =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 @@
 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,7 +76,7 @@
 
 =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.
@@ -65,8 +83,6 @@
 
 =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 @@
 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 @@
 
 # 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,12 +150,20 @@
   }
   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);
 
@@ -137,59 +170,50 @@
   # 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 @@
 	  }
 	}
 	$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 @@
   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 @@
   $" = ',';			# 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 @@
       #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 @@
       # 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"]);
     }
   }
 }

Modified: trunk/Master/texmf-dist/doc/man/man1/texdirflatten.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/texdirflatten.1	2017-06-27 21:56:10 UTC (rev 44712)
+++ trunk/Master/texmf-dist/doc/man/man1/texdirflatten.1	2017-06-27 21:56:44 UTC (rev 44713)
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pod::Man 2.1801 (Pod::Simple 3.05)
+.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.29)
 .\"
 .\" Standard preamble:
 .\" ========================================================================
@@ -38,6 +38,8 @@
 .    ds PI \(*p
 .    ds L" ``
 .    ds R" ''
+.    ds C`
+.    ds C'
 'br\}
 .\"
 .\" Escape single quotes in literal strings from groff's Unicode transform.
@@ -48,17 +50,24 @@
 .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
 .\" entries marked with X<> in POD.  Of course, you'll have to process the
 .\" output yourself in some meaningful fashion.
-.ie \nF \{\
-.    de IX
-.    tm Index:\\$1\t\\n%\t"\\$2"
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
 ..
-.    nr % 0
-.    rr F
-.\}
-.el \{\
-.    de IX
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{
+.    if \nF \{
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
 ..
+.        if !\nF==2 \{
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
 .\}
+.rr rF
 .\"
 .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
 .\" Fear.  Run.  Save yourself.  No user-serviceable parts.
@@ -124,17 +133,17 @@
 .\" ========================================================================
 .\"
 .IX Title "TEXDIRFLATTEN 1"
-.TH TEXDIRFLATTEN 1 "2009-04-17" "perl v5.10.0" "User Contributed Perl Documentation"
+.TH TEXDIRFLATTEN 1 "2017-06-26" "perl v5.22.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
 .nh
 .SH "NAME"
-\&\fBtexdirflatten\fR \- Collects all components of a (La)TeX file in a
-single output directory \*(-- i.e., flattens its hierarchy.
+texdirflatten \- Collects all components of a (La)TeX file in a
+single output directory \-\- i.e., flattens its hierarchy.
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
-texdirflatten \-f input.tex [\-o outputdir]
+texdirflatten [\-1|\-\-onetex] [\-f|\-\-file input.tex] [\-o outputdir] [\-?|\-\-help]
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
 It parses the source file, following its included children (La)TeX
@@ -142,14 +151,21 @@
 graphics and BiBTeX bibliography files in different directories.
 .SH "OPTIONS"
 .IX Header "OPTIONS"
-.IP "\fB\-f\fR \fIinput.tex\fR" 4
-.IX Item "-f input.tex"
+.IP "\fB\-\-file\fR, \fB\-f\fR \fIinput.tex\fR" 4
+.IX Item "--file, -f input.tex"
 Specifies input (La)TeX file.
-.IP "\fB\-o\fR \fIoutputdir\fR" 4
-.IX Item "-o outputdir"
+.IP "\fB\-\-onetex\fR, \fB\-1\fR" 4
+.IX Item "--onetex, -1"
+If specified, produces a single TeX file by expanding all \einput and
+\&\einclude commands in place.
+.IP "\fB\-\-output\fR, \fB\-o\fR \fIoutputdir\fR" 4
+.IX Item "--output, -o outputdir"
 Directory to collect all files. \fBtexdirflatten\fR 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 \f(CW\*(C`flat/\*(C'\fR.
+.IP "\fB\-\-help\fR, \fB\-?\fR" 4
+.IX Item "--help, -?"
+Show this manual page.
 .SH "EXAMPLES"
 .IX Header "EXAMPLES"
 The following example scans \f(CW\*(C`manuscript.tex\*(C'\fR in the current directory
@@ -162,6 +178,12 @@
 .IX Header "CAVEATS"
 Please take backups before running this command. No warranties
 whatsoever provided.
+.PP
+You may need to run \f(CW\*(C`epstopdf\*(C'\fR on \s-1EPS\s0 files if you are using \f(CW\*(C`pdflatex\*(C'\fR:
+.PP
+.Vb 1
+\& $ for i in *.eps; do epstopdf $i; done
+.Ve
 .SH "BUGS"
 .IX Header "BUGS"
 Bug reports and patches are welcome.
@@ -170,7 +192,7 @@
 Cengiz Gunay <cengique<\s-1AT\s0>users.sf.net>
 .SH "COPYRIGHT AND LICENSE"
 .IX Header "COPYRIGHT AND LICENSE"
-Copyleft 2003\-2009, Cengiz Gunay
+Copyleft 2003\-2017, Cengiz Gunay
 .PP
 This library is free software; you may redistribute it and/or modify
 it under the same terms as Perl itself.

Modified: trunk/Master/texmf-dist/doc/man/man1/texdirflatten.man1.pdf
===================================================================
(Binary files differ)

Added: trunk/Master/texmf-dist/doc/support/texdirflatten/README
===================================================================
--- trunk/Master/texmf-dist/doc/support/texdirflatten/README	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/support/texdirflatten/README	2017-06-27 21:56:44 UTC (rev 44713)
@@ -0,0 +1,55 @@
+NAME
+    texdirflatten - Collects all components of a (La)TeX file in a single
+    output directory -- i.e., flattens its hierarchy.
+
+SYNOPSIS
+    texdirflatten [-1|--onetex] [-f|--file input.tex] [-o outputdir]
+    [-?|--help]
+
+DESCRIPTION
+    It parses the source file, following its included children (La)TeX files
+    recursively, to collect together its components, such as graphics and
+    BiBTeX bibliography files in different directories.
+
+OPTIONS
+    --file, -f *input.tex*
+        Specifies input (La)TeX file.
+
+    --onetex, -1
+        If specified, produces a single TeX file by expanding all \input and
+        \include commands in place.
+
+    --output, -o *outputdir*
+        Directory to collect all files. 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 "flat/".
+
+    --help, -?
+        Show this manual page.
+
+EXAMPLES
+    The following example scans "manuscript.tex" in the current directory
+    and gathers it and all its components in the "submit_01/" directory:
+
+     $ texdirflatten -f manuscript.tex -o submit_01
+
+CAVEATS
+    Please take backups before running this command. No warranties
+    whatsoever provided.
+
+    You may need to run "epstopdf" on EPS files if you are using "pdflatex":
+
+     $ for i in *.eps; do epstopdf $i; done
+
+BUGS
+    Bug reports and patches are welcome.
+
+AUTHOR
+    Cengiz Gunay <cengique<AT>users.sf.net>
+
+COPYRIGHT AND LICENSE
+    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.
+


Property changes on: trunk/Master/texmf-dist/doc/support/texdirflatten/README
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/scripts/texdirflatten/texdirflatten
===================================================================
--- trunk/Master/texmf-dist/scripts/texdirflatten/texdirflatten	2017-06-27 21:56:10 UTC (rev 44712)
+++ trunk/Master/texmf-dist/scripts/texdirflatten/texdirflatten	2017-06-27 21:56:44 UTC (rev 44713)
@@ -1,5 +1,10 @@
-#! /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
 
 =head1 NAME
@@ -9,7 +14,7 @@
 
 =head1 SYNOPSIS
 
-texdirflatten -f input.tex [-o outputdir]
+texdirflatten [-1|--onetex] [-f|--file input.tex] [-o outputdir] [-?|--help]
 
 =head1 DESCRIPTION
 
@@ -24,16 +29,25 @@
 
 =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 @@
 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,7 +76,7 @@
 
 =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.
@@ -65,8 +83,6 @@
 
 =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 @@
 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 @@
 
 # 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,12 +150,20 @@
   }
   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);
 
@@ -137,59 +170,50 @@
   # 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 @@
 	  }
 	}
 	$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 @@
   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 @@
   $" = ',';			# 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 @@
       #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 @@
       # 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"]);
     }
   }
 }

Modified: trunk/Master/tlpkg/tlpsrc/texdirflatten.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/texdirflatten.tlpsrc	2017-06-27 21:56:10 UTC (rev 44712)
+++ trunk/Master/tlpkg/tlpsrc/texdirflatten.tlpsrc	2017-06-27 21:56:44 UTC (rev 44713)
@@ -1,2 +1,2 @@
 binpattern f bin/${ARCH}/${PKGNAME}
-docpattern f texmf-dist/doc/man/man1/${PKGNAME}.*
+docpattern +f texmf-dist/doc/man/man1/${PKGNAME}.*



More information about the tex-live-commits mailing list