Colorized Word Diffs

I’ve been finding myself doing a lot for copy and tech editting. I needed a way to annotate a PDF based on the changes I’d made to our markdown source. Trying to eyeball this was difficult, and I checked if there was a way to do word-by-word diffs based on SVN output. Remember, SVN’s diff command will show line-by-line differences. But there is a Perl script wdiff that will show you word by word diffs. With a bash alias, you can pipe svn output to it and see what’s been added/removed more clearly.  Once you install wdiff, either from source or via your distributions package manager, create an alias (I use bash) that will colorize its output:

alias cwdiff="wdiff -n -w $'\033[30;41m' -x $'\033[0m' -y $'\033[30;42m' -z $'\033[0m'"

wdiff compares two files by default but in can also parse the output of a diff file. By piping svn diff to it, you can see the changes word for word. In the example below, I’m reviewing the changes made by a specific commit and using less to page the output, the -r flag keeps the colors intact.

svn diff -r 267 -x -w 05.chapter.markdown | cwdiff -d | less -r

Words that were deleted will be in red, additions are in green.

color-diff

 Update:

Git has this behavior built in using:

git diff --color-words

Also, if you need to share your changes with a designer (who maybe needs to update a PDF…), with this ansi2html script from pixelbeat.org, you can generate HTML output showing your changes. I found that its useful to run the generated HTML through fold so that the lines wrap if you email it to someone.

svn diff foo.markdown | cwdiff -d | ~/bin/ansi2html.sh | fold -s > foo-updates.html

Finally, you can wrap all this functionality into a simple bash script that you can save anywhere. Pipe it the output of a svn diff or diff command, and get nice HTML as a result. It assumes ansi2html is somewhere in your executables $PATH.

#!/bin/bash
# take diff input (from svn diff too), colorize it, convert it to html

cat - | wdiff -n -w $'\033[30;41m' -x $'\033[0m' -y $'\033[30;42m' -z $'\033[0m' -d \
| ansi2html.sh | fold -s