func PrintDiff(w io.Writer, v1, v2 types.Value, leftRight bool) (err error) {
	if !shouldDescend(v1, v2) {
		line(w, DEL, nil, v1)
		return line(w, ADD, nil, v2)
	}
	dChan := make(chan Difference, 16)
	stopChan := make(chan struct{})
	stopDiff := func() {
		close(stopChan)
		for range dChan {
		}
	}
	go func() {
		Diff(v1, v2, dChan, stopChan, leftRight)
		close(dChan)
	}()
	var lastParentPath types.Path
	wroteHdr := false
	firstTime := true
	for d := range dChan {
		parentPath := d.Path[:len(d.Path)-1]
		parentPathChanged := !parentPath.Equals(lastParentPath)
		lastParentPath = parentPath
		if parentPathChanged && wroteHdr {
			err = writeFooter(w, &wroteHdr)
		}
		if parentPathChanged || firstTime {
			firstTime = false
			err = writeHeader(w, parentPath, &wroteHdr)
		}
		lastPart := d.Path[len(d.Path)-1]
		parentEl := parentPath.Resolve(v1, nil)
		var key types.Value
		var pfunc printFunc = line
		switch parent := parentEl.(type) {
		case types.Map:
			if indexPath, ok := lastPart.(types.IndexPath); ok {
				key = indexPath.Index
			} else if hip, ok := lastPart.(types.HashIndexPath); ok {
				hip1 := hip
				hip1.IntoKey = true
				key = hip1.Resolve(parent, nil)
			} else {
				panic("unexpected Path type")
			}
		case types.Set:
		case types.Struct:
			key = types.String(lastPart.(types.FieldPath).Name)
			pfunc = field
		case types.List:
		}
		if d.OldValue != nil {
			err = pfunc(w, DEL, key, d.OldValue)
		}
		if d.NewValue != nil {
			err = pfunc(w, ADD, key, d.NewValue)
		}
		if err != nil {
			stopDiff()
			break
		}
	}
	err = writeFooter(w, &wroteHdr)
	return
}
PrintDiff writes a textual reprensentation of the diff from |v1| to |v2|
to |w|. If |leftRight| is true then the left-right diff is used for ordered
sequences - see Diff vs DiffLeftRight in Set and Map.
package diff
import (
	"io"
	"github.com/attic-labs/noms/go/types"
	"github.com/attic-labs/noms/go/util/writers"
	"github.com/dustin/go-humanize"
)
type prefixOp string
const (
	ADD = "+   "
	DEL = "-   "
)
type (
	printFunc func(w io.Writer, op prefixOp, key, val types.Value) error
)