#!/bin/sh # Gadget to take two LaTeX files and produce a third which # has changebars highlighting the difference between them. # # Version 1.2 # Author: # Don Ward, Careful Computing (don@careful.co.uk) # v1.0 April 1989 # v1.1 Feb 93 Amended to use changebar.sty (v3.0) and dvips # v1.2 Aug 95 Added support for LaTeX209/LaTeX2e # Added RCS support to retrive old files CMD=`basename $0` SED=sed RM="rm -f" DIFF=diff ED=ed AWK=awk GREP=grep MV=mv CAT=cat MKDIR=mkdir CO="co" TMPFILE=/tmp/$CMD.$$ SED_CMD_FILE=$TMPFILE.sed usage() { $CAT << _END_ Usage: $CMD [-hgG] [-d dir] old new [output] default output is stdout $CMD [-hgG] [-d dir] old new file on stdin, output on stdout $CMD [-hgG] -d dir -r rev files old file retrieved using RCS Gadget to take two LaTeX files and produce a third which has changebars highlighting the difference between them. Changebars are inserted for differences after '\begin{document}'. Feature: \`new' can not be named \`-'. Options are: -d dir : Write the output to file \`dir/new', if \`new' is given or to file \`dir/old'. If \`dir' does not exist, it is created. If \`output' is given, it is discarded. -r rev : If the LaTeX \`files' are kept under control of the Revision Control System RCS, the old files of the revision \`rev' can be retrived. \`rev' is specified using the RCS conventions. This option must be used together with the \`-d dir' option. \`files' must be a nonempty list of files. -h : Print this info text. -g : Print some debugging info. -G : Even more debug info. Version 1.2: August 3. 1995 _END_ exit 1 } # parse options and arguments DEBUG="NO" DIR= REV= # process options while getopts d:r:gGh i $* do case $i in d ) DIR=$OPTARG;; r ) REV=$OPTARG;; g ) DEBUG="YES" ;; G ) set -x; DEBUG="YES";; h | \ * ) usage ;; esac done shift `expr $OPTIND - 1` case $# in 1 ) OLD=$1; NEW="-"; OUT="" ;; 2 ) OLD=$1; NEW=$2; OUT="" ;; 3 ) OLD=$1; NEW=$2; OUT="$3" ;; * ) usage ;; esac # check correct options if [ ! -z "$DIR" ] then [ -d $DIR ] || $MKDIR $DIR fi if [ ! -z "$REV" ] then [ -z "$DIR" ] && usage FILES=$* else FILES=$NEW fi # do the work for NEW in $FILES do if [ ! -z "$DIR" ] then if [ $NEW = "-" ] then OUT=$DIR/$OLD else OUT=$DIR/$NEW fi fi if [ ! -z "$REV" ] then OLD=${TMPFILE}.old $CO -p"$REV" -q $NEW > $OLD fi [ $DEBUG = "YES" ] && echo "OLD=\`$OLD' NEW=\`$NEW' OUT=\`$OUT'" # gather some info about the file # Since we have for sure only the name of the OLD file, ... $GREP "^\\\\begin{document}" $OLD > /dev/null if [ $? -eq 0 ] then [ $DEBUG = "YES" ] && echo "contains a \\begin{document}" HAS_BEGIN_DOC="YES" else [ $DEBUG = "YES" ] && echo "contains no \\begin{document}" HAS_BEGIN_DOC="NO" fi # Method to do the work: # 1 Use diff to get an ed script to go from file1 to file2. # 2 Breath on it a bit (with sed) to insert changebar commands. # 3 Apply modified ed script to produce (nearly) the output. # 4 Use awk to insert the changebars option into the \documentstyle # and to handle changebar commands inside verbatim environments. # 5 Remove changebars before \begin{document} with sed # SED commands to edit ED commands to edit old file $CAT > $SED_CMD_FILE <<\_END_ /^\.$/i\ \\cbend{}% /^[0-9][0-9]*[ac]$/a\ \\cbstart{}% /^[0-9][0-9]*,[0-9][0-9]*[ac]$/a\ \\cbstart{}% /^[0-9][0-9]*d$/a\ i\ \\cbdelete{}%\ . /^[0-9][0-9]*,[0-9][0-9]*d$/a\ i\ \\cbdelete{}%\ . _END_ # note DIFF accepts `-' as stdin $DIFF -b -e $OLD $NEW | \ ( $SED -f $SED_CMD_FILE ; echo w ${TMPFILE}.1 ; echo q ) | \ $ED - $OLD # AWK commands to insert Changebars style and to protect # changebar commands in verbatim environments # and to tell what driver is in use; we assume the `dvips' driver $AWK ' BEGIN {kind=""; # we saw now \documentXXX[]{} } /^\\documentstyle/{ kind = "209"; if (index($0, "changebar") == 0 ) { opts = index($0, "[") if (opts > 0) printf "%schangebar,%s\n",substr($0,1,opts),substr($0,opts+1) else printf "\\documentstyle[changebar]%s\n", substr($0,15) next } } /^\\documentclass/{ kind = "2e"; printf "%s\n", $0 printf "\\usepackage[dvips]{changebar}\n" next } /\\begin{document}/ {if (kind == "209" ) {print "\\driver{dvips}"}} /\\begin{verbatim}/{++nesting} /\\end{verbatim}/{--nesting} /\\cbstart{}%|\\cbend{}%|\cbdelete{}%/ { if ( nesting > 0) { # changebar command in a verbatim environment: Temporarily exit, # do the changebar command and reenter. # # The obvious ( printf "\\end{verbatim}%s\\begin{verbatim} , $0 ) # leaves too much vertical space around the changed line(s). # The following magic seeems to work # print "\\end{verbatim}\\nointerlineskip" print "\\vskip -\\ht\\strutbox\\vskip -\\ht\\strutbox" printf "\\vbox to 0pt{\\vskip \\ht\\strutbox%s\\vss}\n", $0 print "\\begin{verbatim}" next } } { print $0 } ' ${TMPFILE}.1 > ${TMPFILE}.2 # if a \begin{document} is contained in the file, # remove the changebar commands before them if [ $HAS_BEGIN_DOC = "YES" ] then SED_CMD="1,/\\\\begin{document}/s/\(\\\\cb[sed][tne][adl][^{}]*{}%\)$/%%\1/" $SED "$SED_CMD" ${TMPFILE}.2 > ${TMPFILE}.3 else $CAT ${TMPFILE}.2 > ${TMPFILE}.3 fi if [ -z "$OUT" ] then $CAT ${TMPFILE}.3 else $MV ${TMPFILE}.3 $OUT fi done [ $DEBUG = "NO" ] && $RM ${TMPFILE}.* ###############################################################