refresh!
diff --git a/Readme b/Readme
new file mode 100644
index 0000000..c589fc6
--- /dev/null
+++ b/Readme
@@ -0,0 +1,9 @@
+package pretty
+
+    import "github.com/kr/pretty"
+
+    Package pretty provides pretty-printing for Go values.
+
+Documentation
+
+    http://godoc.org/github.com/kr/pretty
diff --git a/Readme.md b/Readme.md
deleted file mode 100644
index e8ec9b4..0000000
--- a/Readme.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# pretty
-
-Package pretty provides pretty-printing for Go values. This is useful during
-debugging, to avoid wrapping long output lines in the terminal.
-
-It provides a function, Formatter, that can be used with any function that
-accepts a format string. For example,
-
-    type LongTypeName struct {
-        longFieldName, otherLongFieldName int
-    }
-    func TestFoo(t *testing.T) {
-        var x []LongTypeName{{1, 2}, {3, 4}, {5, 6}}
-        t.Errorf("%# v", Formatter(x))
-    }
-
-This package also provides a convenience wrapper for each function in
-package fmt that takes a format string.
-
-
-## Documentation
-
-See [GoDoc](http://godoc.org/github.com/kr/pretty) for automatic documentation.
-
-
-## Installation
-
-    $ go get github.com/kr/pretty
-
-then
-
-    import "github.com/kr/pretty"
diff --git a/diff_test.go b/diff_test.go
index c2e5696..02d1953 100644
--- a/diff_test.go
+++ b/diff_test.go
@@ -30,38 +30,34 @@
 	{S{S: new(S)}, S{S: &S{A: 1}}, []string{`S.A: 0 != 1`}},
 	{S{}, S{I: 0}, []string{`I: nil != 0`}},
 	{S{I: 1}, S{I: "x"}, []string{`I: int != string`}},
-	{S{}, S{C: []int{1}}, []string{`C: []int{} != []int{1}`}},
+	{S{}, S{C: []int{1}}, []string{`C: []int(nil) != []int{1}`}},
+	{S{C: []int{}}, S{C: []int{1}}, []string{`C: []int{} != []int{1}`}},
 	{S{}, S{A: 1, S: new(S)}, []string{`A: 0 != 1`, `S: nil != &{0 <nil> <nil> []}`}},
 }
 
-
 func TestDiff(t *testing.T) {
 	for _, tt := range diffs {
 		got := Diff(tt.a, tt.b)
-		if len(got) != len(tt.exp) {
+		eq := len(got) == len(tt.exp)
+		if eq {
+			for i := range got {
+				eq = eq && got[i] == tt.exp[i]
+			}
+		}
+		if !eq {
 			t.Errorf("diffing % #v", tt.a)
 			t.Errorf("with    % #v", tt.b)
 			diffdiff(t, got, tt.exp)
 			continue
 		}
-		for i := range got {
-			if got[i] != tt.exp[i] {
-				t.Errorf("diffing % #v", tt.a)
-				t.Errorf("with    % #v", tt.b)
-				diffdiff(t, got, tt.exp)
-				break
-			}
-		}
 	}
 }
 
-
 func diffdiff(t *testing.T, got, exp []string) {
 	minus(t, "unexpected:", got, exp)
 	minus(t, "missing:", exp, got)
 }
 
-
 func minus(t *testing.T, s string, a, b []string) {
 	var i, j int
 	for i = 0; i < len(a); i++ {
diff --git a/example_test.go b/example_test.go
new file mode 100644
index 0000000..ecf40f3
--- /dev/null
+++ b/example_test.go
@@ -0,0 +1,20 @@
+package pretty_test
+
+import (
+	"fmt"
+	"github.com/kr/pretty"
+)
+
+func Example() {
+	type myType struct {
+		a, b int
+	}
+	var x = []myType{{1, 2}, {3, 4}, {5, 6}}
+	fmt.Printf("%# v", pretty.Formatter(x))
+	// output:
+	// []pretty_test.myType{
+	//     {a:1, b:2},
+	//     {a:3, b:4},
+	//     {a:5, b:6},
+	// }
+}
diff --git a/formatter.go b/formatter.go
index 23111ad..77a9f18 100644
--- a/formatter.go
+++ b/formatter.go
@@ -2,26 +2,19 @@
 
 import (
 	"fmt"
+	"github.com/kr/text"
 	"io"
 	"reflect"
+	"strconv"
+	"text/tabwriter"
 )
 
 const (
 	limit = 50
 )
 
-var (
-	commaLFBytes     = []byte(",\n")
-	curlyBytes       = []byte("{}")
-	openCurlyLFBytes = []byte("{\n")
-	spacePlusLFBytes = []byte(" +\n")
-)
-
 type formatter struct {
-	d int
 	x interface{}
-
-	omit bool
 }
 
 // Formatter makes a wrapper, f, that will format x as go source with line
@@ -60,136 +53,231 @@
 
 func (fo formatter) Format(f fmt.State, c rune) {
 	if c == 'v' && f.Flag('#') && f.Flag(' ') {
-		fo.format(f)
+		w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0)
+		p := &printer{tw: w, Writer: w}
+		p.printValue(reflect.ValueOf(fo.x), true)
+		w.Flush()
 		return
 	}
 	fo.passThrough(f, c)
 }
 
-func (fo formatter) format(w io.Writer) {
-	v := reflect.ValueOf(fo.x)
+type printer struct {
+	io.Writer
+	tw *tabwriter.Writer
+}
+
+func (p *printer) indent() *printer {
+	q := *p
+	q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0)
+	q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'})
+	return &q
+}
+
+func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) {
+	if showType {
+		io.WriteString(p, v.Type().String())
+		fmt.Fprintf(p, "(%#v)", x)
+	} else {
+		fmt.Fprintf(p, "%#v", x)
+	}
+}
+
+func (p *printer) printValue(v reflect.Value, showType bool) {
 	switch v.Kind() {
+	case reflect.Bool:
+		p.printInline(v, v.Bool(), showType)
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p.printInline(v, v.Int(), showType)
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p.printInline(v, v.Uint(), showType)
+	case reflect.Float32, reflect.Float64:
+		p.printInline(v, v.Float(), showType)
+	case reflect.Complex64, reflect.Complex128:
+		fmt.Fprintf(p, "%#v", v.Complex())
 	case reflect.String:
-		lim := limit - 8*fo.d
-		s := v.String()
-		z := len(s)
-		n := (z + lim - 1) / lim
-		if n < 1 {
-			n = 1 // empty string still produces output
+		p.fmtString(v.String())
+	case reflect.Map:
+		t := v.Type()
+		if showType {
+			io.WriteString(p, t.String())
 		}
-		sep := append(spacePlusLFBytes, make([]byte, fo.d)...)
-		for j := 0; j < fo.d; j++ {
-			sep[3+j] = '\t'
-		}
-		for i := 0; i < n; i++ {
-			if i > 0 {
-				w.Write(sep)
+		writeByte(p, '{')
+		if nonzero(v) {
+			expand := !canInline(v.Type())
+			pp := p
+			if expand {
+				writeByte(p, '\n')
+				pp = p.indent()
 			}
-			l, h := i*lim, (i+1)*lim
-			if h > z {
-				h = z
+			keys := v.MapKeys()
+			for i := 0; i < v.Len(); i++ {
+				showTypeInStruct := true
+				k := keys[i]
+				mv := v.MapIndex(k)
+				pp.printValue(k, false)
+				writeByte(pp, ':')
+				if expand {
+					writeByte(pp, '\t')
+				}
+				showTypeInStruct = t.Elem().Kind() == reflect.Interface
+				pp.printValue(mv, showTypeInStruct)
+				if expand {
+					io.WriteString(pp, ",\n")
+				} else if i < v.Len()-1 {
+					io.WriteString(pp, ", ")
+				}
 			}
-			fmt.Fprintf(w, "%#v", s[l:h])
+			if expand {
+				pp.tw.Flush()
+			}
 		}
-		return
+		writeByte(p, '}')
+	case reflect.Struct:
+		t := v.Type()
+		if showType {
+			io.WriteString(p, t.String())
+		}
+		writeByte(p, '{')
+		if nonzero(v) {
+			expand := !canInline(v.Type())
+			pp := p
+			if expand {
+				writeByte(p, '\n')
+				pp = p.indent()
+			}
+			for i := 0; i < v.NumField(); i++ {
+				showTypeInStruct := true
+				if f := t.Field(i); f.Name != "" {
+					io.WriteString(pp, f.Name)
+					writeByte(pp, ':')
+					if expand {
+						writeByte(pp, '\t')
+					}
+					showTypeInStruct = f.Type.Kind() == reflect.Interface
+				}
+				pp.printValue(getField(v, i), showTypeInStruct)
+				if expand {
+					io.WriteString(pp, ",\n")
+				} else if i < v.NumField()-1 {
+					io.WriteString(pp, ", ")
+				}
+			}
+			if expand {
+				pp.tw.Flush()
+			}
+		}
+		writeByte(p, '}')
+	case reflect.Interface:
+		switch e := v.Elem(); {
+		case e.Kind() == reflect.Invalid:
+			io.WriteString(p, "nil")
+		case e.IsValid():
+			p.printValue(e, showType)
+		default:
+			io.WriteString(p, v.Type().String())
+			io.WriteString(p, "(nil)")
+		}
+	case reflect.Array, reflect.Slice:
+		t := v.Type()
+		io.WriteString(p, t.String())
+		writeByte(p, '{')
+		expand := !canInline(v.Type())
+		pp := p
+		if expand {
+			writeByte(p, '\n')
+			pp = p.indent()
+		}
+		for i := 0; i < v.Len(); i++ {
+			showTypeInSlice := t.Elem().Kind() == reflect.Interface
+			pp.printValue(v.Index(i), showTypeInSlice)
+			if expand {
+				io.WriteString(pp, ",\n")
+			} else if i < v.Len()-1 {
+				io.WriteString(pp, ", ")
+			}
+		}
+		if expand {
+			pp.tw.Flush()
+		}
+		writeByte(p, '}')
 	case reflect.Ptr:
 		e := v.Elem()
 		if !e.IsValid() {
-			fmt.Fprintf(w, "%#v", fo.x)
+			writeByte(p, '(')
+			io.WriteString(p, v.Type().String())
+			io.WriteString(p, ")(nil)")
 		} else {
-			writeByte(w, '&')
-			if e.CanInterface() {
-				fmt.Fprintf(w, "%# v", formatter{d: fo.d, x: e.Interface()})
-			} else {
-				fmt.Fprint(w, e.String())
-			}
+			writeByte(p, '&')
+			p.printValue(e, true)
 		}
-	case reflect.Slice:
-		s := fmt.Sprintf("%#v", fo.x)
-		if len(s) < limit {
-			io.WriteString(w, s)
-			return
+	case reflect.Chan:
+		x := v.Pointer()
+		if showType {
+			writeByte(p, '(')
+			io.WriteString(p, v.Type().String())
+			fmt.Fprintf(p, ")(%#v)", x)
+		} else {
+			fmt.Fprintf(p, "%#v", x)
 		}
-
-		t := v.Type()
-
-		io.WriteString(w, reflect.TypeOf(fo.x).String())
-		w.Write(openCurlyLFBytes)
-		for i := 0; i < v.Len(); i++ {
-			for j := 0; j < fo.d+1; j++ {
-				writeByte(w, '\t')
-			}
-			if v.Index(i).CanInterface() {
-				inner := formatter{d: fo.d + 1, x: v.Index(i).Interface(), omit: t.Elem().Kind() != reflect.Interface}
-				fmt.Fprintf(w, "%# v", inner)
-			} else {
-				fmt.Fprint(w, v.Index(i).String())
-			}
-			w.Write(commaLFBytes)
-		}
-		for j := 0; j < fo.d; j++ {
-			writeByte(w, '\t')
-		}
-		writeByte(w, '}')
-	case reflect.Struct:
-		t := v.Type()
-		if tryDeepEqual(reflect.Zero(t).Interface(), fo.x) {
-			if !fo.omit {
-				io.WriteString(w, t.String())
-			}
-			w.Write(curlyBytes)
-			return
-		}
-
-		s := fmt.Sprintf("%#v", fo.x)
-		if fo.omit {
-			s = s[len(t.String()):]
-		}
-		if len(s) < limit {
-			io.WriteString(w, s)
-			return
-		}
-
-		if !fo.omit {
-			io.WriteString(w, t.String())
-		}
-		w.Write(openCurlyLFBytes)
-		var max int
-		for i := 0; i < v.NumField(); i++ {
-			if v := t.Field(i); v.Name != "" {
-				if len(v.Name)+2 > max {
-					max = len(v.Name) + 2
-				}
-			}
-		}
-		for i := 0; i < v.NumField(); i++ {
-			if f := t.Field(i); f.Name != "" {
-				for j := 0; j < fo.d+1; j++ {
-					writeByte(w, '\t')
-				}
-				io.WriteString(w, f.Name)
-				writeByte(w, ':')
-				for j := len(f.Name) + 1; j < max; j++ {
-					writeByte(w, ' ')
-				}
-				if v.Field(i).CanInterface() {
-					inner := formatter{d: fo.d + 1, x: v.Field(i).Interface()}
-					fmt.Fprintf(w, "%# v", inner)
-				} else {
-					io.WriteString(w, v.Field(i).String())
-				}
-				w.Write(commaLFBytes)
-			}
-		}
-		for j := 0; j < fo.d; j++ {
-			writeByte(w, '\t')
-		}
-		writeByte(w, '}')
+	case reflect.Func:
+		io.WriteString(p, v.Type().String())
+		io.WriteString(p, " {...}")
+	case reflect.UnsafePointer:
+		p.printInline(v, v.Pointer(), showType)
 	default:
-		fmt.Fprintf(w, "%#v", fo.x)
+		io.WriteString(p, "(UNKNOWN)")
 	}
 }
 
+func canInline(t reflect.Type) bool {
+	switch t.Kind() {
+	case reflect.Map:
+		return !canExpand(t.Elem())
+	case reflect.Struct:
+		for i := 0; i < t.NumField(); i++ {
+			if canExpand(t.Field(i).Type) {
+				return false
+			}
+		}
+		return true
+	case reflect.Interface:
+		return false
+	case reflect.Array, reflect.Slice:
+		return !canExpand(t.Elem())
+	case reflect.Ptr:
+		return false
+	case reflect.Chan, reflect.Func, reflect.UnsafePointer:
+		return false
+	}
+	return true
+}
+
+func canExpand(t reflect.Type) bool {
+	switch t.Kind() {
+	case reflect.String, reflect.Map, reflect.Struct,
+		reflect.Interface, reflect.Array, reflect.Slice,
+		reflect.Ptr:
+		return true
+	}
+	return false
+}
+
+func (p *printer) fmtString(s string) {
+	const segSize = 30
+	y, c := 0, 0
+	for i := range s {
+		if c > segSize {
+			q := strconv.Quote(s[y:][:c])
+			io.WriteString(p, q)
+			io.WriteString(p, " +\n\t")
+			y, c = i, 0
+		}
+		c++
+	}
+	fmt.Fprintf(p, "%#v", s[y:][:c])
+}
+
 func tryDeepEqual(a, b interface{}) bool {
 	defer func() { recover() }()
 	return reflect.DeepEqual(a, b)
@@ -198,3 +286,17 @@
 func writeByte(w io.Writer, b byte) {
 	w.Write([]byte{b})
 }
+
+func getField(v reflect.Value, i int) reflect.Value {
+	val := v.Field(i)
+	if val.Kind() == reflect.Interface && !val.IsNil() {
+		val = val.Elem()
+	}
+	return val
+}
+
+func nonzero(v reflect.Value) bool {
+	defer func() { recover() }()
+	z := reflect.Zero(v.Type())
+	return !reflect.DeepEqual(z.Interface(), v.Interface())
+}
diff --git a/formatter_test.go b/formatter_test.go
index 52c9eca..561b5a6 100644
--- a/formatter_test.go
+++ b/formatter_test.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"testing"
+	"unsafe"
 )
 
 type test struct {
@@ -21,7 +22,6 @@
 
 type F int
 
-
 func (f F) Format(s fmt.State, c int) {
 	fmt.Fprintf(s, "F(%d)", int(f))
 }
@@ -31,18 +31,35 @@
 var gosyntax = []test{
 	{"", `""`},
 	{"a", `"a"`},
-	{1, "1"},
-	{F(5), "F(5)"},
-	{long, `"` + long[:50] + "\" +\n\"" + long[50:] + `"`},
+	{1, "int(1)"},
+	{1.0, "float64(1)"},
+	{complex(1, 0), "(1+0i)"},
+	//{make(chan int), "(chan int)(0x1234)"},
+	{unsafe.Pointer(uintptr(1)), "unsafe.Pointer(0x1)"},
+	{func(int) {}, "func(int) {...}"},
+	{map[int]int{1: 1}, "map[int]int{1:1}"},
+	{int32(1), "int32(1)"},
+	{F(5), "pretty.F(5)"},
+	{
+		map[int]T{1: T{}},
+		`map[int]pretty.T{
+    1:  {},
+}`,
+	},
+	{
+		long,
+		`"abcdefghijklmnopqrstuvwxyzABCDE" +
+    "FGHIJKLMNOPQRSTUVWXYZ0123456789"`,
+	},
 	{
 		LongStructTypeName{
 			longFieldName:      LongStructTypeName{},
 			otherLongFieldName: long,
 		},
 		`pretty.LongStructTypeName{
-	longFieldName:      pretty.LongStructTypeName{},
-	otherLongFieldName: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP" +
-	"QRSTUVWXYZ0123456789",
+    longFieldName:      pretty.LongStructTypeName{},
+    otherLongFieldName: "abcdefghijklmnopqrstuvwxyzABCDE" +
+                        "FGHIJKLMNOPQRSTUVWXYZ0123456789",
 }`,
 	},
 	{
@@ -51,8 +68,8 @@
 			otherLongFieldName: (*LongStructTypeName)(nil),
 		},
 		`&pretty.LongStructTypeName{
-	longFieldName:      &pretty.LongStructTypeName{},
-	otherLongFieldName: (*pretty.LongStructTypeName)(nil),
+    longFieldName:      &pretty.LongStructTypeName{},
+    otherLongFieldName: (*pretty.LongStructTypeName)(nil),
 }`,
 	},
 	{
@@ -62,13 +79,16 @@
 			{long, nil},
 		},
 		`[]pretty.LongStructTypeName{
-	{},
-	{longFieldName:3, otherLongFieldName:3},
-	{
-		longFieldName:      "abcdefghijklmnopqrstuvwxyzABCDEFGH" +
-		"IJKLMNOPQRSTUVWXYZ0123456789",
-		otherLongFieldName: <nil>,
-	},
+    {},
+    {
+        longFieldName:      int(3),
+        otherLongFieldName: int(3),
+    },
+    {
+        longFieldName:      "abcdefghijklmnopqrstuvwxyzABCDE" +
+                            "FGHIJKLMNOPQRSTUVWXYZ0123456789",
+        otherLongFieldName: nil,
+    },
 }`,
 	},
 	{
@@ -78,28 +98,27 @@
 			T{3, 4},
 			LongStructTypeName{long, nil},
 		},
-		`[]interface { }{
-	pretty.LongStructTypeName{},
-	[]byte{0x1, 0x2, 0x3},
-	pretty.T{x:3, y:4},
-	pretty.LongStructTypeName{
-		longFieldName:      "abcdefghijklmnopqrstuvwxyzABCDEFGH" +
-		"IJKLMNOPQRSTUVWXYZ0123456789",
-		otherLongFieldName: <nil>,
-	},
+		`[]interface {}{
+    pretty.LongStructTypeName{},
+    []uint8{0x1, 0x2, 0x3},
+    pretty.T{x:3, y:4},
+    pretty.LongStructTypeName{
+        longFieldName:      "abcdefghijklmnopqrstuvwxyzABCDE" +
+                            "FGHIJKLMNOPQRSTUVWXYZ0123456789",
+        otherLongFieldName: nil,
+    },
 }`,
 	},
 }
 
-
 func TestGoSyntax(t *testing.T) {
 	for _, tt := range gosyntax {
 		s := fmt.Sprintf("%# v", Formatter(tt.v))
 		if tt.s != s {
-			t.Errorf("expected %q\n", tt.s)
-			t.Errorf("got      %q\n", s)
-			t.Errorf("expraw %s\n", tt.s)
-			t.Errorf("gotraw %s\n", s)
+			t.Errorf("expected %q", tt.s)
+			t.Errorf("got      %q", s)
+			t.Errorf("expraw\n%s", tt.s)
+			t.Errorf("gotraw\n%s", s)
 		}
 	}
 }
diff --git a/pretty.go b/pretty.go
index 84b69c4..733424a 100644
--- a/pretty.go
+++ b/pretty.go
@@ -1,19 +1,11 @@
-// Package pretty provides pretty-printing for go values. This is useful during
-// debugging, to avoid wrapping long output lines in the terminal.
+// Package pretty provides pretty-printing for Go values. This is
+// useful during debugging, to avoid wrapping long output lines in
+// the terminal.
 //
-// It provides a function, Formatter, that can be used with any function that
-// accepts a format string. For example,
-//
-//    type LongTypeName struct {
-//        longFieldName, otherLongFieldName int
-//    }
-//    func TestFoo(t *testing.T) {
-//        var x []LongTypeName{{1, 2}, {3, 4}, {5, 6}}
-//        t.Errorf("%# v", Formatter(x))
-//    }
-//
-// This package also provides a convenience wrapper for each function in
-// package fmt that takes a format string.
+// It provides a function, Formatter, that can be used with any
+// function that accepts a format string. It also provides a
+// convenience wrapper for each function in package fmt that takes
+// a format string.
 package pretty
 
 import (