On Fri, Jan 10, 2003 at 10:51:51AM +0100, Jean-Marc Lasgouttes wrote:
> David> Does anyone know of a way of comparing two versions of a text
> David> and producing an output to show which changes have been made.
> 
> Some stupid tricks for finding difference (if you are lucky) can be
> found at
> http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg16018.html

A slightly less stupid solution is to use the attached script,
which requires installing dvipost from
  http://efeu.cybertec.at/dist/dvipost-1.0.tar.gz
#!/usr/bin/env python
# Copyright (C) 2002 Dekel Tsur <[EMAIL PROTECTED]>
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

version = "0.1"

import getopt,os,sys,re,string

add_begin = "\\changestart"
add_end = "\\changeend"
del_begin = "\\overstrikeon"
del_end = "\\overstrikeoff"

math_rexp = r"\$|\\\[|\\\]|\\(?:begin|end)\{(?:equation|eqnarray|align)\*?\}"

def preprocess(from_file, to_file):
    result = []

    if from_file[-3:] == "lyx":
        os.system("lyx -e latex " + from_file)
        from_file2 = from_file[:-3]+"tex"
    else:
        from_file2 = from_file

    fh = open(from_file2)
    lines = fh.readlines()
    fh.close()
    if from_file[-3:] == "lyx":
        os.remove(from_file2)

    preamble = 1
    text = ""
    for line in lines:
        if preamble:
            if re.search(r"\\begin{document}", line):
                preamble = 0
            else:
                result.append(line)
                continue
        # Remove comments
        line = re.sub(r"([^\\]|^)%.*", r"\1%", line)
        # Put %\n before commands
        line = re.sub(r"(\\(\w+){)", "%\n\\1", line)
        # Put %\n after \emph{
        line = re.sub(r"(\\(emph|textbf){)", "\\1%\n", line)
        text = text + line

    x = re.split("("+math_rexp+")", text)
    math_mode = 0
    for i in xrange(len(x)):
        y = x[i]
        if i % 2:
            math_mode = not math_mode
            if math_mode:
                x[i] = x[i]+" "
            else:
                x[i] = " "+x[i]
        elif math_mode:
            x[i] = re.sub(r"([^\\_^])([=<>+-,()}])", r"\1 \2 ", x[i])
            x[i] = re.sub(r"([^\\])(\\)", r"\1 \2", x[i])

    text = string.join(x, "")
    fh = open(to_file, 'w')
    fh.write(text)
    fh.close()
    return result

def usage():
    print """Usage: ldiff [options] [<file1>] <file2>
Show the differences between two latex/lyx files.
ldiff <file1> <file2> to compare two files.
tdiff <file> to compare <file> with the most recent version checked into CVS.
ldiff -r<rev> <file> to compare <file> with revision <rev> of <file>.
ldiff -r<rev1> -r<rev2> <file> to compare revision <rev1> with revision <rev2>.

Options:
    -h, --help                  This information
    -v, --version               Output version information
    -d, --deleted               Show deleted text
    -b, --nocolor               Do not colorize the changed text
    -l, --latex                 Produce only the latex file
    -s, --separation            Separation between change bars and text
                                (default value = -50)"""


_options = ["help", "version", "deleted", "nocolor", "latex", "separation="]
try:
    opts, args = getopt.getopt(sys.argv[1:], "hvdbkls:r:", _options)
except getopt.error:
    usage()
    sys.exit(1)

rev = ""
deleted = 0
colorize = 1
onlylatex = 0
sep = "-50"
for o, a in opts:
    if o in ("-h", "--help"):
        usage()
        sys.exit()
    if o in ("-v", "--version"):
        print "ldiff, version "+version
        sys.exit()
    if o in ("-d", "--deleted"):
        deleted = 1
    if o in ("-b", "--nocolor"):
        colorize = 0
    if o in ("-l", "--latex"):
        onlylatex = 1  
    if o in ("-s", "--separation"):
        sep = a
    if o == "-r":
        rev = rev + " -r" + a

if len(args) not in [1,2]:
    usage()
    sys.exit(1)

file1 = "ldiff_tmp1.tex"
file2 = "ldiff_tmp2.tex"
if len(args) == 2:
    preprocess(args[0], file1)
    file = args[1]
else:
    file0 = file1[:-3]+args[0][-3:]
    os.system("cvs diff %s -u %s | patch -R -o%s" % (rev, args[0], file0))
    preprocess(file0, file1)
    if file0[-3:] == "lyx":
        os.remove(file0)
    file = args[0]

preamble_lines = preprocess(file, file2)

if deleted:
    wdiffopts = "-w'%s{}' -x'%s{}'" % (del_begin, del_end)
else:
    wdiffopts = "-1"
wdiffopts = wdiffopts + " -y'%s{}' -z'%s{}'" % (add_begin, add_end)
fh = os.popen("wdiff %s %s %s" % (wdiffopts, file1, file2))
lines = fh.readlines()
fh.close()
os.remove(file1)
os.remove(file2)

filebase = file[:-4]+"-diff"
filetex = filebase+".tex"

fh = open(filetex, 'w')
for line in preamble_lines:
    fh.write(line)

color = "Gray"
if deleted:
    color = "Blue"

fh.write(r"""
\usepackage{dvipost}
\dvipost{cbexp=0pt}
\dvipost{cbsep=%spt}
""" % sep)
if colorize:
    fh.write(r"""
\dvipost{cbstart color push %s}
\dvipost{cbend color pop}
\dvipost{osstart color push Red}
\dvipost{osend color pop}
""" % color)

text = ""
for line in lines:
    line = re.sub(r"\\maketitle", "\\maketitle\\"+add_end, line)
    line = re.sub(r"%(.*)", r"\1%", line)
    text = text+line

x = re.split("("+math_rexp+"|\\"+del_begin+"\\{\\}|\\"+del_end+"\\{\\})", text)
math_mode = 0
math_mode_save = 0
os_mode = 0
for i in xrange(len(x)):
    y = x[i]
    if i % 2:
        if y == del_begin+"{}":
            os_mode = 1
            math_mode_save = math_mode
        elif y == del_end+"{}":
            os_mode = 0
            if math_mode_save != math_mode:
                x[i] = " $"+x[i]
                math_mode = math_mode_save
        else:
            math_mode = not math_mode
    elif os_mode:
        if math_mode:
            if string.count(x[i], '{') != string.count(x[i], '}'):
                x[i] = re.sub(r"\{|\}", "", x[i])
        else:
            x[i] = re.sub(r"\\\w+|\{|\}", "", x[i])

text = string.join(x, "")

fh.write(text)
fh.close()

if onlylatex:
    sys.exit()

filedvi = filebase+".dvi"
fileps = filebase+".ps"

os.system("latex "+filetex)
os.system("bibtex "+filebase)
os.system("latex "+filetex)
os.system("latex "+filetex)
os.system("ltxpost %s %s" % (filedvi, filedvi))
os.system("dvips %s -o %s" % (filedvi, fileps))
os.rename(fileps, "__"+fileps)
os.system("rm %s.*" % filebase)
os.rename("__"+fileps, fileps)

Reply via email to