#!/usr/bin/perl -w ## mgplatex - Compile latex code embedded in MagicPoint code ## See doc at end of file or run 'mgplatex -h' ## Todo : %latexline-%endlatexline : ## Find a way of positionning the image correctly # Default values ##################### $verbose = 0; $force = 0; $outfile = ""; $directory = ""; $latexpreamble = "\\usepackage[latin1]{inputenc}\n"; $latexinit = ""; $skip = 0; # No arguments : show help ########### unless (@ARGV) { print "\n mgplatex : At least one argument is needed\n\n"; exec "perldoc -t $0|cat"; } while ($ARGV[0] =~ s/^-//) { # Read options ####################### map { # Loop through each letter if ($_ eq "v") { $verbose++ } elsif ($_ eq "s") { $skip = 1 } elsif ($_ eq "f") { $force = 1 } elsif ($_ eq "d") { $directory = shift @ARGV } elsif ($_ eq "o") { $outfile = shift @ARGV } elsif ($_ eq "h") { exec "perldoc -t $0|cat" } elsif ($_ eq "H") { exec "perldoc $0" } else { die "Unknown option '$_'" } } split ("", shift @ARGV); } # Preparation ######################## $infile = shift @ARGV; # Name of input unless ($outfile) { # Name of output file $outfile = $infile; $outfile =~ s/\.mgplatex$//; $outfile .= ".mgp"; } # Directory for auxiliary files $directory = "$infile.auxdir" unless $directory; # Open files open FF, "<$infile" or die "Can't read file '$infile'"; open GG, ">$outfile" or die "Can't write file '$outfile'"; unless (-d $directory) { print "Creating '$directory'\n" if $verbose; mkdir $directory or die "Can't create directory '$directory'"; } $counter = 0; # Counter for latex expressions / files # CD to directory chdir $directory or die "Can't cd to '$directory'"; while (! eof(FF)) { # Read input ######################### $_ = ; my ($keep, $latex, $latexsize) = ("","",""); # Reading LaTeX block ################ if (/^\s*(?:\\|\%\s*)(beginlatex|latexline)\s*(.*)/) { print "Found beginning latex block\n" if $verbose > 1; $latexsize = $2; my $opening = $1; my ($isline,$lineoffset,$closing) = (0,10,"endlatex"); if ($opening eq "latexline") { $isline = 1; $closing = "endlatexline"; if ($latexsize =~ s/^(\s*\d+\s+\d+\s+)(\d+)$/$1/) { $lineoffset = $2; } } $latexsize = "0 $latexsize"; my $basename = "latex-$counter"; $counter++ ; while (1) { $_ = ; last if /^\s*(?:\\|\%\s*)$closing/; # Size of latex image if (/^\%\s*latexsize\s*(.*)/) { chomp ($latexsize = $1); } else { # Correct \input{} for changed directory s|\\input{(.*)}|"\\input{". &localize($1) ."}"|eg; /^\%\s*(center|leftfill|rightfill)/ ? $keep : $latex .= $_; } if (eof(FF)) {warn "Found $opening without $closing"; last} } ## print "Keep >>$keep<<\nLatex >>$latex<<\n" if $verbose; my $epsfile = "$basename.eps"; my $mgpcode = qq(\%image "$directory/$epsfile" $latexsize\n); if ($isline) { $mgpcode = "\%cont\n$mgpcode\%cont\n"; } print GG $keep; # Print kept code in mgp file print GG $mgpcode; # Print image command in mgp file # Create latex code chomp ($latex); chomp ($latexinit); next if $skip; $alllatexcode = <; close JJ; $dont_compile = $alllatexcode eq $origcode; } if ($dont_compile) { # Compilation not needed print "Skipping unchanged file '$latexfile'\n" if $verbose > 1; next } else { # Create the latex file and compile it unlink $epsfile; open II, ">$latexfile" or die "Can't create file '$latexfile'"; print II $alllatexcode; close II; print "Compiling '$latexfile'\n" if $verbose; } # Where does output of latex and dvips go? $outpipe = ($verbose>1) ? "" : " &> /dev/null" ; # Compile latex file die "Can't run (in $directory) 'latex $latexfile' : \n" . "There is probably a problem in the code --\n" . $latex . "\n------------------------------------------\n" if system "latex -interaction=nonstopmode $latexfile $outpipe"; die "Can't run (in $directory) 'dvips -E $basename.dvi -o $epsfile'" if system "dvips -E $basename.dvi -o $epsfile $outpipe"; # Shift eps image so that it is aligned with # current line of text. # This does not work :-( # if ($isline) { # system q|perl -i.bak -pe 's{^(%%BoundingBox:\s+\d+\s+\d+\s+\d+\s+)(\d+)}{"$1" . (| . $lineoffset . q|+ $2)}e' | . $basename . ".eps" ; # } # Todo : remove temp files # End of reading LaTeX block ########## # Read LaTeX preamble or initialization } elsif (/^\s*(?:\\|\%\s*)(latexpreamble|latexinit)/) { my $what = $1; $$what = ""; while (1) { $_ = ; last if /^\s*(?:\\|\%\s*)end$what/; $$what .= $_; if (eof(FF)) { warn "$what without end$what"; last; } } print "Found $what\n" if $verbose; $$what =~ s|\\input{(.*)}|"\\input{". &localize($1) ."}"|eg; # End of reading LaTeX preamble ###### } else { # Pass mgp code through ############## print GG $_; } } # End of reading input ############### close FF; close GG; exit 0; # That's it ########################## ## Subs ############################################################## # change \input{x} to \input{../x} sub localize { my $f = shift; $f =~ s{^}{../} unless $f =~ m{^/}; $f; } ## Doc ############################################################### =head1 NAME mgplatex - Compile latex code embedded in MagicPoint code Creates a MagicPoint F from a F containing MagicPoint code with inlined LaTeX code. =head1 SYNOPSIS mgplatex [options] F Reads F, transforms LaTeX code enclosed in each B<%beginlatex-%endlatex>, B<\beginlatex-\endlatex> or B<%latexline-%endlatexline> block into equivalent mgp code and writes the result in F, which is readable by F. In the process, a directory is created (default : F), in which .tex files -one per block of latex code- are created and transformed into encapsulated postscript (.eps) images by B and B. The arguments following %beginlatex are the width and height (in screen percents) of the latex text and are passed to the mgp command %image that is used to display the LaTeX output. A %latexline block behave the same as %beginlatex block except that the latex code is displayed on the same line as the preceding and following magicpoint code. This is useful for embedding small amounts of latex code in paragraphs. If a B<%latexpreamble-%endlatexpreamble> block is present, it is inserted before C<\begin{document}>. By default, C<\usepackage[latin1]{inputenc}> is inserted. If a B<%latexinit-%endlatexinit> block is present, it is inserted between C<\begin{document}> and the code defined by each %beginlatex-%endlatex block. By default, nothing is instered. =head1 EXAMPLE The following block %beginlatex 60 30 A little bit of \LaTeX : \[ A(x) = \int_{0}^{\infty} e^-\frac{x}{2} dx \] %endlatex is transformed by mgplatex into : %image "file.auxdir/latex-0.eps" 60 35 where F is the image resulting from running B and B on the latex code. It is possible to I by specifying them in preamble. The following example uses the color and dsfont packages : %latexpreamble \usepackage[latin1]{inputenc} \usepackage{dsfont} \usepackage{color} %endlatexpreamble %beginlatex 30 5 $$ \textcolor{red}{\mathbf{X}} \in \mathds{R}^3 $$ %endlatex =head1 OPTIONS Options can be grouped together. =over 4 =item -d F Put generated files in F. By default, uses F. =item -o F Call F the resulting .mgp file. By default, the name is obtained by removing an eventual '.mgplatex' suffix of F and appending '.mgp'. =item -f Force compilation of all latex files. By default, a latex file is compiled only if it has been modified. =item -v Be verbose : say what's going on and show output of latex and dvips. More -v options produce more verbose output. =item -h Show this help and exit. =item -H Display help with a pager and exit. =back =head1 SEE ALSO B, L, B and B. Embedding latex in mgp is an old wheel that is often reinvented on mgp-user@mew.org. Luigi Rizzo made a on-the-fly preprocessor [1] and so did Stephan Buchert [3], who modified an the script B by Sylvain Pion. Anders Logg made an offline preprocessor B [2]. B should be able to read the embedded code of B. [1] http://www.mew.org/ml/mgp-users/msg00253.html [2] http://www.csl.sony.co.jp/person/nishida/mgp-users/msg00290.html [3] http://www.csl.sony.co.jp/person/nishida/mgp-users/msg00419.html =head1 COPYRIGHT Etienne Grossmann Eetienne@isr.ist.utl.ptE This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =cut