#!/bin/bash # $Id: proof,v 1.2 2002/09/30$ ################################################################################ # Proof - A simple but smart editor interface to common # # TeX/LaTeX and METAFONT/MetaPost processing tasks # # # # (Copyright (C) 2002 Klaus Bosau) # ################################################################################ function info { echo \ "Usage: proof [-P] [-abfp123xyzs] [-u routine] file or: proof -T file or: proof [-hv] Process and view TeX, LaTeX, METAFONT and MetaPost sourcecode -P enter preview mode -T leave preview mode and exit -a leave auxiliary files untouched -b create back-up file -f use formatfile 'mylatex' -p use PostScript-Type-1 fonts -n METAFONT proofing mode n, where n can be 1, 2 or 3 -x generate dvi-file -y generate ps-file (default) -z generate pdf-file -u call userdefined conversion routine -s don't call viewer -h print this help message -v print version information Options -abfp123xyzus may be handed over also in the sourcecode itself. (see Proof manual page on how to do this) However, if you'd like to make use of this feature, you should keep in mind that this would make both ad- ditional small letter commandline options (except -h and -v) and existing environmental settings ineffective. Please send bug reports or suggestions to kbosau@web.de." } configfile=~/.proofrc # default configuration file function error { echo -e "--> ${0##*/}: $1" [ "$2" ] && { [ "$action" = 'watch' ] && read; exit 1; } } [ ! -e $configfile ] && error "Can't find configuration file!" halt # global initializations . $configfile optionlist=':PTfbap123xyzu:sv' # 'getopts' option list nfsscmd='\table' # 'nfssfont' test command FORMATFILEDIR=$(eval echo $FORMATFILEDIR) # assign absolute path # dvips if [ "${DVI2PS%% *}" = 'dvips' ]; then PDF_OPT='-P pdf -G0' # enable distilling to PDF PSFONTS_OPT='-P cmz -P amz' # use PostScript-Type-1 fonts fi # TeX comp='tex' init='tex --ini &latex mylatex.ltx' virt='virtex --fmt latex' myvirt='virtex --fmt mylatex' formatfile='latex.fmt' myformatfile='mylatex.fmt' if [ "$USE_ETEX" = 'yes' ]; then comp='etex' init='etex --ini &elatex mylatex.ltx' virt='evirtex --efmt elatex' myvirt='evirtex --efmt mylatex' formatfile='elatex.efmt' myformatfile='mylatex.efmt' fi # pdfTeX pdfcomp='pdftex' pdfvirt='pdfvirtex --fmt pdflatex' if [ "$USE_ETEX" = 'yes' ]; then pdfcomp='pdfetex' pdfvirt='pdfevirtex --efmt pdfelatex' fi function option # checks if option is set { local opt function opts { local line if line=$(head -1 $_source$_ext | grep '(-'); then echo $line | sed 's/^.*(\(-[^)]*\)).*/\1/' # document elif [ "$OPTS" ]; then echo $OPTS # commandline else echo $PROOFOPTS # environment fi } [ ! -e $_source$_ext ] && return 1 if [ "$1" = 'y' ]; then ! option x && ! option z && return 0 # enables default output filetype else OPTIND=1 while getopts $optionlist opt $(opts); do [ $opt = $1 ] && return 0 done fi return 1 } function tex2dvi { local cmd=$comp fdir=${FORMATFILEDIR:-$PWD} function _mv { [ $2 = $PWD ] && return 0 mv $1 $2 } if grep '^\(\\documentclass\|\\documentstyle\)' >/dev/null; then cmd=$virt # LaTeX source if option f; then if [ ! -e $fdir/$myformatfile ]; then echo "${0##*/}: Building formatfile..." [ ! -d $fdir ] && \ { error "Can't find directory $fdir!"; return 1; } $init $_source && _mv $myformatfile $fdir || \ { error 'Unable to install formatfile!'; return 1; } rm -f mylatex.log; new_ff=yes fi cmd=$myvirt # read formatfile fi fi $cmd --interaction=$REPORTMODE $1 } <$_source$_ext function tex2pdf { local cmd=$pdfcomp grep '^\(\\documentclass\|\\documentstyle\)' >/dev/null && cmd=$pdfvirt $cmd --interaction=$REPORTMODE $1 } <$_source$_ext function pid # returns PID's matching given pattern { $PROCSTAT | grep -v 'grep' | grep "$*" | sed 's/^\ *\([0-9]*\)\ .*$/\1/' } function view_file { local cmd function tell # starts process only if not yet running (untested) { # force reread [ -n "$(pid ghostview $2)" ] && return 0 kill -SIGUSR1 $(pid xdvi.bin $2) >/dev/null 2>&1 && return 0 kill -SIGHUP $(pid gv $2) >/dev/null 2>&1 && return 0 # start anew $* & } case "${1##*.}" in dvi) cmd=$DVI_VIEWER; last=x;; ps ) cmd=$PS_VIEWER; last=y;; pdf) cmd=$PDF_VIEWER; last=z;; esac option s || tell $cmd $1 } function view # conversion and viewing { local dvi2ps=$DVI2PS function mk_test { $virt --interaction=$REPORTMODE $1 </dev/null; then $OPTARG $_source && view_file $_source.${ftypes##*->} else error "Can't find conversion routine $OPTARG!" fi return fi case $_ext in .mf ) if option 2; then mk_test nfssfont "${_source}:${nfsscmd}:\bye" ftypes='*pk,tfm->' elif option 3; then mk_test fontsmpl "${_source}" else $MF --interaction=$REPORTMODE "\mode=proof; input $_source;" && \ gftodvi $_source.*gf && \ if option x; then view_file $_source.dvi ftypes='log,*gf,*pk,tfm,dvi->' else $dvi2ps $_source.dvi && \ view_file $_source.ps ftypes='log,*gf,*pk,tfm,dvi,ps->' fi fi;; .mp ) $MP --interaction=$REPORTMODE $_source && \ tex2dvi "mproof $(ls $_source.[0-9]*)" && \ if option x; then view_file mproof.dvi else $dvi2ps mproof.dvi && \ view_file mproof.ps fi ftypes='log,mpx->[0-9]';; .tex) if option x; then tex2dvi $_source.tex && \ view_file $_source.dvi ftypes='log,aux->dvi' elif option z; then case "$TEXPDFMODE" in 2) tex2dvi $_source.tex && \ $DVI2PDF $_source.dvi ftypes='log,aux,dvi->pdf';; 3) tex2dvi $_source.tex && \ $DVI2PS $PDF_OPT $_source.dvi && \ $PS2PDF $_source.ps ftypes='log,aux,dvi->pdf';; *) tex2pdf $_source.tex ftypes='log,aux->pdf';; esac && view_file $_source.pdf else tex2dvi $_source.tex && \ $dvi2ps $_source.dvi && \ view_file $_source.ps ftypes='log,dvi,aux,idx->ps' fi;; .dvi) if option y; then $dvi2ps $_source.dvi && \ view_file $_source.ps ftypes='->ps' elif option z; then case "$DVIPDFMODE" in 2) $DVI2PS $PDF_OPT $_source.dvi && \ $PS2PDF $_source.ps ftypes='ps->pdf';; *) $DVI2PDF $_source.dvi ftypes='->pdf';; esac && view_file $_source.pdf else view_file $_source.dvi fi;; .ps ) if option z; then $PS2PDF $_source.ps && \ view_file $_source.pdf ftypes='->pdf' else view_file $_source.ps fi;; .pdf) view_file $_source.pdf;; esac } function cleanup { local aux all ign="\($_ext\|,v\|~\)$" files # clean up! aux=${ftypes%->*} ! option a && [ "$aux" ] && eval rm -f "$_source.{$aux,zzz}" rm -f {fontsmpl,nfssfont,mproof}.* tmp* # list files! all="\($(echo $ftypes | tr -d '*' | sed 's/->/,/g' | \ sed 's/\(^,\|,$\)//;s/,/\\\|/g')\)$" if [ "$ftypes" ] && files=$(ls $_source.* | grep -v "$ign" | grep "$all"); then echo "${0##*/}: $PWD <-- "$files else echo "${0##*/}: no output" fi [ "$new_ff" ] && echo "${0##*/}: ${FORMATFILEDIR:-$PWD} <-- $myformatfile" # ftypes='aux,dvi->ps' --> # --> delete {aux,dvi} if requested and show {aux,dvi,ps} if found } function backup { function backup_file { declare -i n=$BACKUP_FILES cp $1 $1.0~ until [ -e $1.$n~ ]; do n=$((n-1)) done n=$((n+1)) declare -i i=$n while [ $i -gt 0 ]; do mv $1.$((i-1))~ $1.$i~ i=$((i-1)) done [ $n -gt $BACKUP_FILES ] && rm -f $1.$n~ } if [ "$USE_RCS" = 'yes' ] && type 'ci' &>/dev/null; then # call RCS echo "${0##*/}: RCS:"; ci -l $_source$_ext else # default back-up method [ "$USE_RCS" = 'yes' ] && \ error "Can't find RCS! Using default back-up procedure instead..." backup_file $_source$_ext echo "${0##*/}: $PWD <-- $_source$_ext.1~" fi } function terminate # log out procedure { cleanup option b && backup [ "$action" = 'watch' ] && read } # process options! while getopts $optionlist opt; do case $opt in P ) action=watch;; T ) action=quit;; v ) echo 'proof v1.2'; exit 0;; \? ) info; exit 1;; esac OPTS=$* done OPTS="${OPTS% *}" shift $(($OPTIND - 1)) # check syntax! [ -z "$1" ] && error 'Please specify your document!' halt ! echo $1 | grep '\(.mf\|.mp\|.tex\|.dvi\|.ps\|.pdf\)$' >/dev/null && \ error "Unknown file type!" halt [ "$action" != 'quit' ] && [ ! -e "$1" ] && error "Can't find file $1!" halt # go! case "$action" in quit ) kill -TERM $(pid "${0##*/}"'.*'-P'.*'"$1") >/dev/null 2>&1;; * ) # set shell variables! cd $(dirname $1) || exit 1 _ext=".${1##*.}" _source=$(basename $1 $_ext) current=/tmp/proof-$$ # preserves st_mtime # set signal trap! trap 'rm -f $current; terminate; exit 0' INT TERM # wait until file exists! [ ! -e "$1" ] && until [ -e $_source$_ext ]; do sleep 1; done view # view only? [ -z "$action" ] && { terminate; exit 0; } # watch! echo >$current while :; do until [ $_source$_ext -nt $current ]; do sleep 1 done view; echo >$current done;; esac