#! /bin/bash

# This converts a unified diff between text files into a unified-like
# diff that displays word-by-word changes.  It's useful for viewing
# textual changes in a patch to a text file in which paragraphs were
# refilled.

# Copyright 2006, 2007  Alexandre Oliva <lxoliva@fsfla.org>

# 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 3 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, see <http://www.gnu.org/licenses/>.


tempfile=
case $# in
0|1)
   if test -z "$1" || test ! -f "$1"; then
     trap 'status=$?; rm -f "$tempfile"; (exit $status); exit' 0 1 2 15
     tempfile=$(mktemp)
     cat ${1+"$1"} > "$tempfile"
     set -- "$tempfile"
   fi
   set -- "$1"
   ;;
*) echo Too many arguments >&2;
   echo Usage: $(basename $0) "[unidiff.patch]"
   exit 1;;
esac

diff -U8 <(sed -n '0,/^@@/d; s,^[- ],,p; s,^@@.*,,p' "$1" |
		sed 's,[ 	][ 	]*,\n,g') \
	 <(sed -n '0,/^@@/d; s,^[+ ],,p; s,^@@.*,,p' "$1" |
		sed 's,[ 	][ 	]*,\n,g') |
sed -n '/^@@/,$p' | awk '
/^@@/ { print ""; print "@@@"; state = "@"; next; }
/^[ ]./ {
  if (state != "=") { state = "="; print ""; print state; }
  gsub (/^[ ]/, ""); print; next; }
/^[-]./ {
  if (state != "-") { state = "-"; print ""; print state; }
  gsub (/^[-]/, ""); print; next; }
/^[+]./ {
  if (state != "+") { state = "+"; print ""; print state; }
  gsub (/^[+]/, ""); print; next; }
{ next; }
' | fmt | sed '/^$/d; s,^= ,  ,'

exit 0
