lyxport
1049 lines
| 35.6 KiB
| text/plain
|
TextLexer
/ tools / lyxport
ville
|
r988 | #!/usr/bin/env perl | ||
# | ||||
#***************************************************************************** | ||||
# | ||||
# lyxport - script for exporting lyx docs to HTML, PostScript and PDF | ||||
# | ||||
# Inspired on the lyx2html script by Steffen Evers (tron@cs.tu-berlin.de) | ||||
# (many thanks to him). | ||||
# | ||||
# Copyright (C) 2001 Fernando Pérez (Fernando.Perez@colorado.edu) | ||||
# | ||||
#***************************************************************************** | ||||
# | ||||
# 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; either version 2 of the License, or | ||||
# (at your option) any later version. | ||||
# | ||||
# 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. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# If you do not have a copy of the GNU General Public License, write | ||||
# to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, | ||||
# MA 02139, USA. | ||||
# | ||||
# If the author of this software was too lazy to include the full GPL | ||||
# text along with the code, you can find it at: | ||||
# | ||||
# http://www.gnu.org/copyleft/gpl.html | ||||
# | ||||
#***************************************************************************** | ||||
=pod | ||||
=head1 NAME | ||||
B<lyxport> - Export a LyX or LaTeX file to HTML, PostScript and PDF. | ||||
=head1 SYNOPSIS | ||||
B<lyxport> [options] F<file> | ||||
Perl script which takes a LyX or LaTeX file as its only argument and produces | ||||
HTML, PostScript and PDF versions of the document. The name is short for "lyx | ||||
export". | ||||
You can call B<lyxport> with a filename with or without extension: F<file>, | ||||
F<file.lyx> and F<file.tex> will all work. B<lyxport> will update the LaTeX | ||||
file if there is a corresponding LyX file with a newer timestamp. | ||||
Use B<lyxport --help> for more information, and B<lyxport --man> for a full | ||||
man page. | ||||
=cut | ||||
#***************************************************************************** | ||||
# modify here the command names to suit your local conditions | ||||
my %cmd= ( | ||||
lyx => "/usr/bin/lyx", | ||||
latex => "latex", | ||||
latex2html => "latex2html", | ||||
dvips => "dvips", | ||||
pdflatex => "pdflatex", | ||||
epstopdf => "epstopdf" | ||||
); | ||||
#************ DO NOT CHANGE ANYTHING BELOW THIS ULESS YOU *REALLY* KNOW | ||||
#************ WHAT YOU ARE DOING. | ||||
#***************************************************************************** | ||||
# modules and globals | ||||
use strict; | ||||
use File::Copy; | ||||
use File::Basename; | ||||
my (%opt); # command line options | ||||
my $version = "0.3.2"; # keep this up to date with the docs (at end)! | ||||
#***************************************************************************** | ||||
# "main" (simple minded way to keep variable scoping under control) | ||||
main(); | ||||
sub main { | ||||
my ($runs, # number of latex runs | ||||
$file_in, # input filename as given at cmd line | ||||
$file_base, # base (no extension) name of file to work on | ||||
$lyx_time, # timestamps of lyx/tex files | ||||
$tex_time, | ||||
$l2h_file, # tex file cleaned up for latex2html | ||||
$targets_built, | ||||
$targets_failed, | ||||
$status, # status string for diagnostics printing | ||||
@latex_from_lyx # LaTeX files was created from LyX file | ||||
); | ||||
#------------------------------------------------------------------------ | ||||
# code begins | ||||
cmdline_process(\%opt,\$file_in); | ||||
# set defaults and filenames needed throughout | ||||
$runs=$opt{runs}; | ||||
set_cmd_defaults(\%cmd); | ||||
$file_base=check_file_exists($file_in); | ||||
# various filenames (with extensions) | ||||
my @exts=qw(lyx tex aux dvi log ps pdf out toc); | ||||
my ($lyx,$tex,$aux,$dvi,$log,$ps,$pdf,$out,$toc) = map { "$file_base.$_" } @exts; | ||||
# first, if tex file is older than lyx file, update | ||||
@latex_from_lyx=update_tex($lyx,$tex); | ||||
if ($opt{clean}) { | ||||
lyxport_info("Cleanup of old auxiliary files requested"); | ||||
safe_system("rm -rf $file_base"); | ||||
unlink ($aux,$log,$out,$toc); | ||||
} | ||||
# run latex for both html (needs .aux file) and ps (needs .dvi) | ||||
if ($opt{html} or $opt{ps}) { | ||||
run_latex("$cmd{latex} -interaction=nonstopmode",$tex,\$runs); | ||||
} | ||||
# now make targets | ||||
if ($opt{html}) { | ||||
make_html($tex,$file_base,$opt{opts_l2h},\$status, | ||||
\$targets_built,\$targets_failed); | ||||
} | ||||
if ($opt{ps}) { | ||||
make_ps($dvi,$ps,$file_base,\$status,\$targets_built,\$targets_failed); | ||||
} | ||||
if ($opt{pdf}) { | ||||
make_pdf($tex,$pdf,\$runs,$file_base, | ||||
\$status,\$targets_built,\$targets_failed); | ||||
} | ||||
#cleanup before exiting and print some diagnostics info | ||||
unless ($opt{debug}) { | ||||
unlink ($dvi,$log,$out); | ||||
} | ||||
# extra cleanup | ||||
if ($opt{tidy}) { | ||||
print "tidy up $opt{tidy},$aux,$log,$out,$toc,@latex_from_lyx\n"; | ||||
tidy_up($opt{tidy},$aux,$log,$out,$toc,@latex_from_lyx); | ||||
} | ||||
final_diagnostics($file_in,$status,$targets_built,$targets_failed); | ||||
exit(0); | ||||
} # end of main() | ||||
#***************************************************************************** | ||||
# subroutines | ||||
#----------------------------------------------------------------------------- | ||||
sub make_html { | ||||
my($tex,$html_dir,$opts_l2h,$stat_ref,$built_ref,$failed_ref)=@_; | ||||
my($success); | ||||
lyxport_info("Making HTML"); | ||||
run_latex2html($tex,$opts_l2h); | ||||
$success=check_targets("${html_dir}/${html_dir}.html",'HTML', | ||||
$built_ref,$failed_ref); | ||||
if ($success) {$$stat_ref .= "Target HTML built in directory $html_dir\n" } | ||||
} # end of make_html() | ||||
#----------------------------------------------------------------------------- | ||||
sub make_ps { | ||||
my($dvi,$ps,$html_dir,$stat_ref,$built_ref,$failed_ref)=@_; | ||||
my($success); | ||||
lyxport_info("Making PostScript"); | ||||
safe_system("$cmd{dvips} $dvi -o $ps"); | ||||
$success=check_targets($ps,'PostScript',$built_ref,$failed_ref); | ||||
if ($success and not $opt{leave}) { | ||||
move2html_dir('PostScript',$ps,$html_dir,$stat_ref,$built_ref); | ||||
} | ||||
} # end of make_ps() | ||||
#----------------------------------------------------------------------------- | ||||
sub make_pdf { | ||||
my($tex,$pdf,$runs_ref,$html_dir,$stat_ref,$built_ref,$failed_ref)=@_; | ||||
my($success); | ||||
lyxport_info("Making PDF"); | ||||
run_pdflatex($tex,$pdf,$runs_ref); | ||||
$success=check_targets($pdf,'PDF',$built_ref,$failed_ref); | ||||
if ($success and not $opt{leave}) { | ||||
move2html_dir('PDF',$pdf,$html_dir,$stat_ref,$built_ref); | ||||
} | ||||
} # end of make_pdf() | ||||
#----------------------------------------------------------------------------- | ||||
# move a given target to the html dir, only if it exists. leaves diagnostics | ||||
# info in a status string | ||||
sub move2html_dir { | ||||
my($name,$file,$dir,$stat_ref,$html_status_ref)=@_; | ||||
if ($$html_status_ref =~ /HTML/) { | ||||
safe_system("mv $file $dir"); | ||||
$$stat_ref .= "Target $name moved to directory $dir\n"; | ||||
} else { | ||||
$$stat_ref .= "Target $name left in current directory\n"; | ||||
} | ||||
} # end of move2html_dir() | ||||
#----------------------------------------------------------------------------- | ||||
# make sure that the tex file is up to date vs the lyx original before starting | ||||
# returns a list of the included .tex files which were generated (besides the main one) | ||||
sub update_tex { | ||||
my($lyx,$tex)=@_; | ||||
my($lyx_time,$tex_time); | ||||
my(@lyx_out,@made_tex,$lc); | ||||
@made_tex=(); | ||||
unless (-e $lyx) { | ||||
print "LyX file not found. Working off the LaTeX file alone.\n\n"; | ||||
return; | ||||
} | ||||
$lyx_time=(stat($lyx))[9]; | ||||
$tex_time=(stat($tex))[9]; | ||||
if ($lyx_time>$tex_time or not(-e $tex)) { | ||||
lyxport_info("LaTeX file outdated or not existent, regenerating it..."); | ||||
unlink $tex; | ||||
@lyx_out=`$cmd{lyx} -dbg latex --export latex $lyx 2>&1 `; | ||||
# try again without -dbg option: LyX has a bug here! Note that this will | ||||
# disable the ability to remove extra .tex files generated from \include | ||||
# statements. But at least it will work, until they fix the bug in LyX. | ||||
unless (-e $tex) { | ||||
@lyx_out=`$cmd{lyx} --export latex $lyx 2>&1 `; | ||||
} | ||||
# end of ugly workaround | ||||
unless (-e $tex) {die "Aborting: couldn't create LaTeX file with LyX.\n\n"}; | ||||
push (@made_tex,$tex); | ||||
# find whether lyx made auxiliary (included) .tex files and report | ||||
foreach $lc (0..$#lyx_out-1) { | ||||
$_=$lyx_out[$lc]; | ||||
if (/^incfile:.*\.lyx/) { | ||||
$lyx_out[$lc+1] =~ /^writefile:(.*)$/; | ||||
push (@made_tex,basename($1)); | ||||
} | ||||
} | ||||
if (@made_tex) { | ||||
lyxport_info("Made LaTeX included files: @made_tex"); | ||||
} | ||||
lyxport_info("Done with LaTeX generation. Moving on."); | ||||
} | ||||
return @made_tex; | ||||
} # end of update_tex() | ||||
#----------------------------------------------------------------------------- | ||||
# run latex on a file as many times as needed | ||||
# if the given # of runs is > 0, that many are done; otherwise latex is run | ||||
# as many times as needed until cross-references work. | ||||
# can be used to run either normal latex or pdflatex | ||||
sub run_latex { | ||||
my($latex_cmd,$file,$runs_ref)=@_; | ||||
# pre-determined # of runs | ||||
if ($$runs_ref > 0) { | ||||
foreach (1..$$runs_ref) { | ||||
lyxport_info("$latex_cmd run # $$runs_ref"); | ||||
safe_system("$latex_cmd $file"); | ||||
} | ||||
} | ||||
# or make as many runs as needed to get things right (not very robust...) | ||||
else { | ||||
$$runs_ref=0; | ||||
while (1) { | ||||
$$runs_ref++; | ||||
lyxport_info("$latex_cmd run # $$runs_ref"); | ||||
$_ = `$latex_cmd $file`; | ||||
print; | ||||
last unless (/Rerun to get cross-references right/m or | ||||
/^No file .*\.toc.$/m); | ||||
} | ||||
} | ||||
} # end of run_latex() | ||||
#----------------------------------------------------------------------------- | ||||
# cleanup the tex code so that latex2html doesn't get too confused | ||||
# this is essentially a Perl version (made with s2p) of Steffan Effer's | ||||
# original improvetex sed script, part of his lyx2html script collection | ||||
sub improve_tex4html { | ||||
my ($texfile,$newfile)=@_; | ||||
my ($len1,$pflag); | ||||
my $printit=1; | ||||
local *OLD,*NEW; | ||||
open(OLD,"< $texfile") || die "Can't read from file $texfile: $!\n"; | ||||
open(NEW,"> $newfile") || die "Can't write to file $newfile: $!\n"; | ||||
select(NEW) || die "Can't make $newfile default filehandle: $!\n"; | ||||
# code generated by s2p follows. Emacs can't reindent it properly! | ||||
# this code is ugly (once in Perl, original sed was ok). Clean it up... | ||||
$pflag=$\; # save print flag | ||||
$\="\n"; | ||||
LINE: | ||||
while (<OLD>) { | ||||
chomp; | ||||
# remove pagerefs over two lines (senseless in HTML) | ||||
if (/on *$\|on *page *$/) { | ||||
$_ .= "\n"; | ||||
$len1 = length; | ||||
$_ .= <OLD>; | ||||
chop if $len1 < length; | ||||
s/on *\n*page *\n*\\pageref{[^}]*}/\n/g; | ||||
} | ||||
# remove regular pagerefs (senseless in HTML) | ||||
s/on *page *\\pageref{[^}]*}//g; | ||||
# comment out redefintion of url tag (confuses latex2html) | ||||
if (/^\\IfFileExists{url.sty}/) { | ||||
s/^/%/; | ||||
print; | ||||
$_ = <OLD>; | ||||
s/^/%/; | ||||
} | ||||
# remove empty pages | ||||
if (/^\\thispagestyle{empty}~\\newpage$/) { | ||||
$printit = 0; | ||||
next LINE; | ||||
} | ||||
if (/^\\thispagestyle{empty}~$/) { | ||||
$printit = 0; | ||||
next LINE; | ||||
} | ||||
# remove custom latex commands for fancyheaders | ||||
s/\\fancyhead[^{]*{[^{}]*([^{}]*{[^{}]*})*[^{}]*}*//g; | ||||
s/\\thispagestyle{[^{}]*}//g; | ||||
# change documentclass from scrbook to book | ||||
s/^(\\documentclass[^{}]*{)scrbook}/$1book}/; | ||||
# comment out unsupported packages | ||||
s/^(\\usepackage\[T1\]{fontenc})/%$1/; | ||||
s/^(\\usepackage{a4wide})/%$1/; | ||||
s/^(\\usepackage{fancyhdr})/%$1/; | ||||
s/^(\\usepackage{ae)/%$1/; | ||||
s/^(\\pagestyle{fancy})/%$1/; | ||||
# the geometry package doesn't make sense in html | ||||
s/^(\\usepackage{geometry})/%$1/; | ||||
s/^(\\geometry)/%$1/; | ||||
# comment out ident/skip block command (produces error message; why?) | ||||
s/^(\\setlength\\parskip{.*})/%$1/; | ||||
s/^(\\setlength\\parindent{.*})/%$1/; | ||||
} continue { | ||||
if ($printit) { print } | ||||
else { $printit++ } | ||||
} | ||||
close(OLD); | ||||
close(NEW); | ||||
select(STDOUT); | ||||
$\=$pflag; # restore defaults | ||||
} # end of improve_tex4html() | ||||
#----------------------------------------------------------------------------- | ||||
sub run_latex2html { | ||||
my ($tex,$latex2html_opts)=@_; | ||||
my ($l2h_file,$symlink_exists,$htmldir); | ||||
($htmldir=$tex) =~ s/\.tex$//; | ||||
$l2h_file="${tex}_#tmp_2html#"; | ||||
improve_tex4html($tex,$l2h_file); | ||||
# add index support | ||||
my $xtraargs = ""; | ||||
my $idx = "$htmldir.idx"; | ||||
if(-e $idx ) { | ||||
$xtraargs .= "-index $idx"; | ||||
} | ||||
safe_system("$cmd{latex2html} $xtraargs $latex2html_opts $l2h_file"); | ||||
unless ($opt{debug}) { | ||||
unlink($l2h_file,"$htmldir/labels.pl"); | ||||
} | ||||
# latex2html always leaves 2 copies of the file (one as file.html, one as | ||||
# index.html). In systems that support symlinks, remove one and replace it | ||||
# with a link: | ||||
$symlink_exists = eval { symlink("",""); 1 }; | ||||
if ($symlink_exists) { | ||||
unlink("$htmldir/index.html"); | ||||
symlink("$htmldir.html","$htmldir/index.html"); | ||||
} | ||||
} # end of run_latex2html() | ||||
#----------------------------------------------------------------------------- | ||||
# remove calls to eps figures if they have an accompanying tiff, jpg or png | ||||
sub improve_tex_figs { | ||||
my ($tex,$textmp)=@_; | ||||
local (*TEX,*TMP); | ||||
# begin changes to tex file | ||||
my ($printit,$figname,$fignoneps,$figbase,$figext,$fignew,@figlist,@tmpfiles); | ||||
open(TEX,"< $tex") || die "Can't read from LaTeX file $tex: $!\n"; | ||||
open(TMP,"> $textmp") || die "Can't write to temp file $textmp: $!\n"; | ||||
$printit=1; | ||||
while (<TEX>) { | ||||
if (/includegraphics{([^\}]*)/) { | ||||
$figname=$1; | ||||
# remove .eps from fig name and make a .pdf version if necessary | ||||
if ($figname =~ /\.eps$/i) { | ||||
($figbase = $figname) =~ s/\.eps$//i; | ||||
# now we need to find if there's any non-eps figure for this file: | ||||
# pdflatex can handle jpegs, tiffs, etc. So we only need to build | ||||
# an associated pdf if there is no other figure file for pdflatex | ||||
# to work with | ||||
@figlist=grep {/\.jpe?g$|\.tiff?$|\.png$|\.pdf$/i} <$figbase.*>; | ||||
if (@figlist > 1) { | ||||
lyxport_info("Problem! More than one figure file found: @figlist"); | ||||
die "I don't know what to do here. Sorry, aborting...\n\n"; | ||||
} elsif (@figlist==1) { | ||||
# problem: pdftex only recognizes jpg (not jpeg, not JPG, etc) | ||||
# and tif (not tiff, not TIF, etc). It also gets confused by files | ||||
# called a.b.c.jpg (it thinks .b.c.jpg is the extension). argh!!! | ||||
($fignoneps)=(@figlist); | ||||
# so first, extract the 3 or 4 letter extension and lowercase it | ||||
$fignoneps =~ /.*\.(....??)$/; | ||||
($figext = $1) =~ tr/[A-Z]/[a-z]/; | ||||
# and remove any periods from the base of the name (replace by _) | ||||
$figbase =~ s/\./_/g; | ||||
$fignew="$figbase.$figext"; | ||||
if ($fignoneps =~ /\.JPE?G$|\.TIFF?$|\.PNG$|\.PDF$/) { | ||||
lyxport_info("pdflatex only recognizes the following extensions:\n". | ||||
"pdf, png, jpg, tif. (all lowercase, no variations like jpeg or tiff).\n". | ||||
"lyxport will make a copy of $fignoneps to $fignew so that pdflatex is happy"); | ||||
copy($fignoneps,$fignew); | ||||
push(@tmpfiles,$fignew); | ||||
} | ||||
s/$figname/$fignew/; # in $_, for printing to temp file | ||||
} else { | ||||
s/$figname/$figbase.pdf/; | ||||
lyxport_info("Making PDF figure <$figbase.pdf> from <$figname>"); | ||||
safe_system("$cmd{epstopdf} $figname"); | ||||
} | ||||
} | ||||
} | ||||
} continue { | ||||
if ($printit) { print TMP $_} | ||||
else { $printit++ } | ||||
} | ||||
close(TEX); | ||||
close(TMP); | ||||
return @tmpfiles; | ||||
} # end of improve_tex_figs() | ||||
#----------------------------------------------------------------------------- | ||||
# Make the pdf directly from the latex file | ||||
# Notes: for this to work ok, the following must have been done: | ||||
# 1. ~/.dvipsrc file must contain the lines | ||||
# p+ psfonts.cmz | ||||
# p+ psfonts.amz | ||||
# 2. The latex preamble of the lyx file must have | ||||
# \usepackage{ae,aecompl} | ||||
# This is so that T1 encoded fonts come out looking good in the final pdf. | ||||
sub run_pdflatex { | ||||
my ($tex,$pdf,$runs_ref)=@_; | ||||
my ($texbase,$tmpbase,$textmp,@tmpfiles,@extensions,$printit); | ||||
local *TEX,*TMP; | ||||
# first fix references to eps figures (make sure that pdf versions exist!!!) | ||||
# make all changes in a temp tex file | ||||
($texbase=$tex) =~ s/\.tex$//; | ||||
$tmpbase = "${texbase}_#tmp_pdf#"; | ||||
@extensions=qw(tex aux out toc log); | ||||
($textmp,@tmpfiles)= map { "${tmpbase}.$_" } @extensions; | ||||
push(@tmpfiles,improve_tex_figs($tex,$textmp)); | ||||
# now run the actual pdflatex converter | ||||
run_latex("$cmd{pdflatex} -interaction=nonstopmode",$textmp,$runs_ref); | ||||
rename( "${tmpbase}.pdf",$pdf); | ||||
unless ($opt{debug}) { unlink ($textmp,@tmpfiles,"texput.log"); } | ||||
} # end of run_pdflatex() | ||||
#----------------------------------------------------------------------------- | ||||
# general utility routines (not related to latex/html/pdf) follow | ||||
#------------------------------------------------------------------------- | ||||
sub cmdline_process{ | ||||
my($opt_ref,$file_ref)=@_; | ||||
# modules | ||||
no strict "vars"; # avoid some unpleasant warnings while checking options | ||||
use Getopt::Long; | ||||
# allow bundling of single letter options (-a -b == -ab) | ||||
Getopt::Long::Configure ("bundling"); | ||||
use Pod::Usage; | ||||
# note: the second name for each option (after |) is an alias for user | ||||
# convenience only. Internally, the only created hash entries use the *first* | ||||
# name as a key (i.e. $opt{h} doesn't exist, $opt{html} is set with -h or --html) | ||||
my(@option_list) = qw(html|h ps|p pdf|f leave | ||||
runs|r=i opts_l2h|o=s clean|c tidy|t+ | ||||
cld|l debug|d help man|m version|v); | ||||
# debug mode overrides all post-run cleanup options | ||||
if ($opt{debug}) { $opt{t}=0 } | ||||
# default: a negative # of runs means auto-detect | ||||
$$opt_ref{runs}= -99; | ||||
# dash options first | ||||
GetOptions($opt_ref,@option_list) || pod2usage(-verbose => 0); | ||||
# execute all possible "die" modes first | ||||
cmdline_debug(%$opt_ref) if ($$opt_ref{cld}); | ||||
pod2usage(-verbose => 1) if ($$opt_ref{help}); | ||||
pod2usage(-verbose => 2) if ($$opt_ref{man}); | ||||
die "\nlyxport: version $version\n\n" if ($$opt_ref{version}); | ||||
## Now get filename (only ONE) | ||||
pod2usage(-verbose => 0, -message => | ||||
"\nERROR: lyxport works with exactly ONE file at a time.\n") | ||||
if (@ARGV != 1); | ||||
($$file_ref)=@ARGV; | ||||
# choose whether to make all targets or just the explicitly specified ones | ||||
unless ($$opt_ref{html} or $$opt_ref{ps} or $$opt_ref{pdf}) { | ||||
$$opt_ref{html}=$$opt_ref{ps}=$$opt_ref{pdf}=1; | ||||
} | ||||
} # end of cmdline_process() | ||||
#----------------------------------------------------------------------------- | ||||
# quick and dirty hash printing by key/value pairs | ||||
sub print_hash { | ||||
my($key_msg,$val_msg,%hash)=@_; | ||||
my($op,$val); | ||||
while ( ($op,$val)=each(%hash) ) {print "$key_msg $op $val_msg $val\n" } | ||||
} # end of print_hash() | ||||
#----------------------------------------------------------------------------- | ||||
sub cmdline_debug{ | ||||
my(%opt)=@_; | ||||
print "\nlyxport command line debug mode\n"; | ||||
print "-------------------------------\n\n"; | ||||
print "This is a dump of your command line options, as key-value pairs:\n\n"; | ||||
print_hash("","->",%opt); | ||||
print "\nExiting...\n\n"; | ||||
exit; | ||||
} # end of cmdline_debug() | ||||
#----------------------------------------------------------------------------- | ||||
# execute a system call but die with some info if return value is non-zero | ||||
sub safe_system { | ||||
my $error; | ||||
$error=system(@_)/256; | ||||
if ($error) { | ||||
print "\nERROR: Command\n @_\nfailed.\n"; | ||||
} | ||||
return $error; | ||||
} # end of safe_system() | ||||
#----------------------------------------------------------------------------- | ||||
# check that the command names specified at the top exist in the system, | ||||
# otherwise choose bare defaults and hope for the best. | ||||
sub set_cmd_defaults { | ||||
my ($cmd)=@_; | ||||
my ($prog,$cmd_name); | ||||
print "\n"; | ||||
while (($prog,$cmd_name)=each(%cmd)) { | ||||
print "Checking for program <$prog>, as <$cmd_name>... \n"; | ||||
if (system("which $cmd_name")/256) { | ||||
$$cmd{$prog}=$prog; | ||||
print "Not found. Reverting to default name $prog.\n"; | ||||
} else { print "OK, found it.\n" } | ||||
} | ||||
print "\nDone configuring command names\n\n"; | ||||
} # end of set_cmd_defaults() | ||||
#----------------------------------------------------------------------------- | ||||
# make sure there's either a .lyx or a .tex file to work with | ||||
# returns a stripped name (without .lyx or .tex extension) of the file | ||||
sub check_file_exists { | ||||
my($file_in)=@_; | ||||
my($base_file); | ||||
$_=$file_in; | ||||
if (/\.lyx$/) { s/\.lyx$// } | ||||
elsif (/\.tex$/) { s/\.tex$// } | ||||
$base_file=$_; | ||||
unless (-e "${base_file}.lyx" or -e "${base_file}.tex") { | ||||
die "I can't find a LyX or LaTeX file to work with!\nAborting...\n\n"; | ||||
} | ||||
return $base_file; | ||||
} # end of check_file_exists() | ||||
#----------------------------------------------------------------------------- | ||||
sub check_targets{ | ||||
my($file,$tag,$built,$failed)=@_; | ||||
my($success)=0; | ||||
$tag .= ' '; | ||||
if (-s $file) { $$built .= $tag; $success=1; } | ||||
else { $$failed .= $tag } | ||||
return $success; | ||||
} # end of check_targets() | ||||
#----------------------------------------------------------------------------- | ||||
# do extra cleaning of aux, toc, log files generated during running | ||||
sub tidy_up { | ||||
my($tidy,$aux,$log,$out,$toc,@latex_from_lyx)=@_; | ||||
lyxport_info("Cleanup of leftover auxiliary files"); | ||||
print "Removing files: $aux, $log, $out, $toc\n"; | ||||
unlink ($aux,$log,$out,$toc); | ||||
if ($tidy>1 and @latex_from_lyx) { | ||||
lyxport_info("Extra cleanup: removing LaTeX file(s) @latex_from_lyx"); | ||||
unlink(@latex_from_lyx); | ||||
foreach (@latex_from_lyx) { | ||||
s/\.tex$/\.aux/; | ||||
if (-e) { | ||||
print "Removing aux file $_\n"; | ||||
unlink($_); | ||||
} | ||||
} | ||||
} | ||||
} # end of tidy_up() | ||||
#----------------------------------------------------------------------------- | ||||
sub lyxport_info { | ||||
my ($target)=@_; | ||||
print "\n",'*'x75,"\n"; | ||||
print "<lyxport> $target\n\n"; | ||||
} # end of lyxport_info() | ||||
#----------------------------------------------------------------------------- | ||||
sub final_diagnostics{ | ||||
my($file_in,$status,$targets_built,$targets_failed)=@_; | ||||
lyxport_info("All done!"); | ||||
print "Input file: $file_in\n\n"; | ||||
print "Targets built : $targets_built\n\n"; | ||||
if ($targets_failed) { | ||||
print "PROBLEM!\nTargets failed: $targets_failed\n\n"; | ||||
} | ||||
print "Diagnostics of build process:\n\n$status\nBye!\n\n"; | ||||
} # end of final_diagnostics() | ||||
#************************ end of code for <lyxport> ******************* | ||||
__END__ | ||||
=pod | ||||
=head1 DESCRIPTION | ||||
=head2 Purpose | ||||
LyX ( http://www.lyx.org ) is a wonderful document processor, which can produce | ||||
from a single source multiple versions for different purposes: a PostScript | ||||
file for printing on a Unix-type system, a PDF file for distribution across | ||||
multiple operating systems, or an HTML file for Internet display. It | ||||
accomplishes this by exporting its own file format to a LaTeX file and then | ||||
running various converters on this resulting file. | ||||
However, it turns out that this process isn't exactly foolproof, as these | ||||
converters have all sorts of little quirks which can produce anything from | ||||
surprises in the way the final result looks like to outright failure of the | ||||
export process. The purpose of B<lyxport> is to serve as a "smart wrapper" | ||||
around those export facilities which LyX normally uses, trying to massage the | ||||
LaTeX file that everything starts from in the hopes of having better success | ||||
in producing HTML and PDF (PostScript usually poses no problems). | ||||
B<lyxport> also allows you to keep around only the LyX file, and possibly any | ||||
ancillary figure files. B<lyxport> takes care of generating (and removing | ||||
afterwards if instructed to do so) any intermediate files necessary for the | ||||
export process. | ||||
For example, in order to make PDF from a LaTeX file, any included eps figures | ||||
need to be converted to pdf format. But LyX likes to have the figures in eps | ||||
format for on-screen display, which is a great feature to have. B<lyxport> | ||||
allows you to keep your LyX file as usual (with references to .eps figures) | ||||
and will make .pdf versions of any included figure on the fly as needed. You | ||||
can even ask it to remove those pdf files after it finishes, if you really | ||||
want to maintain a minimum of files around (though it will have to remake them | ||||
again if you ever need to update your pdf exported document). | ||||
=head2 Command line use | ||||
If you simply type B<lyxport> F<file>, it will try to make PostScript, HTML, | ||||
and PDF versions of your file, putting them all in a single directory named | ||||
F<file> (without a .lyx or .tex extension if your file had one). But it has | ||||
L<command line options|OPTIONS AND ARGUMENTS> for making only the | ||||
formats you want, and fairly detailed control over its behavior. | ||||
=head2 If you don't have LyX | ||||
Despite its name, if you are a regular LaTeX user and don't even have LyX | ||||
installed in your system, B<lyxport> can still be useful to you. In fact, | ||||
B<lyxport> only uses LyX once in each run: if there is no F<file.tex> or if | ||||
F<file.lyx> file is newer than F<file.tex>, B<lyxport> updates F<file.tex> | ||||
from F<file.lyx>. But if there is no F<file.lyx> at all it will simply use | ||||
F<file.tex> and proceed with all its functionality intact. | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 OPTIONS AND ARGUMENTS | ||||
Single letter options (preceded by a single dash B<->) can be bundled: B<-pf> | ||||
is equivalent to B<-p -f>. Long options (preceded by two dashes B<-->) can be | ||||
abbreviated to as few letters as needed to clear ambiguity. | ||||
=over | ||||
=item B<-r --runs> I<NUM> | ||||
Set number of latex runs by hand (otherwise auto-determined). | ||||
=item B<-o --opts_l2h> I<'string'> | ||||
String with options to be passed to B<latex2html>. This string should be | ||||
protected by single quotes to allow double quotes inside of it. | ||||
For example, if you want to pass to B<latex2html> the option B<-info "my | ||||
info"> you can do so with B<lyxport -o ' -info "my info" '> (the extra spaces | ||||
around the quote marks are not needed, they are here only for the sake of | ||||
clarity). | ||||
B<latex2html> has I<many> command-line options. For a project you are working | ||||
constantly on, it may be more convenient to permanently set some of those | ||||
options via a file called F<.latex2html-init> which B<latex2html> always | ||||
reads at startup. See the B<latex2html> man page or the excellent online | ||||
documentation kept at http://www-texdev.mpce.mq.edu.au/l2h/docs/manual for | ||||
full details. | ||||
=item B<-h --html> | ||||
Export to HTML. | ||||
=item B<-p --ps> | ||||
Export to PostScript. | ||||
=item B<-f --pdf> | ||||
Export to PDF. See below the section L<PDF GENERATION> for details on how to | ||||
obtain nice-looking PDF from your LaTeX sources. | ||||
If none of the three above options is specified, the default behavior is to | ||||
export I<all> three formats. If any is given, then only those formats | ||||
explicitly specified will be produced (e.g. B<-h -f> makes HTML and PDF only, | ||||
but not PostScript). | ||||
=item B<--leave> | ||||
By default lyxport moves the resulting PostScript and PDF files into the | ||||
directory containing the HTML results (if it was created). This option tells | ||||
it to leave them in the current directory. | ||||
=item B<-c --clean> | ||||
Do a clean start export, removing first any html directory, .aux, .log | ||||
and .toc files which may have been left from previous runs. | ||||
=item B<-t --tidy> | ||||
B<lyxport> will tidy up I<after> itself, removing .aux, .log and .toc files left | ||||
in the current directory. Use this only for "final" publication of documents, as | ||||
those files are otherwise useful to shorten the time of runs. | ||||
This option is incremental: you can call it twice (you can bundle it as | ||||
B<-tt>). If called twice, B<lyxport> will remove also the LaTeX file | ||||
associated with your LyX file, but I<only if> B<lyxport> I<itself created it | ||||
in the same run>. This behavior is meant to be a safety net, so that | ||||
B<lyxport> doesn't accidentally remove LaTeX files which you may have manually | ||||
modified in some way. | ||||
So if this option is called twice, you can start with a LyX file named F<file.lyx> | ||||
and end up only with your original file plus a single directory named F<file> which | ||||
will contain F<file.html>, F<file.ps> and F<file.pdf> (plus some ancillary stuff for | ||||
the html version). This mode of operation is obviously provided for the neatness | ||||
freaks amongst us. | ||||
=item B<-d --debug> | ||||
Debugging mode: B<lyxport> will leave I<all> temporary files it creates lying | ||||
around. If a particular target refuses to build, you can then try to run the | ||||
respective commands on the temporary files manually, and possibly diagnose the | ||||
source of the problem. | ||||
This option will override any calls made to option B<--tidy>. | ||||
=item B<-l --cld> | ||||
Special command-line debugging mode: only prints (in a rather primitive form) | ||||
the names and values of all command-line options which were set. Useful for | ||||
finding problems with complicated option strings being passed to | ||||
B<latex2html>. | ||||
=item B<--help> | ||||
Print this help and quit. | ||||
=item B<-m --man> | ||||
Print a complete man page. B<lyxport> is documented using embedded pod | ||||
strings, so you can see its full documentation using the command B<perldoc | ||||
lyxport>. | ||||
You can also convert this documentation to other formats using the | ||||
I<pod2_anything> family of converters (L<pod2html>, L<pod2latex>, L<pod2man> | ||||
and L<pod2text>). See their respective man pages for details. | ||||
Note that if you installed B<lyxport> properly, you should already have a man | ||||
page available, plus html and plain text versions of the documents. These are | ||||
by default installed to a directory named F</usr/local/doc/lyxport-XXX>, where | ||||
F<XXX> is the version number. At installation time, you may manually change | ||||
the F</usr/local> prefix. Consult your local documents or ask your system | ||||
administrator for details on the specifics of your configuration. | ||||
=item B<-v --version> | ||||
Print version information and quit. | ||||
=item B<filename> | ||||
The given filename may have a .lyx or .tex extension (or none at | ||||
all). I<lyxport> will update the tex file from the lyx file if necessary. | ||||
B<lyxport> accepts only I<one> filename at a time. | ||||
=back | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 INTEGRATION WITH LyX | ||||
If you find that B<lyxport> is more succesful in exporting your files than | ||||
LyX's default calls to B<latex2html> and B<pdflatex>, you can modify LyX to | ||||
use B<lyxport> as its conversion routine. For LyX versions 1.1.6 and above, go | ||||
to C<< Edit->Preferences->Converters->Converters >> and specify B<lyxport> as your | ||||
converter for C<< LaTeX->HTML >> and C<< LaTeX->PDF >>. LyX's convention | ||||
is to call B<$$i> the current file. | ||||
For example, if you want to setup B<lyxport> to be your PDF export filter | ||||
under LyX, in the C<Converters> dialog, in the C<< LaTeX->PDF(pdflatex) >> | ||||
option, set: | ||||
lyxport --pdf $$i | ||||
This way you'll be able to export to pdf directly from within LyX, even if | ||||
your figures are in eps format. | ||||
LyX's C<Converters> dialog is a bit confusing: after making changes, you must | ||||
first press the C<Modify> button for your changes to actually be recorded, and | ||||
then C<Save>. | ||||
You can similarly set up B<lyxport> to be your LaTeX to HTML converter. | ||||
For LyX versions earlier than 1.1.6 (which didn't have the new Preferences | ||||
dialog) these same options can be configured via your LyX defaults file. See | ||||
the LyX documentation for details. | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 PDF GENERATION | ||||
=head2 Fonts | ||||
Normally PDF documents made on Unix-type systems from LaTeX sources produce | ||||
horrible looking fonts when viewed with Adobe's own Acrobat Reader. I don't | ||||
know the many intricacies of the problem (you can search for the details on | ||||
your own). I'll simply list here the trick that has helped I<me> solve the | ||||
font problem. Try it, your mileage may vary. | ||||
=over | ||||
=item 1 | ||||
In your home directory, make (or modify it if it already exists) a file | ||||
named F<.dvipsrc> which must contain the lines: | ||||
p+ psfonts.cmz | ||||
p+ psfonts.amz | ||||
=item 2 | ||||
Make sure that the LaTeX preamble of your LyX file (or the part before | ||||
C<\begin{document}> if you are using straight LaTeX files) contains: | ||||
\usepackage[T1]{fontenc} | ||||
\usepackage{ae,aecompl} | ||||
This will guarantee that T1 encoded fonts come out looking good in the final PDF. | ||||
=back | ||||
=head2 Figures | ||||
B<pdflatex> (if I understand correctly) only accepts filenames with a single | ||||
B<.> in them, and only uses graphic files with extensions pdf, png, jpg and | ||||
tif (all lowercase). B<lyxport> will do its best to analyze your latex file | ||||
and try to change references to figures to accommodate B<pdflatex>, by | ||||
creating temporary copies of your image files if necessary. | ||||
Ideally, you should be able to have for example a figure called F<fig.1.JPG> | ||||
along with a F<fig.1.eps> (for B<lyx> to preview it), and B<lyxport> would | ||||
export a pdf document without leaving any more files after itself, even though | ||||
it temporarily had to create F<fig_1.jpg> to make B<pdflatex> happy. As I | ||||
said, ideally... If things don't quite work, try the B<--debug> option. If you | ||||
find a fix for the problem, mail it to me: fperez@pizero.colorado.edu | ||||
=head2 Links | ||||
In order for URLs and similar elements to produce proper active links in the | ||||
PDF document, you need to include in your LaTeX preamble the line | ||||
\usepackage{hyperref} | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 REQUIRES | ||||
B<lyxport> relies on some programs listed below, for the reasons indicated: | ||||
=over | ||||
=item B<lyx> | ||||
To make LaTeX files from LyX files. Tested with lyx version 1.1.6fix1, should | ||||
work with earlier versions (perhaps with minor changes to the way LyX is called). | ||||
=item B<latex> | ||||
To produce PostScript and for latex2html to work properly (cross-references). | ||||
=item B<dvips> | ||||
For making PostScript output. | ||||
=item B<latex2html> | ||||
For generating HTML from latex sources. | ||||
=item B<pdflatex> | ||||
For making PDF output from a latex file with proper cross-referencing and | ||||
internal document links. | ||||
=item B<epstopdf> | ||||
A Perl script to automatically generate pdf versions of eps figures included | ||||
in lyx files. It is more robust in its handling of various eps quirks than a | ||||
straight call to B<ps2pdf>. | ||||
=item B<perl> | ||||
Well, it's a Perl script after all, isn't it? | ||||
=back | ||||
However, partial use of B<lyxport> is still possible without some of these | ||||
components. If for example you don't have B<latex2html> in your system, you | ||||
can still use B<lyxport> to produce PostScript and PDF. Various combinations | ||||
are possible. | ||||
=head2 Portability | ||||
There are calls in B<lyxport> to some Unix commands like B<rm -rf>. For this | ||||
reason it is not totally portable. These calls are however reasonably few and | ||||
could be eliminated if there is enough demand by replacing them with | ||||
equivalent Perl code. It's just more work... | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 TO DO | ||||
=over | ||||
=item * | ||||
Build rpm for more convenient installation. | ||||
=item * | ||||
Clean up the C<improve_tex4html()> code for readability. | ||||
=back | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 VERSION | ||||
This is B<lyxport> version 0.3.1 | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 AUTHOR | ||||
Fernando Pérez E<lt>fperez@pizero.colorado.eduE<gt>. | ||||
Please email me with comments, suggestions, bugfixes, etc. | ||||
The most current version of B<lyxport> should always be available at | ||||
http://www-hep.colorado.edu/~fperez/lyxport | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 ACKNOWLEDGEMENTS | ||||
Inspired on the B<lyx2html> script by Steffen Evers | ||||
E<lt>tron@cs.tu-berlin.deE<gt>. Some of the code is a blatant ripoff of | ||||
Steffen's code, using B<s2p> to get Perl versions of his original B<sed> | ||||
scripts. | ||||
=cut | ||||
########################################################################### | ||||
=pod | ||||
=head1 COPYRIGHT AND DISCLAIMER | ||||
This program is Copyright 2001 by Fernando Pérez. | ||||
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; either version 2 of the License, or (at your option) any later | ||||
version. | ||||
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. See the | ||||
GNU General Public License for more details. | ||||
If you do not have a copy of the GNU General Public License write to | ||||
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, | ||||
MA 02139, USA. | ||||
If the author of this software was too lazy to include the full GPL text along | ||||
with the code, you can find it at: http://www.gnu.org/copyleft/gpl.html | ||||
=cut | ||||
#************************** end of file <lyxport> ********************** | ||||