errors/fmt: don’t indent first line of detail in absence of message

Newlines within regular messages are now also indented
in detail mode.

The colon ‘:’ is still strictly interpreted as a separator of
the regular message and the detail part. This means that
there is no colon after the first line of a detail-only message.

The indenting formatter is now always called in detail mode.
This does not show any differences in the benchmarks
and also simplifies the codes.

Change-Id: I33e948771bf77a27e0e5421072b5eb0d497a4644
Reviewed-on: https://go-review.googlesource.com/c/155818
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/errors/fmt/errors.go b/errors/fmt/errors.go
index 06fcffe..6be666e 100644
--- a/errors/fmt/errors.go
+++ b/errors/fmt/errors.go
@@ -192,28 +192,27 @@
 
 func (p *errPPState) Write(b []byte) (n int, err error) {
 	if !p.fmt.inDetail || p.fmt.plusV {
-		k := 0
 		if len(b) == 0 {
 			return 0, nil
 		}
-		if p.fmt.indent {
-			if p.fmt.needNewline {
-				p.fmt.needNewline = false
-				p.buf.WriteByte(':')
-				p.buf.Write(detailSep)
-				if b[0] == '\n' {
-					b = b[1:]
-				}
+		if p.fmt.inDetail && p.fmt.needNewline {
+			p.fmt.needNewline = false
+			p.buf.WriteByte(':')
+			p.buf.Write(detailSep)
+			if b[0] == '\n' {
+				b = b[1:]
 			}
-			for i, c := range b {
-				if c == '\n' {
-					p.buf.Write(b[k:i])
-					p.buf.Write(detailSep)
-					k = i + 1
-				}
+		}
+		k := 0
+		for i, c := range b {
+			if c == '\n' {
+				p.buf.Write(b[k:i])
+				p.buf.Write(detailSep)
+				k = i + 1
 			}
 		}
 		p.buf.Write(b[k:])
+		p.fmt.needNewline = !p.fmt.inDetail
 	}
 	return len(b), nil
 }
@@ -223,7 +222,7 @@
 
 func (p *errPP) Print(args ...interface{}) {
 	if !p.fmt.inDetail || p.fmt.plusV {
-		if p.fmt.indent {
+		if p.fmt.plusV {
 			Fprint((*errPPState)(p), args...)
 		} else {
 			(*pp)(p).doPrint(args)
@@ -233,7 +232,7 @@
 
 func (p *errPP) Printf(format string, args ...interface{}) {
 	if !p.fmt.inDetail || p.fmt.plusV {
-		if p.fmt.indent {
+		if p.fmt.plusV {
 			Fprintf((*errPPState)(p), format, args...)
 		} else {
 			(*pp)(p).doPrintf(format, args)
@@ -242,11 +241,6 @@
 }
 
 func (p *errPP) Detail() bool {
-	inDetail := p.fmt.inDetail
 	p.fmt.inDetail = true
-	p.fmt.indent = p.fmt.plusV
-	if p.fmt.plusV && !inDetail {
-		p.fmt.needNewline = true
-	}
 	return p.fmt.plusV
 }
diff --git a/errors/fmt/errors_test.go b/errors/fmt/errors_test.go
index 0aa0192..116ddc4 100644
--- a/errors/fmt/errors_test.go
+++ b/errors/fmt/errors_test.go
@@ -223,6 +223,21 @@
 			"\nnewline: and another" +
 			"\none",
 	}, {
+		err: newline,
+		fmt: "%+v",
+		want: "msg with" +
+			"\n    newline:" +
+			"\n    somefile.go:123" +
+			"\n  - and another" +
+			"\n    one:" +
+			"\n    somefile.go:123",
+	}, {
+		err: wrapped{"", wrapped{"inner message", nil}},
+		fmt: "%+v",
+		want: "somefile.go:123" +
+			"\n  - inner message:" +
+			"\n    somefile.go:123",
+	}, {
 		err:  spurious(""),
 		fmt:  "%s",
 		want: "spurious",
diff --git a/errors/fmt/format.go b/errors/fmt/format.go
index f79301e..0390f71 100644
--- a/errors/fmt/format.go
+++ b/errors/fmt/format.go
@@ -37,7 +37,6 @@
 
 	// error-related flags.
 	inDetail    bool
-	indent      bool
 	needNewline bool
 }