]> git.lyx.org Git - lyx.git/blob - lib/reLyX/MakePreamble.pm
John's --with-version-suffix
[lyx.git] / lib / reLyX / MakePreamble.pm
1 # This file is part of reLyX. 
2 # Copyright (c) 1998-9 Amir Karger karger@post.harvard.edu
3 # You are free to use and modify this code under the terms of
4 # the GNU General Public Licence version 2 or later.
5
6 package MakePreamble;
7 # This package reads a LaTeX preamble (everything before \begin{document}
8 #    and translates it to LaTeX.
9
10 use strict;
11
12 my $debug_on; # package-wide variable set if -d option is given
13 my $true_class; # which textclass to use (if -c option is given)
14
15 sub split_preamble {
16 # Split the file into two files, one with just the preamble
17 # Simply copy stuff verbatim, saving translation for later
18 # Skip the LyX-generated portion of the preamble, if any. (Otherwise,
19 #     when you try to "view dvi" in LyX, there will be two copies of the
20 #     preamble matter, which will break LyX.
21     my ($InFileName, $PreambleName, $OutFileName) = (shift, shift, shift);
22     my ($a, $b, $c);
23     my $forget=0;
24
25     # Was -d option given?
26     $debug_on = (defined($main::opt_d) && $main::opt_d);
27     # -c option?
28     $true_class = defined($main::opt_c) ? $main::opt_c : "";
29     my $zzz = $debug_on 
30         ? " from LaTeX file $InFileName into $PreambleName and $OutFileName" 
31         : "";
32     warn "Splitting Preamble$zzz\n";
33
34     open (INFILE, "<$InFileName") or die "problem opening $InFileName: $!\n";
35     open (PREAMBLE, ">$PreambleName") or
36                 die "problem opening $PreambleName: $!\n";
37     open (OUTFILE, ">$OutFileName") or die "problem opening $OutFileName: $!\n";
38
39     # Copy everything up to "\begin{document}" into the preamble
40     while (<INFILE>) {
41         if (s/\Q\begin{document}\E//) {
42             ($a, $b, $c) = ($`, $&, $'); # save for later
43             last;
44         }
45         # In real life, there should never be Textclass specific stuff unless
46         # there is also LyX specific. But it can't hurt to test for both.
47         $forget=1 if m/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific/ ||
48                      m/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Textclass specific/;
49         print PREAMBLE $_ unless $forget;
50         $forget=0 if m/%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified/;
51     }
52     die "Didn't find \\begin{document} command!" unless defined $b;
53     # There *could* be a preamble command on the same line as \begin{doc}!
54     print PREAMBLE $a;
55     print "Put preamble into file $PreambleName\n" if $debug_on;
56
57     # Copy everything else into another file
58     # Ignore anything after '\end{document}
59     print OUTFILE $b, $c; #'\begin{document}' plus anything else on the line
60     while (<INFILE>) {
61         print OUTFILE $_;
62         last if $_ =~ /^[^%]*\Q\end{document}\E/;
63     }
64
65     print "Put rest of file into $OutFileName\n" if $debug_on;
66     close INFILE; close OUTFILE; close PREAMBLE;
67     #warn "Done splitting preamble\n";
68 } #end sub split_preamble
69
70
71
72 # Actually translate a LaTeX preamble (in a file) into a LyX preamble.
73 # Input:
74 # First argument is the name of the file containing *only* the preamble
75 # Second argument is the LyX format (e.g., "2.15")
76 #
77 # Output: document class, LyX Preamble, LaTeX preamble
78 #    LyX premable contains the LyX options etc.
79 #    LaTeX preamble is stuff that doesn't translate into LyX options)
80 #
81 sub translate_preamble {
82     my $PreambleName = shift;
83     my $Format = shift;
84     $debug_on = (defined($main::opt_d) && $main::opt_d);
85     my $zzz=$debug_on ? " from $PreambleName" :"";
86     warn "Creating LyX preamble$zzz\n";
87     open (PREAMBLE, "<$PreambleName");
88
89     # Translate optional args to \documentclass to LyX preamble statements
90     my %Option_Trans_Table = (
91         "10pt"           => "\\paperfontsize 10",
92         "11pt"           => "\\paperfontsize 11",
93         "12pt"           => "\\paperfontsize 12",
94
95         "letterpaper"    => "\\papersize letterpaper",
96         "legalpaper"     => "\\papersize legalpaper",
97         "executivepaper" => "\\papersize executivepaper",
98         "a4paper"        => "\\papersize a4paper",
99         "a5paper"        => "\\papersize a5paper",
100         "b5paper"        => "\\papersize b5paper",
101
102         "twoside"        => "\\papersides 2",
103         "oneside"        => "\\papersides 1",
104
105         "landscape"      => "\\paperorientation landscape",
106
107         "onecolumn"      => "\\papercolumns 1",
108         "twocolumn"      => "\\papercolumns 2",
109     );
110
111     # This is the string in which we're concatenating everything we translate
112     my $LyX_Preamble = "";
113
114 # It would be nice to read the defaults.lyx file but for now we don't bother
115 #my $default_dir = "templates/";
116 #my $default_name = "defaults.lyx";
117 #my $default_file = $dot_lyxdir . $default_dir . $default_name;
118 #if (-e $default_file) {
119 #    print "Going to open default LyX file $default_file\n";
120 #    open (DEFAULT_LYX,$default_file) or warn "can't find default lyx file!";
121 #       if ($fmt =~ /^\s*\\lyxformat [0-9.]+/) {
122 #           print $fmt
123 #       } else {
124 #           die "Need \\lyxformat command in first line of default lyx file!";
125 #       }
126 #       AFTER printing the preamble, we'd print other commands from defaults.lyx
127 #       while (($line = <DEFAULT_LYX>) !~ /^.*\\layout/) {
128 #           if ($line !~ /^\s*(\#|\\textclass\W)/) { #already printed this line
129 #               print OUTFILE $line;
130 #           }
131 #       }
132 #}
133
134     # Write first two lines of the lyx file
135     my ($nm, $dt);
136     # whoami is needed on Win32, because getlong/getpwuid aren't implemented
137     # I'd rather use internal Perl functions when possible, though
138     $nm = (eval {getlogin || getpwuid($<)}) || `whoami`;
139     chomp($nm); # whomai returns "foo\n"
140     $dt = localtime;
141     $LyX_Preamble .= "\#This file was created by <$nm> $dt\n";
142     $LyX_Preamble .= "\#LyX 1.0 (C) 1995-1999 Matthias Ettrich " .
143                     "and the LyX Team\n";
144
145     # Print \lyxformat.
146     $LyX_Preamble .= "\\lyxformat $Format\n";
147
148     # Ignore everything up to the \documentclass
149     my $ignore = "";
150     while (<PREAMBLE>) {
151         next if /^\s*$/ || /^\s*%/; # skip whitespace or comment
152         # could just allow 'documentclass' and not support 2.09
153         last if s/^\s*\\document(style|class)//;
154         $ignore .= $_; # concatenate the ignored text
155     } # end while
156     warn "Uncommented text before \\documentclass command ignored!\n"if $ignore;
157     print "Ignored text was\n------\n$ignore------\n" if $debug_on && $ignore;
158
159     # concatenate all the extra options until the required argument to 
160     # \documentclass, which will be in braces
161     until (eof(PREAMBLE) || /\{/) {
162         my $instr = <PREAMBLE>;
163         $instr =~ s/\s*%.*$//; # get rid of comments
164         chomp; # remove the \n on $_ prior to concatenating
165         $_ .= $instr;
166     } # end loop; check the now longer $_ for a brace
167
168     # Read optional arguments, which are now guaranteed to be on one line
169     # (They're read here, but printed AFTER the \\textclass command)
170     #    Note: the below pattern match is *always* successful, so $& is always
171     # set, but it will be '' if there are no optional arguments. $1 will be
172     # whatever was inside the brackets (i.e., not including the [])
173     my $extra_options;
174     if (defined($_)) {
175         s/^\s*//; # there might be space before args
176         s/$Text::TeX::optionalArgument//;
177         $extra_options = $1 if $&;
178     }
179
180     # Read the document class, in braces, then convert it to a textclass
181     # However, if the user input a different class with the -c option, use that
182     s/\s*\{(\S+)\s*\}//;
183     my $class = $1;
184     $class = $true_class if $true_class; # override from -c option
185     die "no document class in file, no -c option given\n" unless $class;
186     $LyX_Preamble .= "\\textclass $class\n";
187     print "document class is $class\n" if $debug_on;
188
189     # Analyze the extra options, and remove those we know about
190     if ($extra_options) {
191         my $op;
192         foreach $op (keys %Option_Trans_Table) {
193             $extra_options =~ s/\b$op\b// && do {
194                 $LyX_Preamble .= "$Option_Trans_Table{$op}\n";
195                 print "Document option $op\n" if $debug_on;
196             }
197         }
198         $extra_options =~ s/^,+|,+(?=,)|,+$//g; # extra commas
199     }
200     # Convert any remaining options to an \options command
201     if ($extra_options) {
202         $LyX_Preamble .= "\\options $extra_options\n";
203         print "extra options: $extra_options\n" if $debug_on;
204     }
205
206     # Now copy the whole preamble into the preamble of the LyX document
207     #     (unless there is no preamble)
208     # Everything until the end of filehandle PREAMBLE is preamble matter
209     my $Latex_Preamble = $_; # there COULD be a preamble command on same line
210     my $write_preamble = (! /^\s*$/ && ! /^\s*%/);
211     while (<PREAMBLE>) {
212         $Latex_Preamble .= $_;
213         # write an official preamble if we find anything that's not comment
214         $write_preamble ||= (! /^\s*$/ && ! /^\s*%/);
215     }
216
217     if ($write_preamble) {
218         $Latex_Preamble =~ s/^\s*//;
219         print "LaTeX preamble, consists of:\n$Latex_Preamble" if $debug_on;
220         $Latex_Preamble = "\\begin_preamble\n$Latex_Preamble\\end_preamble\n";
221         print "End of LaTeX preamble\n" if $debug_on;
222     } else {
223         $Latex_Preamble = ""; #just comments, whitespace. Ignore them
224     }
225
226     #warn "Done creating LyX Preamble\n";
227     return ($class, $LyX_Preamble, $Latex_Preamble);
228 }
229
230 1; # return true value to calling program