Interactive Diff
July 12, 2019
Kernighan and Pike implemented idiff in about three pages of C; we use awk:
#! /usr/local/bin/gawk -f
BEGIN {
ed = ENVIRON["EDITOR"]; if (ed == "") { ed = "ed" }
outfile = "idiff.out"; tempfile = "idiff.tmp"; diffile = "idiff.dif"
file1 = ARGV[1]; file2 = ARGV[2]; ARGV[1] = ARGV[2] = ""
system("diff " file1 " " file2 " > " diffile)
nf1 = nf2 = 0
while (getline difline < diffile > 0) {
cmd = substr(difline, match(difline, /[acd]/), 1)
split(difline, linenums, cmd)
split(linenums[1], ones, ","); split(linenums[2], twos, ",")
from1 = ones[1]; to1 = ones[2] > 0 ? ones[2] : ones[1]
from2 = twos[1]; to2 = twos[2] > 0 ? twos[2] : twos[1]
nlines = to1-from1 + to2-from2 + 1
if (cmd == "a") { from1++ }
else if (cmd == "c") { nlines += 2 }
else if (cmd == "d") { from2++ }
print difline
while (nlines-- > 0) { getline difline < diffile; print difline } do { printf("? "); getline buf if (substr(buf, 1, 1) == ">") { nskip(file1, to1-nf1); ncopy(file2, to2-nf2, outfile) } else if (substr(buf, 1, 1) == "<") { nskip(file2, to2-nf2); ncopy(file1, to1-nf1, outfile) } else if (substr(buf, 1, 1) == "e") { ncopy(file1, from1-1-nf1, outfile) nskip(file2, from2-1-nf2) ncopy(file1, to1+1-from1, tempfile) print "---" > tempfile ncopy(file2, to2+1-from2, tempfile) close(tempfile) system(ed " " tempfile) ncopy(tempfile, -1, outfile) close(tempfile) } else if (substr(buf, 1, 1) == "!") { system(substr(buf, 2)); print "!" } else { print "Enter < or > or e or !cmd" } } while (substr(buf, 1, 1) !~ /[><e]/)
nf1 = to1; nf2 = to2
}
system("rm " tempfile " " diffile)
}
function nskip(fin, n, junk) {
while (n-- != 0) { getline junk < fin } }
function ncopy(fin, n, fout, line) {
while ((n-- != 0) && (getline line < fin > 0)) { print line > fout } }
Every time I use awk I am amazed at how it fits such a neat “sweet spot” in language design. It’s a small language, but very expressive. Automatic initialization of variables, field splitting, associative arrays, implicit conversion between strings and numbers, and the pattern/action paradigm combine to make a highly productive programming environment.
You can run the program at https://ideone.com/nI9CNB.