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.