]> git.lyx.org Git - lyx.git/blob - lib/reLyX/reLyXmain.pl
fix typo that put too many include paths for most people
[lyx.git] / lib / reLyX / reLyXmain.pl
1 #!/usr/bin/perl -w
2 #
3 # Main code for reLyX - the LaTeX to LyX translator
4 #
5 # reLyX is Copyright (c) 1998-9 Amir Karger karger@post.harvard.edu
6 # You are free to use and modify this code under the terms of
7 # the GNU General Public Licence version 2 or later.
8 #
9 # This code usually gets called by the reLyX wrapper executable
10 #
11 # $Id: reLyXmain.pl,v 1.4 2001/08/31 07:54:05 jamatos Exp $
12 #
13
14 require 5.002; # Perl 5.001 doesn't work. Perl 4 REALLY doesn't work.
15
16 # Standard Perl Library modules
17 use strict; # must define all variables, no barewords, no hard references
18
19 # Variables from other files, like Getopt::Std, OR vars that need to be global
20 # $opt_f etc. - command line options set by Getop::Std::getopts
21 # $dot_lyxdir - the user's personal .lyx directory
22 # $Success    - keep track of whether reLyX finished successfully or died
23 # @File_List  - the list of files to translate. Initially this is just
24 #               the file input by the user, but \input or \include commands
25 #               will add to it.
26 use vars qw($opt_c $opt_d $opt_f $opt_h $opt_n $opt_o $opt_p $opt_r $opt_s
27             $dot_lyxdir
28             $Success
29             @File_List
30             @Suffix_List
31             $LyXFormat
32            );
33 use Cwd; # getcwd etc.
34 use Getopt::Std; # read in command-line options
35 use File::Basename; # &basename and &dirname
36
37 # Modules containing subroutines for reLyX
38 # Note that @INC must include the directory that these modules are in. The
39 # reLyX wrapper takes care of that.
40 use Text::TeX; # TeX parser package
41 use ReadCommands; # package to read LaTeX commands' syntax from a file
42 use MakePreamble; # package to split off LaTeX preamble & translate it to LyX
43 use CleanTeX; # package to clean TeX file for Lyxifying
44 use BasicLyX; # package to translate clean TeX to Basic LyX
45 use LastLyX; # package to print out LyX file once all translation is done
46
47
48 # Hack to allow running reLyX without the wrapper
49 if (!defined($lyxdir)) {$lyxdir = "/usr/local/share/lyx"}
50 if (!defined($lyxname)) {$lyxname = "lyx"}
51 # there's a use vars in the wrapper, so we only need these if running w/out it
52 use vars qw($lyxdir $lyxname);
53  
54 # variables that a user might want to change
55 @Suffix_List = '\.(ltx|latex|tex)'; # allowed suffixes for LaTeX file
56 $LyXFormat = "2.15"; #What to print in \lyxformat command in .lyx file
57 my $syntaxname = "syntax.default"; # name of the default syntax file
58 $dot_lyxdir = $ENV{'HOME'} . "/.$lyxname"; # personal .lyx directory
59
60 # This variable tells us if the program died or exited happily
61 BEGIN{$Success = 0}
62
63 ##############################################################################
64 # MAIN
65 #
66
67 # Print welcome message including version info
68 my $version_info = '$Date: 2001/08/31 07:54:05 $'; # RCS puts checkin date here
69 $version_info =~ s&.*?(\d+/\d+/\d+).*&$1&; # take out just the date info
70 warn "reLyX, the LaTeX to LyX translator. Revision date $version_info\n\n";
71
72 # Usage information
73 my $Usage_Short = <<"ENDSHORTUSAGE";
74
75
76 USAGE:
77 $0 [ -c textclass ] [ -fd ] [ -o outputdir ]
78          [ -r renv1[,renv2...]] [ -s sfile1[,sfile2...]] inputfile
79
80 $0 -p -c textclass [ -fd ] [ -o outputdir ]
81          [ -r renv1[,renv2...]] [ -s sfile1[,sfile2...]] inputfile(s)
82
83 $0 -h   (to get more usage information)
84
85 ENDSHORTUSAGE
86
87 my $Usage_Long = $Usage_Short . <<"ENDLONGUSAGE";
88     -c    which textclass this file is (required with -p)
89              Overrides \\documentclass command, if one exists
90     -d    print lots of debug information & save temporary files
91     -f    force destruction of existing lyx file or temporary files
92     -h    print this message and quit
93     -n    convert a noweb file to a literate document (requires -c)
94     -o    output all LyX files to directory "outputdir"
95              Otherwise, LyX file is created in directory the LaTeX file is in
96     -p    translate LaTeX fragments or include files (requires -c)
97              I.e., files without \\documentclass commands
98     -r    give reLyX a (list of) regular environment(s)
99     -s    give reLyX a (list of) additional syntax file(s) to read
100
101 man reLyX for lots of usage information
102
103
104
105 ENDLONGUSAGE
106
107 # Read command line
108 # Get Options: set $opt_f etc. based on command line options
109 getopts('c:dfhno:pr:s:') or die "Illegal option!$Usage_Short";
110 if ($opt_h) {print $Usage_Long; $Success=1; exit}
111 die "No LaTeX file was input on the command line$Usage_Short" unless @ARGV;
112
113 # Make each file in the file list an absolute file name (e.g., staring with '/')
114 @File_List = map {&abs_file_name($_)} @ARGV;
115
116 # If noweb files, then we need to pre-process each file
117 if (defined $opt_n) {
118     die "-n option requires -c!$Usage_Short" unless defined $opt_c;
119     foreach (@File_List) {
120         system("noweb2lyx", "-pre", "$_", "$_.pre$$");
121         $_ .= ".pre$$";
122     }
123 }
124
125 # -p option allows multiple input files
126 if (defined $opt_p) {
127     die "-p option requires -c!$Usage_Short" unless defined $opt_c;
128 } else {
129     die "Only one input file allowed unless using -p option$Usage_Short"
130                     unless @ARGV == 1;
131 }
132
133 # Make sure outputdir given with -o option is valid
134 # Make it an absolute path, too!
135 if (defined($opt_o)) {
136     die "directory $opt_o doesn't exist!\n$Usage_Short"
137                                  unless defined(-d $opt_o);
138     die "$opt_o isn't a directory!\n$Usage_Short" unless -d $opt_o;
139     $opt_o = &my_fast_abs_path($opt_o);
140     # may not have trailing slash.
141     $opt_o .= '/' unless $opt_o =~ /\/$/;
142 }
143
144 # Read file(s) containing LaTeX commands and their syntax
145 # Read personal syntax.default, or system-wide if there isn't a personal one
146 # Then read other syntax files, given by the -s option
147 my $default_file = "$dot_lyxdir/reLyX/$syntaxname";
148 if (! -e $default_file) {
149     $default_file = "$lyxdir/reLyX/$syntaxname";
150     die "cannot find default syntax file $default_file" unless -e $default_file;
151 }
152 my @syntaxfiles = ($default_file);
153 push (@syntaxfiles, (split(/,/,$opt_s))) if defined $opt_s;
154 &ReadCommands::read_syntax_files(@syntaxfiles);
155
156 ########### Main loop over files (include files will be added to @File_List)
157 my $count=0; #number of files we've done
158 my @deletelist = (); # files to delete when we're done (if no '-d' flag)
159 my $Doc_Class; # LaTeX documentclass
160 my $LyX_Preamble = "";   # LyX Preamble not including Latex preamble part
161 my $Latex_Preamble = "";
162 my $File;
163 while ($File = shift(@File_List)) {
164     # TODO we should always die (or something) if temp files exist & !opt_f
165     my $OutFileName;
166     my $filenum = 0; #numbering for temporary files
167
168     # May need to add ".tex" to input file name.
169     #    PathBase is the output file name without ".lyx". It's used for building
170     # temporary files' file names, too.
171     #    Finally, make sure the file is valid, directory is writable, etc.
172     # Sub returns (undef, undef, undef) if something goes wrong.
173     my ($InFileDir, $InFileName, $PathBase) = &test_file($File);
174
175     # Change to the input file's directory, so that if the input file has an
176     # \include{../foo} in it, we'll find the included file.
177     # Did something go wrong?
178     unless (defined($InFileDir) && chdir($InFileDir)) {
179         # main file must be ok; for included files or file fragments, just warn
180         next if ($count || $opt_p);
181         die "\n"; # printed error already
182     }
183
184     # OK. Start parsing the file!
185     print STDERR "In Directory $InFileDir\n" if $opt_d;
186     print STDERR "($InFileName: ";
187
188     # Read preamble and calculate document class if necessary
189     # (It's necessary when we're doing the first file.)
190     unless ($count) {
191
192         if ($opt_p) { # it's a partial file
193             $Doc_Class = $opt_c;
194         } else {
195             # Split the preamble off of the rest of the file
196             my $PreambleName = $PathBase . ".relyx" . ++$filenum;
197             $OutFileName = $PathBase . ".relyx" . ++$filenum;
198             push @deletelist, $OutFileName, $PreambleName;
199             &MakePreamble::split_preamble($InFileName,
200                                     $PreambleName, $OutFileName);
201             $InFileName = $OutFileName;
202
203             # Now read and translate the LaTeX preamble into LyX
204             # Return document's class so we know which layout file(s) to read
205             # Also return LyX preamble in a string, for later
206             ($Doc_Class, $LyX_Preamble, $Latex_Preamble) =
207                  &MakePreamble::translate_preamble($PreambleName, $LyXFormat);
208
209         } # end partial file if
210
211         # Read file(s) containing the valid LyX layouts for this documentclass
212         # and their LaTeX command/environment equivalents
213         &ReadCommands::read_layout_files($Doc_Class);
214     }
215
216     # Clean the TeX file (not including its preamble)
217     $OutFileName = $PathBase . ".relyx" . ++$filenum;
218     push @deletelist, $OutFileName;
219     &CleanTeX::call_parser($InFileName, $OutFileName);
220
221     # Now convert basic constructs in the cleaned TeX file to LyX constructs
222     $InFileName = $OutFileName;
223     $OutFileName = $PathBase . ".relyx" . ++$filenum;
224     push @deletelist, $OutFileName;
225     &BasicLyX::call_parser($InFileName, $OutFileName);
226
227     # Final cleanup step for noweb files
228     if (defined $opt_n) {
229         $InFileName = $OutFileName;
230         $OutFileName = $PathBase . ".relyx" . ++$filenum;
231         push @deletelist, $OutFileName;
232         system("noweb2lyx", "-post", $InFileName, $OutFileName);
233     }
234
235     # Finally, print out the actual LyX file including the preamble
236     # For the *first* file, print out the LaTeX preamble too
237     $InFileName = $OutFileName;
238     if (defined $opt_n) {
239         push @deletelist, $PathBase;
240         $PathBase =~ s/.pre$$//;
241     }
242     $OutFileName = $PathBase . ".lyx";
243     my $preamble = $count ? $LyX_Preamble : $LyX_Preamble . $Latex_Preamble;
244     &LastLyX::last_lyx($InFileName, $OutFileName, $preamble);
245
246     warn ")\n";
247
248 } continue {
249     $count++;
250
251 } # END MAIN WHILE LOOP
252
253 # Cleanup
254 unless ($opt_d) {
255     warn "Deleting temp files\n";
256     unlink @deletelist;
257 }
258
259 $Success = 1;
260 exit;
261
262 # If we "die", output a sad message
263 END{
264     if ($Success) {
265         warn "Finished successfully!\n";
266     } else {
267         warn "Exited due to fatal Error!\n";
268     }
269 }
270
271 ##################### SUBROUTINES  ###########################################
272 # Input: File (including absolute path)
273 # Output: input file directory (absolute path)
274 #         input file name (".tex" added if necessary) without path
275 #         PathBase, the output file name (including path) without ".lyx" ending
276 # Returns (undef, undef, undef) if something breaks
277 #
278 # Only allow certain suffixes
279 #    Test for things, like writability of output directory, existence of
280 # .lyx file we would be creating...
281 sub test_file {
282     my $File = shift;
283     my @return_error = (undef, undef, undef);
284
285     # Get file names, set up for making different temporary files
286     # fileparse_set_fstype("MSDOS") for DOS support!
287     my ($in_basename, $in_path, $suffix) = fileparse($File, @Suffix_List);
288     #$path .= '/' unless $path =~ /\/$/; # fix BUG in perl5.002 fileparse!
289
290     # Try adding .tex to filename if you can't find the file the user input
291     unless (-e $File) {
292         if (! $suffix) { # didn't have a valid suffix. Try adding one
293             if (-e "$File.tex") {
294                 $suffix = ".tex";
295             } else {
296                 warn "\nCan't find input file $File or $File.tex\n";
297                 return @return_error;
298             }
299         } else { # it had a valid suffix, but the file doesn't exist
300             warn "\nCan't find input file $File\n";
301             return @return_error;
302         }
303     }
304     my $in_filename = $in_basename . $suffix;
305
306     # Make sure directory is valid
307     #    Note that we chdir to an input file's directory before translating it.
308     # Therefore, unless the -o option is given, we want to output files in '.'
309     #
310     # TODO if file foo.tex includes a/bar.tex and b/bar.tex, then with the
311     # -o option things will get ugly. We could test for that and create a name
312     # (like relyx-1-12345-bar.tex) for the second (and later!) bar.tex file(s)
313     my $out_path = defined $opt_o ? $opt_o : "./";
314     unless (-w $out_path) { # Note: "" isn't writable!
315         warn "\nDirectory $out_path isn't writable!\n";
316         return @return_error;
317     }
318     $out_path =~ s(^./)(); # "foo" is more readable than "./foo"
319     # This will be used for creating LyX file as well as temp files
320     my $PathBase = $out_path . $in_basename;
321
322     # Check for files that already exist
323     my $lname = $PathBase . ".lyx";
324     if (-e $lname) {
325         if ($opt_f) {
326             warn "Will overwrite file $lname\n" if $opt_d;
327         } else {
328             warn "\nLyX file $lname already exists. Use -f to overwrite\n";
329             return @return_error;
330         }
331     }
332
333     return ($in_path, $in_filename, $PathBase);
334 } # end sub test_file
335
336
337 sub abs_file_name {
338     my $File = shift;
339     my ($basename, $path, $suffix) = fileparse($File, @Suffix_List);
340     my $realpath = &my_fast_abs_path($path);
341     # add / at end
342     $realpath .= '/' unless $realpath =~ /\/$/; 
343     my $name = "$realpath$basename$suffix";
344     return $name;
345 }
346
347
348 # Stole this from Cwd.pm. Can't use the Cwd:: function cuz it's not in 5.003
349 # I could test $] >5.004 or something, but why bother?
350 sub my_fast_abs_path {
351     my $cwd = fastcwd();
352     my $path = shift || '.';
353     chdir($path) || die "Cannot chdir to $path:$!";
354     my $realpath = fastcwd();
355     chdir($cwd)  || die "Cannot chdir back to $cwd:$!";
356     $realpath;
357 }
358
359
360 1; # return "true" to the wrapper