#!/bin/bash -p # # Latex wrapper script, version 0.96 # # The purpose of this script is to make running latex # more efficient and more convenient. # # What this script can do for you: # # 1. Run latex/pdflatex using a custom format, # remaking the custom format if necessary; # 2. Grep for errors, warnings, unresolved references, # or underfull/overfull boxes; # 3. Call dvips/dvipdfm # 4. Start a viewer, or notify the viewer if already running, # so that it pops up to the front and reloads the dvi/ps/pdf file. # 5. Convert xfig files into eps files. # 6. Create/use thumbnails (only with dfvipdfm; stolen from dvipdft) # # Reasons: # 1. This will speed up latex a lot # o if you have a small document and at least a few \usepackage's, or # o if you have a lot of \usepackage's, or # o if your home and/or latex installation is on a remote server. # 2. This can reduce the "verboseness" of latex, which can help # during the early stages of a document. # 3. Convenience during the final stages of the document. # 4. Convenience, too, especially when run from an editor. # 5. This is usually done by a makefile; however, we need this script anyway, # so we can do it here as well. Plus, by doing it here ein 'ltx', we can # find out which xfig-files are actually included in the tex file. # # Symopis: # ltx [options ..] [main_latex_files ..] # default = no option = print only errors and new chapters; # for a list of all options, type 'ltx -h'. # # Examples: # 1. 'ltx paper' # creates custom format file for paper.tex, if not existing yet, # and create DVI file paper.dvi; print only errors, but continue latex'ing; # 2. 'ltx -x paper' # like 1, and start xdvi, or update xdvi if already started by previous 'ltx'; # 3. 'ltx -w paper' # like 1, but print all warnings; # 4. 'ltx -p paper' # like 1 and run dvips at the end; # # The two paths of creating PDF with ltx: # I. Using pdftex: # 'ltx -P paper' # (it still creates a custom format file for speedup) # II. Using dvipdfm: # In your document you should use the 'dvipdfm' option with packages # instead of 'dvips', for instance: # \documentclass[dvipfdm]{article} # \usepackage[dvipdfm]{graphicx} # \usepackage[dvipdfm]{hyperref} # Then 'ltx paper' will create the DVI file, # and 'ltx -D -P paper' will create the PDF file. # If you want to be able to create both Postscript and PDF # from the same laTeX source, you can write: # \ifx\dvipdfm\undefined # \documentclass[dvips]{book} # \usepackage[dvips]{graphicx} # \else # \documentclass[dvipdfm]{book} # \usepackage[dvipdfm]{graphicx} # \fi # (Actually, one of option -D's jobs is to define \dvipdfm) # Of course, options -x/-w/etc can be combined with -D/-P. # # How 'ltx' determines the tex file: # If no main_latex_file is specified, then 'ltx' uses "whole.tex", # "main.tex", or "root.tex" in the current working directory, if present. # If none exists, then it processes all .tex files which are newer than # their dvi/ps/pdf files. # If you do specify the main latex file(s), you can say 'ltx main.tex', # 'ltx main.', or just 'ltx main'. # Each main_latex_file should be the "root" tex file of the document. # # Caching of window id's: # In order to speed up the signalling of the previewer window, # ltx tries to use the cached window id. # If that cache is older than 1 day, then it is not used. # # Conversion of xfig files to eps: # This is done with the fig2dev program. # In addition, all text in such xfig files is enclosed by \tex{..} # for use with psfrag.sty. # If you don't like this, remove the call of psfrag_instex, and change # the call of fig2dev accordingly. # # Page size: # Deteremines automagically the page size (by grepping the tex source), # and passes the appropriate function to dvips/dvipdfm. # Works only if specified in the source by \usepackage[..a4paper..]{geometry} # in one(!) line. # # Notes: # - This script finds out atomatically if something in the preamble of the # main document has been changed. # - It can handle several separate LaTeX documents in the same directory. # - It does not notice if something in a style file or package has changed. # - You can run this script from an editor or from the shell. # - ltx will *not* re-generate the format file, # if you change one of the definitions (option -f) or options. # # This script has been tested with teTeX under IRIX (SGI's Unix). # It should work under any other Unix, too. # # History: # 0.9 - GZ, Aug 2000 # 0.91 - GZ, Sep 00, multiple files, aux files start with dot # 0.92 - GZ, Sep 00, cache window id # 0.93 - GZ, Sep 00, try to find out our parent process for "press return.." # 0.94 - GZ, Sep 00, convert fig -> eps, too # 0.95 - GZ, Oct 00, dvipdfm option added, inlcuding thumbnail feature # 0.95 - GZ, Dec 00, orig. option -f is gone, has new meaning # 0.96 - GZ, Dec 00, run latex if document class doesn't allow custom format file # 0.97 - GZ, Apr 01, works under IRIX and Solaris5 (and maybe others) # 0.98 - GZ, Jun 01, changed to bash, so that it runs under Linux # # Home location of this script: # http://www.igd.fhg.de/~zach/latex/index.html#ltx # # Author: # Gabriel.Zachmann@gmx.net # Please send updates, corrections, etc., to Gabriel.Zachmann@gmx.net # # TODO: # # License: # You can do with this script whatever you want, # provided you give credit where credit is due, # and provided you don't make money from it. # # you can add your favorite main tex file name here default_main_files="whole main root" # where temp files are put tmpdir=${TMPDIR:-/tmp} # path of fig2dev program fig2dev=/igd/a4/software/xfig/fig2dev # in case of an error, and the parent process of 'ltx' is one of the following, # the user has to press return (for vim: set shell=/bin/ksh !) editors='vi|vim|emacs|jot|pico|nano|joe|jed' # where option -t puts the thumbnail images (seems like it *must* be /tmp ;-( ) thumbnaildir=./thumbnails # parse command line pattern="! |l\.[0-9]|chapter:|\\\\\\end|\([a-zA-Z0-9_\-]*\.tex|[0-9]\]\)" # dunno why 6x backslash. see also antipattern variable below pdf="" defs="" texfiles="" printer="" dvips="" while [[ $# > 0 ]] do case $1 in -n) nopattern=1;; -c) pattern="$pattern|Citation";; -r) pattern="$pattern|Reference";; -e) pattern="$pattern|non-existent";; -o) pattern="$pattern|Overfull";; -w|-W) pattern="$pattern|Citation|Overfull|Warning:|non-existent|Reference|re-run"; pattern="$pattern|LaTeX Font Info:|\(Font\)"; if [[ "$1" = -W ]] then pattern="$pattern|Underfull"; fi allwarnings=1;; -u) pattern="$pattern|Underfull";; -p) dvips=1;; -P) pdf=pdf;; -D) dvipdfm=1;; -C) cleanup=1;; -x) raise_window=1;; -i) dont_run_initex=1;; -I) run_initex=1;; -W) dont_use_winid=1;; -t) thumbnails=1;; -f) defs="$defs $2"; shift;; -O) printer=1;; -h) echo 'Usage: ltx [options ..]' echo ' -c = print missing citations' echo ' -r = print reference errors' echo ' -e = print non-existent pictures' echo ' -o = print overfull and underfull boxes' echo ' -w = print all warnings & errors (except underfull boxes)' echo ' -W = print all warnings & errors (including underfull boxes)' echo ' -n = print all latex output' echo " -i = don't run initex, even if preabmle has changed" echo " -I = run initex, even if preabmle has not changed" echo ' -x = raise xdvi/gv window, or start the viewer' echo ' -p = create Postscript (default = create DVI)' echo ' -P = create PDF (using pdftex or dvipdfm, depending on -D)' echo ' -D = use dvipdfm for creating PDF, and define \dvipdfm' echo ' -O = send it to the default printer' echo ' -t = create/use thumbnails (only with -D & -P)' echo ' -C = clean, =remove all aux. files before running latex, incl. format file' echo " -W = don't used cached window id of viewer" echo " -f ... = put tex code ... just before the \input; can be used for def's" echo ' -h = this help' exit ;; *) f="${1%tex}"; f="${f%.}" texfiles="$texfiles $f.tex";; esac shift done #augment pattern, set antipattern if [[ ! -z "$dvipdfm" || ! -z "$pdf" ]] then # latex should include only PDF images pattern="$pattern|\.eps>" antipattern="\([^ \)]*\.(eepic|pdf|jpg)\)" else antipattern="\([^ \)]*\.(eepic|eps|jpg)\)" fi # check sanity of options if [[ ! -z "$thumbnails" ]] then if [[ -z "$pdf" || -z "$dvipdfm" ]] then echo "ltx: option -t makes sense only with options -D and -P!" echo " (ignoring)"; thumbnails="" fi fi if [[ ! -z "$dvipdfm" && ! -z "$dvips" ]] then echo "ltx: Warning: options -D and -p together make no sense!" echo " Assuming -P instead of -p." dvips="" pdf=pdf fi # accommodate different OS's OS=`uname` case $OS in SunOS) id=/usr/xpg4/bin/id grep=/usr/xpg4/bin/grep egrep=/usr/xpg4/bin/egrep tr=/usr/xpg4/bin/tr pidpos=9-15 ;; *) id=id grep=grep egrep=egrep tr=tr pidpos=9-15 ;; esac # find tex files if none specified on command line if [[ -z "$texfiles" ]] then for f in $default_main_files do if [[ -e "$f".tex ]] then texfiles="$f" break fi done fi if [[ -z "$texfiles" ]] then for f in *.tex do fn="${f%.tex}" if [[ "$fn.dvi" -ot "$f" || (! -z "$dvips" && "$fn.ps" -ot "$f") || (! -z "$pdf" && "$fn.pdf" -ot "$f") ]] then texfiles="$texfiles $f" fi done fi if [[ -z "$texfiles" ]] then echo "ltx: no main tex file specified, none of the default ones found," >& 2 echo " and none of the .tex files has changed." >& 2 exit 1 fi echo "tex files = $texfiles" if [[ ! -z "$printer" ]] then if [[ ! -z "$pdf" ]] then echo "Can't print from PDF file!" echo "(Maybe you meant option -O instead of -P?)" elif [[ -z "$dvips" ]] then dvips=1 fi fi function processtex { echo "Processing $1 ..." maintex="${1%.tex}" if [[ ! -f "$maintex.tex" ]] then echo " $maintex.tex does not exist!" return fi # set some variables so discrimination between latex/pdflatex is easier if [[ -z "$pdf" && -z "$dvipdfm" ]] then fmtsuff="dvi" elif [[ -z "$dvipdfm" ]] then fmtsuff="pdf" else fmtsuff="dvipdfm" fi prefile=".$maintex-$fmtsuff.pre" fmtfile=".$maintex-$fmtsuff.fmt" # clean up aux files if [[ "$cleanup" != "" ]] then echo Removing intermediate files .. for suf in log aux toc lot lof out blg pfg brf otc #bbl do if [[ -e "$maintex".$suf ]] then echo -n "$maintex.$suf " rm "$maintex".$suf fi done echo for f in "$prefile" "$fmtfile" ".$maintex.xdvi" ".$maintex.gv" mylatex.ltx do if [[ -e "$f" ]] then echo -n "$f" rm "$f" fi done echo if [[ -e $thumbnaildir/"$maintex".1 ]] then echo $thumbnaildir/"$maintex.[0-9]*" rm $thumbnaildir/"$maintex".1 rm $thumbnaildir/"$maintex".[0-9]* 2>/dev/null fi fi # check if document class alows custom format file weird_document_class=`head -20 "$maintex.tex" | grep documentclass | grep dinbrief` # check if preambel has changed if [[ ! -e "$fmtfile" ]] then run_initex=1 elif [[ -z "$dont_run_initex" && "$fmtfile" -ot "$maintex.tex" && -z "$run_initex" && -z "$weird_document_class" ]] then tmprefile=$tmpdir/ltx-$$-pre rm -f "$tmprefile" sed -e '/begin{document}/q' -e '/^[ ]*%/d' -e '/^[ ]*$/d' \ "$maintex.tex" > "$tmprefile" if [[ ! -s "$tmprefile" ]] then echo echo Couldn\'t extract preambel of "$maintex.tex"! echo "(No begin{document}?)" echo Assuming format has to be rebuilt .. run_initex=1 elif [[ ! -e "$prefile" || ! -e "$fmtfile" ]] then cp "$tmprefile" "$prefile" run_initex=1 elif diff -b "$tmprefile" "$prefile" > /dev/null then echo Custom format file is up-to-date else rm "$prefile" cp "$tmprefile" "$prefile" run_initex=1 fi rm -f "$tmprefile" fi # run initex, if necessary if [[ ! -z "$pdf" && -z "$dvipdfm" ]] then pdftex=pdf else pdftex="" fi if [[ ! -z "$run_initex" ]] then echo "Running initex to create custom format file ..." # remove some secondary files, which might cause problems otherwise # for instance, when switching from PDF to PS rm -f "$maintex.aux" "$maintex.brf" if [[ ! -e mylatex.ltx ]] then # try to symlink it mylatex=`kpsewhich mylatex.ltx` if [[ "$mylatex" = "" ]] then echo "ltx: couldn\'t find mylatex.ltx!" >& 2 exit 1 fi echo "Linking mylatex.ltx to $mylatex." echo rm -f mylatex.ltx # -e==false also, if mylatex.ltx is dangling link ln -s $mylatex . fi if [[ ! -z "$dvipdfm" ]] then defs="$defs \def\dvipdfm{1}" fi ${pdftex}initex \&${pdftex}latex mylatex.ltx \ "\relax $defs \input" "$maintex.tex" if [[ $? != 0 ]] then echo "ltx: don't run latex because of error from initex!" >& 2 exit $? fi mv mylatex.fmt "$fmtfile" echo fi # stop viewer (if any) # to prevent viewer from updating while outfile is incomplete pid=""; wid="" if [[ -z "$dvips" && -z "$pdf" ]] then viewer_name=xdvi.bin # we start xdvi.bin, because xdvi start 'xdvi.bin -name xdvi ...', # which leaves less room for the dvi file name, which increases # changes that 'grep $maintex' failes. else viewer_name=gv fi idfile=".$maintex.$viewer_name" my_uid=`$id -u` if [[ ! -z "$dont_use_winid" ]] then rm -f "$idfile" fi if [[ -r "$idfile" ]] then # try cached id's pid=`head -n 1 -q "$idfile"` wid=`tail -n 1 -q "$idfile"` if [[ ! -z "$pid" ]] then if /bin/ps -p $pid | grep -q $pid then true else pid=""; wid="" rm -f "$idfile" echo rm -f "$idfile" fi fi fi if [[ -z "$pid" ]] then pid=`/bin/ps -f -u $my_uid | grep $viewer_name | grep "$maintex" | head -1 | cut -b$pidpos` # this grep works only, if viewer is started like 'gv file.ps -options'. fi if [[ ! -z "$pid" ]] then kill -STOP $pid fi # run latex ltxoutfile="$maintex.dvi" if [[ -e "$ltxoutfile" ]] then rm -f "$ltxoutfile".old mv "$ltxoutfile" "$ltxoutfile".old fi echo "Running latex ..." if [[ -z "$weird_document_class" ]] then # we can actually use a custom format file if [[ "$nopattern" = 1 ]] then ${pdftex}virtex --interaction nonstopmode \&"${fmtfile%.fmt}" "$maintex" else echo "pattern=$pattern" ${pdftex}virtex --interaction nonstopmode \&"${fmtfile%.fmt}" "$maintex" | $egrep "($pattern)" #| $egrep -v "$antipattern" fi else # some classes don't work with custom format files :-( echo " document class doesn't work with custom format file." ${pdftex}latex --interaction nonstopmode "$maintex" fi # check if latex succeded (checking $? doesn't seem to work ;-( ) err=0 if [[ ! -f "$ltxoutfile" ]] then echo echo No $ltxoutfile file! err=1 fi if [[ ! -f "$maintex".log ]] then echo echo No log file! err=1 fi if $grep -q -e '^!' "$maintex".log then echo echo "LaTeX has encountered errors!" err=1 fi if [[ "$err" = 1 ]] then if [[ ! -z "$pid" ]] then # continue viewer kill -CONT $pid fi return fi # run dvips/dvipdfm if wanted if [[ ! -z "$dvips" || ( ! -z "$dvipdfm" && ! -z "$pdf" ) ]] then # find out paper size geometry=`$grep -e {geometry} "$maintex.tex" | $egrep -v ^%` if [[ ! -z "$geometry" ]] then papersize="" if [[ "$geometry" = *a4paper* ]] then papersize="a4" elif [[ "$geometry" = *letterpaper* ]] then papersize="letter" fi if [[ ! -z "$papersize" ]] then echo Paper size: $papersize if [[ ! -z "$dvips" ]] then papersize="-t $papersize" else papersize="-p $papersize" fi fi fi fi if [[ ! -z "$dvips" ]] then echo "Running dvips ..." dvips $papersize -Pcmz -Pamz -o -r0 "$maintex" elif [[ ! -z "$dvipdfm" && ! -z "$pdf" ]] then save_tmp="$TMP" if [[ ! -z "$thumbnails" && -d "$thumbnaildir" && -e "$thumbnaildir/$maintex.1" ]] then export TMP="$thumbnaildir" echo "Running dvipdfm (using thumbnails from $TMP) ..." thumb="-t" else echo "Running dvipdfm ..." thumb="" fi dvipdfm $papersize $thumb -z9 "$maintex" TMP="$save_tmp" fi # continue viewer if [[ ! -z "$pid" ]] then kill -CONT $pid fi # print it if [[ ! -z "$printer" && -s "$maintex.ps" ]] then echo "printing $maintex.ps .." lpr "$maintex.ps" fi # raise dvips/gv window if any, or launch it if [[ "$raise_window" != "" ]] then if [[ ! -z "$pdf" ]] then viewed_file="$maintex".pdf elif [[ "$dvips" != "" ]] then viewed_file="$maintex".ps else viewed_file="$maintex".dvi fi if [[ $viewer_name = gv ]] then win_name=gv viewer_options="-safer -pixmap" signal=HUP else win_name=Xdvi viewer_options="-paper a4 -nopostscript -keep -s 7 -gsalpha -bg white" signal=USR1 fi if [[ -z "$pid" || -z "$wid" ]] then echo "starting $viewer_name .." $viewer_name "$viewed_file" $viewer_options -geometry +100+1 > /dev/console 2>&1 & # viewed_file must be first parameter, so that we can ps|grep for it # cache window id echo "trying to obtain window id .." sleep 1 pid=`/bin/ps -f -u $my_uid | $grep $viewer_name | $grep "$maintex" | $grep -v grep | head -1 | cut -b$pidpos` typeset -i i=0 wid="" if [[ `uname` == Linux && "$DISPLAY" == :0* ]] then # seems to be necessary under RedHat 7.0 :-( # (for xwininfo) DISPLAY=`uname -n`:0.0 fi while [[ ! -z "$pid" && -z "$wid" && $i -lt 10 ]] do echo . # Window id doesn't show up immediately :-( . # We can't grep for $maintex, because if hyperref is used # gv shows the pdftitle, not the file name. sleep 1 wid=`xwininfo -root -tree | $grep $win_name | # "$maintex" $tr -s "[:space:]" | cut -d' ' -f2` (( i += 1 )) done if [[ -z "$pid" || -z "$wid" ]] then echo if [[ -z "$pid" ]] then echo Failed to determine PID of $viewer_name! else echo Failed to determine window ID of $viewer_name! fi echo else echo "window id = $wid" echo $pid > "$idfile" echo $wid >> "$idfile" fi else echo "raising viewer (window id = $wid)" raise_window $wid # send "update" signal, in case the viewer was already on top kill -$signal $pid fi fi # create thumbnails if [[ ! -z "$thumbnails" && -s "$maintex.pdf" && ! -z "$pdf" && ! -z "$dvipdfm" ]] then if [[ -d $thumbnaildir ]] then echo "Updating thumbnails ..." rm -rf $thumbnaildir else echo "Creating thumbnails ..." fi if [[ ! -d $thumbnaildir ]] then mkdir $thumbnaildir fi if [[ ! -d $thumbnaildir ]] then echo "ltx: Failed to create thumbnail directory $thumbnaildir!" else gs -r10 -dNOPAUSE -dBATCH -sDEVICE=png256 \ -sOutputFile=$thumbnaildir/"$maintex".%d "$maintex".pdf | \ $grep -v -e Loading -e Page fi fi } # process each tex file err=0 for f in $texfiles do processtex $f done if [[ "$err" = 1 ]] then # check if running from an editor if /bin/ps -p $PPID | $grep -E -q "$editors" then echo echo Press return .. read l exit 1 fi fi