mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
Tim Peters writes:
I should have waited overnight <wink/sigh>. Nothing wrong with the one I sent, but I couldn't resist going on to add new -r1 / -r2 cmdline options for recreating the original files from ndiff's output. That's attached, if you're game! Us Windows guys don't usually have a sed sitting around <wink>.
This commit is contained in:
parent
a3433e89eb
commit
02ef28b9a9
1 changed files with 53 additions and 24 deletions
|
@ -1,17 +1,21 @@
|
||||||
#! /usr/bin/env python
|
#! /usr/bin/env python
|
||||||
|
|
||||||
# Module ndiff version 1.3.0
|
# Module ndiff version 1.4.0
|
||||||
# Released to the public domain 26-Mar-1999,
|
# Released to the public domain 27-Mar-1999,
|
||||||
# by Tim Peters (tim_one@email.msn.com).
|
# by Tim Peters (tim_one@email.msn.com).
|
||||||
|
|
||||||
# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
|
# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
|
||||||
|
|
||||||
"""ndiff [-q] file1 file2
|
"""ndiff [-q] file1 file2
|
||||||
|
or
|
||||||
|
ndiff (-r1 | -r2) < ndiff_output > file1_or_file2
|
||||||
|
|
||||||
Print a human-friendly file difference report to stdout. Both inter-
|
Print a human-friendly file difference report to stdout. Both inter-
|
||||||
and intra-line differences are noted.
|
and intra-line differences are noted. In the second form, recreate file1
|
||||||
|
(-r1) or file2 (-r2) on stdout, from an ndiff report on stdin.
|
||||||
|
|
||||||
If -q ("quiet") is not specified, the first two lines of output are
|
In the first form, if -q ("quiet") is not specified, the first two lines
|
||||||
|
of output are
|
||||||
|
|
||||||
-: file1
|
-: file1
|
||||||
+: file2
|
+: file2
|
||||||
|
@ -24,22 +28,22 @@ Each remaining line begins with a two-letter code:
|
||||||
"? " line not present in either input file
|
"? " line not present in either input file
|
||||||
|
|
||||||
Lines beginning with "? " attempt to guide the eye to intraline
|
Lines beginning with "? " attempt to guide the eye to intraline
|
||||||
differences, and were not present in either input file.
|
differences, and were not present in either input file. These lines can
|
||||||
|
be confusing if the source files contain tab characters.
|
||||||
|
|
||||||
The first file can be recovered by retaining only lines that begin with
|
The first file can be recovered by retaining only lines that begin with
|
||||||
" " or "- ", and deleting those 2-character prefixes.
|
" " or "- ", and deleting those 2-character prefixes; use ndiff with -r1.
|
||||||
|
|
||||||
The second file can be recovered similarly, but by retaining only " "
|
The second file can be recovered similarly, but by retaining only " "
|
||||||
and "+ " lines. On Unix, the second file can be recovered by piping the
|
and "+ " lines; use ndiff with -r2; or, on Unix, the second file can be
|
||||||
output through
|
recovered by piping the output through
|
||||||
|
|
||||||
sed -n '/^[+ ] /s/^..//p'
|
sed -n '/^[+ ] /s/^..//p'
|
||||||
Modifications to recover the first file are left as an exercise for
|
|
||||||
the reader.
|
|
||||||
|
|
||||||
See module comments for details and programmatic interface.
|
See module comments for details and programmatic interface.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = 1, 3, 0
|
__version__ = 1, 4, 0
|
||||||
|
|
||||||
# SequenceMatcher tries to compute a "human-friendly diff" between
|
# SequenceMatcher tries to compute a "human-friendly diff" between
|
||||||
# two sequences (chiefly picturing a file as a sequence of lines,
|
# two sequences (chiefly picturing a file as a sequence of lines,
|
||||||
|
@ -324,7 +328,7 @@ class SequenceMatcher:
|
||||||
if k:
|
if k:
|
||||||
if alo < i and blo < j:
|
if alo < i and blo < j:
|
||||||
self.__helper(alo, i, blo, j, answer)
|
self.__helper(alo, i, blo, j, answer)
|
||||||
answer.append( x )
|
answer.append(x)
|
||||||
if i+k < ahi and j+k < bhi:
|
if i+k < ahi and j+k < bhi:
|
||||||
self.__helper(i+k, ahi, j+k, bhi, answer)
|
self.__helper(i+k, ahi, j+k, bhi, answer)
|
||||||
|
|
||||||
|
@ -528,14 +532,20 @@ def fancy_helper(a, alo, ahi, b, blo, bhi):
|
||||||
elif blo < bhi:
|
elif blo < bhi:
|
||||||
dump('+', b, blo, bhi)
|
dump('+', b, blo, bhi)
|
||||||
|
|
||||||
|
def fail(msg):
|
||||||
|
import sys
|
||||||
|
out = sys.stderr.write
|
||||||
|
out(msg + "\n\n")
|
||||||
|
out(__doc__)
|
||||||
|
return 0
|
||||||
|
|
||||||
# open a file & return the file object; gripe and return 0 if it
|
# open a file & return the file object; gripe and return 0 if it
|
||||||
# couldn't be opened
|
# couldn't be opened
|
||||||
def fopen(fname):
|
def fopen(fname):
|
||||||
try:
|
try:
|
||||||
return open(fname, 'r')
|
return open(fname, 'r')
|
||||||
except IOError, detail:
|
except IOError, detail:
|
||||||
print "couldn't open " + fname + ": " + str(detail)
|
return fail("couldn't open " + fname + ": " + str(detail))
|
||||||
return 0
|
|
||||||
|
|
||||||
# open two files & spray the diff to stdout; return false iff a problem
|
# open two files & spray the diff to stdout; return false iff a problem
|
||||||
def fcompare(f1name, f2name):
|
def fcompare(f1name, f2name):
|
||||||
|
@ -568,33 +578,52 @@ def fcompare(f1name, f2name):
|
||||||
def main(args):
|
def main(args):
|
||||||
import getopt
|
import getopt
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(args, "q")
|
opts, args = getopt.getopt(args, "qr:")
|
||||||
except getopt.error, detail:
|
except getopt.error, detail:
|
||||||
print str(detail)
|
return fail(str(detail))
|
||||||
print __doc__
|
|
||||||
return 0
|
|
||||||
noisy = 1
|
noisy = 1
|
||||||
|
qseen = rseen = 0
|
||||||
for opt, val in opts:
|
for opt, val in opts:
|
||||||
if opt == "-q":
|
if opt == "-q":
|
||||||
|
qseen = 1
|
||||||
noisy = 0
|
noisy = 0
|
||||||
|
elif opt == "-r":
|
||||||
|
rseen = 1
|
||||||
|
whichfile = val
|
||||||
|
if qseen and rseen:
|
||||||
|
return fail("can't specify both -q and -r")
|
||||||
|
if rseen:
|
||||||
|
if args:
|
||||||
|
return fail("no args allowed with -r option")
|
||||||
|
if whichfile in "12":
|
||||||
|
restore(whichfile)
|
||||||
|
return 1
|
||||||
|
return fail("-r value must be 1 or 2")
|
||||||
if len(args) != 2:
|
if len(args) != 2:
|
||||||
print 'need 2 args'
|
return fail("need 2 filename args")
|
||||||
print __doc__
|
|
||||||
return 0
|
|
||||||
f1name, f2name = args
|
f1name, f2name = args
|
||||||
if noisy:
|
if noisy:
|
||||||
print '-:', f1name
|
print '-:', f1name
|
||||||
print '+:', f2name
|
print '+:', f2name
|
||||||
return fcompare(f1name, f2name)
|
return fcompare(f1name, f2name)
|
||||||
|
|
||||||
|
def restore(which):
|
||||||
|
import sys
|
||||||
|
tag = {"1": "- ", "2": "+ "}[which]
|
||||||
|
prefixes = (" ", tag)
|
||||||
|
for line in sys.stdin.readlines():
|
||||||
|
if line[:2] in prefixes:
|
||||||
|
print line[2:],
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
args = sys.argv[1:]
|
args = sys.argv[1:]
|
||||||
if 1:
|
if "-profile" in args:
|
||||||
main(args)
|
|
||||||
else:
|
|
||||||
import profile, pstats
|
import profile, pstats
|
||||||
|
args.remove("-profile")
|
||||||
statf = "ndiff.pro"
|
statf = "ndiff.pro"
|
||||||
profile.run("main(args)", statf)
|
profile.run("main(args)", statf)
|
||||||
stats = pstats.Stats(statf)
|
stats = pstats.Stats(statf)
|
||||||
stats.strip_dirs().sort_stats('time').print_stats()
|
stats.strip_dirs().sort_stats('time').print_stats()
|
||||||
|
else:
|
||||||
|
main(args)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue