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.
7 # This package reads a LaTeX preamble (everything before \begin{document}
8 # and translates it to LaTeX.
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)
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);
25 # Was -d option given?
26 $debug_on = (defined($main::opt_d) && $main::opt_d);
28 $true_class = defined($main::opt_c) ? $main::opt_c : "";
30 ? " from LaTeX file $InFileName into $PreambleName and $OutFileName"
32 warn "Splitting Preamble$zzz\n";
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";
39 # Copy everything up to "\begin{document}" into the preamble
41 if (s/\Q\begin{document}\E//) {
42 ($a, $b, $c) = ($`, $&, $'); # save for later
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/;
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}!
55 print "Put preamble into file $PreambleName\n" if $debug_on;
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
62 last if $_ =~ /^[^%]*\Q\end{document}\E/;
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
72 # Actually translate a LaTeX preamble (in a file) into a LyX preamble.
74 # First argument is the name of the file containing *only* the preamble
75 # Second argument is the LyX format (e.g., "2.15")
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)
81 sub translate_preamble {
82 my $PreambleName = 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");
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",
95 "letterpaper" => "\\papersize letterpaper",
96 "legalpaper" => "\\papersize legalpaper",
97 "executivepaper" => "\\papersize executivepaper",
98 "a4paper" => "\\papersize a4paper",
99 "a5paper" => "\\papersize a5paper",
100 "b5paper" => "\\papersize b5paper",
102 "twoside" => "\\papersides 2",
103 "oneside" => "\\papersides 1",
105 "landscape" => "\\paperorientation landscape",
107 "onecolumn" => "\\papercolumns 1",
108 "twocolumn" => "\\papercolumns 2",
111 # This is the string in which we're concatenating everything we translate
112 my $LyX_Preamble = "";
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.]+/) {
124 # die "Need \\lyxformat command in first line of default lyx file!";
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;
134 # Write first two lines of the lyx file
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"
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";
146 $LyX_Preamble .= "\\lyxformat $Format\n";
148 # Ignore everything up to the \documentclass
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
156 warn "Uncommented text before \\documentclass command ignored!\n"if $ignore;
157 print "Ignored text was\n------\n$ignore------\n" if $debug_on && $ignore;
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
166 } # end loop; check the now longer $_ for a brace
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 [])
175 s/^\s*//; # there might be space before args
176 s/$Text::TeX::optionalArgument//;
177 $extra_options = $1 if $&;
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
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;
189 # Analyze the extra options, and remove those we know about
190 if ($extra_options) {
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;
198 $extra_options =~ s/^,+|,+(?=,)|,+$//g; # extra commas
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;
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*%/);
212 $Latex_Preamble .= $_;
213 # write an official preamble if we find anything that's not comment
214 $write_preamble ||= (! /^\s*$/ && ! /^\s*%/);
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;
223 $Latex_Preamble = ""; #just comments, whitespace. Ignore them
226 #warn "Done creating LyX Preamble\n";
227 return ($class, $LyX_Preamble, $Latex_Preamble);
230 1; # return true value to calling program