#! /usr/local/bin/gawk -f # NAME # # idiff -- interactive diff # # USAGE # # idiff file1 file2 -- interactively merge file differences # # DESCRIPTION # # idiff takes two files file1 and file2, diffs them, and presents # the difference to the user interactively. At each difference, # the user may accept the text from file1 by responding <, or # accept the text from file2 by responding >, or edit the difference # by responding e (in which case whatever the user saves from the # editor is entered into the output file), or execute a command # by typing !cmd, in which case the user must then respond when # the prompt is repeated. The assembled output with the selected # differences is placed in file idiff.out. # # EXAMPLE # # $ cat file1 # This is # a test # of # your # skill # and comprehension. # $ cat file2 # This is # not a test # of # our # ability. # $ diff file1 file2 # 2c2 # < a test # --- # > not a test # 4,6d4,5 # < your # < skill # < and comprehension. # --- # > our # > ability. # $ idiff file1 file2 # 2c2 # < a test # --- # > not a test # ? > # 4,6c4,5 # < your # < skill # < and comprehension. # --- # > our # > ability. # ? < # $ cat idiff.out # This is # not a test # of # your # skill # and comprehension.\014 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) !~ /[> 0)) { print line > fout } }