Use fmt.Formatter throughout (#40)

* Use fmt.Formatter throughout

Replace Fprintf with fmt.Formatter logic on various types. This
effectively guts Fprint to be just a recursive call down the err.Cause
chain. The next step will be to move this recursive logic into
wrapper.Format.

This change necessitates adding types for the error impls returned from
New and Errorf, and Wrap and Wrapf, respectively. The name of the latter
type is acceptable, the former is not and alternative suggestions are
encouraged.

- Remove cause.Format
- Added fmt.Formatter tests. The location is temporary, once this PR is merged and Fprint removed
they will be merged into errors_test.go
diff --git a/errors.go b/errors.go
index 219df86..a97116f 100644
--- a/errors.go
+++ b/errors.go
@@ -54,18 +54,35 @@
 package errors
 
 import (
-	"errors"
 	"fmt"
 	"io"
 )
 
+// _error is an error implementation returned by New and Errorf
+// that implements its own fmt.Formatter.
+type _error struct {
+	msg string
+	*stack
+}
+
+func (e _error) Error() string { return e.msg }
+
+func (e _error) Format(s fmt.State, verb rune) {
+	switch verb {
+	case 'v':
+		if s.Flag('+') {
+			fmt.Fprintf(s, "%+v: ", e.Stacktrace()[0])
+		}
+		fallthrough
+	case 's':
+		io.WriteString(s, e.msg)
+	}
+}
+
 // New returns an error that formats as the given text.
 func New(text string) error {
-	return struct {
-		error
-		*stack
-	}{
-		errors.New(text),
+	return _error{
+		text,
 		callers(),
 	}
 }
@@ -73,11 +90,8 @@
 // Errorf formats according to a format specifier and returns the string
 // as a value that satisfies error.
 func Errorf(format string, args ...interface{}) error {
-	return struct {
-		error
-		*stack
-	}{
-		fmt.Errorf(format, args...),
+	return _error{
+		fmt.Sprintf(format, args...),
 		callers(),
 	}
 }
@@ -87,19 +101,26 @@
 	msg   string
 }
 
-func (c cause) Error() string { return fmt.Sprintf("%v", c) }
+func (c cause) Error() string { return fmt.Sprintf("%s: %v", c.msg, c.Cause()) }
 func (c cause) Cause() error  { return c.cause }
 
-func (c cause) Format(s fmt.State, verb rune) {
+// wrapper is an error implementation returned by Wrap and Wrapf
+// that implements its own fmt.Formatter.
+type wrapper struct {
+	cause
+	*stack
+}
+
+func (w wrapper) Format(s fmt.State, verb rune) {
 	switch verb {
 	case 'v':
 		if s.Flag('+') {
-			io.WriteString(s, c.msg)
+			fmt.Fprintf(s, "%+v: %s", w.Stacktrace()[0], w.cause.msg)
 			return
 		}
 		fallthrough
 	case 's':
-		fmt.Fprintf(s, "%s: %v", c.msg, c.Cause())
+		io.WriteString(s, w.Error())
 	}
 }
 
@@ -109,15 +130,12 @@
 	if err == nil {
 		return nil
 	}
-	return struct {
-		cause
-		*stack
-	}{
-		cause{
+	return wrapper{
+		cause: cause{
 			cause: err,
 			msg:   message,
 		},
-		callers(),
+		stack: callers(),
 	}
 }
 
@@ -127,15 +145,12 @@
 	if err == nil {
 		return nil
 	}
-	return struct {
-		cause
-		*stack
-	}{
-		cause{
+	return wrapper{
+		cause: cause{
 			cause: err,
 			msg:   fmt.Sprintf(format, args...),
 		},
-		callers(),
+		stack: callers(),
 	}
 }
 
@@ -179,20 +194,8 @@
 //
 // Deprecated: Fprint will be removed in version 0.7.
 func Fprint(w io.Writer, err error) {
-	type stacktrace interface {
-		Stacktrace() []Frame
-	}
-
 	for err != nil {
-		switch err := err.(type) {
-		case stacktrace:
-			frame := err.Stacktrace()[0]
-			fmt.Fprintf(w, "%+v: ", frame)
-		default:
-			// de nada
-		}
 		fmt.Fprintf(w, "%+v\n", err)
-
 		cause, ok := err.(causer)
 		if !ok {
 			break
diff --git a/example_test.go b/example_test.go
index 427e2a9..041a75b 100644
--- a/example_test.go
+++ b/example_test.go
@@ -14,9 +14,9 @@
 	// Output: whoops
 }
 
-func ExampleNew_fprint() {
+func ExampleNew_printf() {
 	err := errors.New("whoops")
-	errors.Fprint(os.Stdout, err)
+	fmt.Printf("%+v", err)
 
 	// Output: github.com/pkg/errors/example_test.go:18: whoops
 }
@@ -65,7 +65,7 @@
 
 func ExampleErrorf() {
 	err := errors.Errorf("whoops: %s", "foo")
-	errors.Fprint(os.Stdout, err)
+	fmt.Printf("%+v", err)
 
 	// Output: github.com/pkg/errors/example_test.go:67: whoops: foo
 }
diff --git a/format_test.go b/format_test.go
new file mode 100644
index 0000000..70a37cc
--- /dev/null
+++ b/format_test.go
@@ -0,0 +1,70 @@
+package errors
+
+import (
+	"fmt"
+	"testing"
+)
+
+func TestFormat(t *testing.T) {
+	tests := []struct {
+		error
+		format string
+		want   string
+	}{{
+
+		New("error"),
+		"%s",
+		"error",
+	}, {
+		New("error"),
+		"%v",
+		"error",
+	}, {
+		New("error"),
+		"%+v",
+		"github.com/pkg/errors/format_test.go:23: error",
+	}, {
+		Errorf("%s", "error"),
+		"%s",
+		"error",
+	}, {
+		Errorf("%s", "error"),
+		"%v",
+		"error",
+	}, {
+		Errorf("%s", "error"),
+		"%+v",
+		"github.com/pkg/errors/format_test.go:35: error",
+	}, {
+		Wrap(New("error"), "error2"),
+		"%s",
+		"error2: error",
+	}, {
+		Wrap(New("error"), "error2"),
+		"%v",
+		"error2: error",
+	}, {
+		Wrap(New("error"), "error2"),
+		"%+v",
+		"github.com/pkg/errors/format_test.go:47: error2",
+	}, {
+		Wrapf(New("error"), "error%d", 2),
+		"%s",
+		"error2: error",
+	}, {
+		Wrapf(New("error"), "error%d", 2),
+		"%v",
+		"error2: error",
+	}, {
+		Wrapf(New("error"), "error%d", 2),
+		"%+v",
+		"github.com/pkg/errors/format_test.go:59: error2",
+	}}
+
+	for _, tt := range tests {
+		got := fmt.Sprintf(tt.format, tt.error)
+		if got != tt.want {
+			t.Errorf("fmt.Sprintf(%q, err): got: %q, want: %q", tt.format, got, tt.want)
+		}
+	}
+}