prevent wrapping into longer, general testing
This commit is contained in:
parent
612aa94f0a
commit
b1e3ada95c
21
debug_test.go
Normal file
21
debug_test.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package notation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDebugNode(t *testing.T) {
|
||||||
|
const expect = `"foobarbaz"`
|
||||||
|
o := "foobarbaz"
|
||||||
|
n := reflectValue(none, reflect.ValueOf(o))
|
||||||
|
s := fmt.Sprint(n)
|
||||||
|
if s != expect {
|
||||||
|
t.Fatalf(
|
||||||
|
"failed to get debug string of node, got: %s, expected: %s",
|
||||||
|
s,
|
||||||
|
expect,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
51
env_test.go
Normal file
51
env_test.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package notation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func withEnv(t *testing.T, e ...string) (revert func()) {
|
||||||
|
var r []func()
|
||||||
|
revert = func() {
|
||||||
|
for i := range r {
|
||||||
|
r[i]()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
revertOne := func(key, value string, existed bool) func() {
|
||||||
|
return func() {
|
||||||
|
if existed {
|
||||||
|
if err := os.Setenv(key, value); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Unsetenv(key); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range e {
|
||||||
|
var key, value string
|
||||||
|
p := strings.Split(e[i], "=")
|
||||||
|
key = p[0]
|
||||||
|
if len(p) > 1 {
|
||||||
|
value = p[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
prev, ok := os.LookupEnv(key)
|
||||||
|
if err := os.Setenv(key, value); err != nil {
|
||||||
|
revert()
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r = append(r, revertOne(key, prev, ok))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
244
fprint.go
244
fprint.go
@ -1,125 +1,168 @@
|
|||||||
package notation
|
package notation
|
||||||
|
|
||||||
import (
|
func unwrappable(n node) bool {
|
||||||
"fmt"
|
return n.len == n.wrapLen.max &&
|
||||||
"io"
|
n.len == n.fullWrap.max
|
||||||
)
|
|
||||||
|
|
||||||
type writer struct {
|
|
||||||
w io.Writer
|
|
||||||
n int
|
|
||||||
err error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *writer) write(o interface{}) {
|
func initialize(t *int, v int) {
|
||||||
if w.err != nil {
|
if *t > 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := fmt.Fprint(w.w, o)
|
*t = v
|
||||||
w.n += n
|
}
|
||||||
w.err = err
|
|
||||||
|
func max(t *int, v int) {
|
||||||
|
if *t >= v {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = v
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeLen(t int, n node) node {
|
func nodeLen(t int, n node) node {
|
||||||
var w int
|
var w, f int
|
||||||
for i, p := range n.parts {
|
for i, p := range n.parts {
|
||||||
switch part := p.(type) {
|
switch part := p.(type) {
|
||||||
case string:
|
case string:
|
||||||
n.len += len(part)
|
n.len += len(part)
|
||||||
w += len(part)
|
w += len(part)
|
||||||
|
f += len(part)
|
||||||
case node:
|
case node:
|
||||||
part = nodeLen(t, part)
|
part = nodeLen(t, part)
|
||||||
n.parts[i] = part
|
n.parts[i] = part
|
||||||
n.len += part.len
|
n.len += part.len
|
||||||
if part.len == part.wlen {
|
if unwrappable(part) {
|
||||||
|
w += part.len
|
||||||
|
f += part.len
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if part.len == part.wrapLen.max {
|
||||||
w += part.len
|
w += part.len
|
||||||
} else {
|
} else {
|
||||||
w += part.wlen0
|
w += part.wrapLen.first
|
||||||
if w > n.wlen {
|
initialize(&n.wrapLen.first, w)
|
||||||
n.wlen = w
|
max(&n.wrapLen.max, w)
|
||||||
}
|
w = part.wrapLen.last
|
||||||
|
|
||||||
if part.wlen > n.wlen {
|
|
||||||
n.wlen = part.wlen
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.wlen0 == 0 {
|
|
||||||
n.wlen0 = w
|
|
||||||
}
|
|
||||||
|
|
||||||
w = part.wlenLast
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f += part.fullWrap.first
|
||||||
|
initialize(&n.fullWrap.first, f)
|
||||||
|
max(&n.fullWrap.max, f)
|
||||||
|
f = part.fullWrap.last
|
||||||
case wrapper:
|
case wrapper:
|
||||||
if len(part.items) == 0 {
|
if len(part.items) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if w > n.wlen {
|
initialize(&n.wrapLen.first, w)
|
||||||
n.wlen = w
|
max(&n.wrapLen.max, w)
|
||||||
|
initialize(&n.fullWrap.first, f)
|
||||||
|
max(&n.fullWrap.max, f)
|
||||||
|
w, f = 0, 0
|
||||||
|
n.len += (len(part.items) - 1) * len(part.sep)
|
||||||
|
if part.mode == line {
|
||||||
|
w += (len(part.items) - 1) * len(part.sep)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.wlen0 == 0 {
|
for j, item := range part.items {
|
||||||
n.wlen0 = w
|
item = nodeLen(t, item)
|
||||||
}
|
part.items[j] = item
|
||||||
|
n.len += item.len
|
||||||
w = 0
|
switch part.mode {
|
||||||
for j, ni := range part.items {
|
case line:
|
||||||
ni = nodeLen(t, ni)
|
w += item.len
|
||||||
part.items[j] = ni
|
max(&f, item.len)
|
||||||
n.len += ni.len
|
default:
|
||||||
wni := t + ni.len + len(part.suffix)
|
wj := t + item.len + len(part.suffix)
|
||||||
if wni > w {
|
max(&w, wj)
|
||||||
w = wni
|
fj := t + item.fullWrap.max
|
||||||
|
max(&f, fj)
|
||||||
|
fj = t + item.fullWrap.last + len(part.suffix)
|
||||||
|
max(&f, fj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(part.items) > 0 {
|
max(&n.wrapLen.max, w)
|
||||||
n.len += (len(part.items) - 1) * len(part.sep)
|
max(&n.fullWrap.max, f)
|
||||||
}
|
w, f = 0, 0
|
||||||
|
|
||||||
w = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if w > n.wlen {
|
initialize(&n.wrapLen.first, w)
|
||||||
n.wlen = w
|
max(&n.wrapLen.max, w)
|
||||||
}
|
n.wrapLen.last = w
|
||||||
|
initialize(&n.fullWrap.first, f)
|
||||||
if n.wlen0 == 0 {
|
max(&n.fullWrap.max, f)
|
||||||
n.wlen0 = w
|
n.fullWrap.last = f
|
||||||
}
|
|
||||||
|
|
||||||
n.wlenLast = w
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrapNode(t, c0, c1 int, n node) node {
|
func wrapNode(t, c0, c1 int, n node) node {
|
||||||
if n.len <= c0 || n.wlen == n.len {
|
if n.len <= c0 {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.len <= c1 && n.len-c0 <= n.wlen {
|
if n.wrapLen.max >= n.len && n.fullWrap.max >= n.len {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.len <= c1 && n.len-c0 <= n.wrapLen.max {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
n.wrap = true
|
n.wrap = true
|
||||||
if n.wlen <= c0 {
|
cc0, cc1 := c0, c1
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, p := range n.parts {
|
for i, p := range n.parts {
|
||||||
switch part := p.(type) {
|
switch part := p.(type) {
|
||||||
case node:
|
case node:
|
||||||
n.parts[i] = wrapNode(t, c0, c1, part)
|
part = wrapNode(t, cc0, cc1, part)
|
||||||
|
n.parts[i] = part
|
||||||
|
if part.wrap {
|
||||||
|
cc0 -= part.wrapLen.last
|
||||||
|
cc1 -= part.wrapLen.last
|
||||||
|
} else {
|
||||||
|
cc0 -= part.len
|
||||||
|
cc1 -= part.len
|
||||||
|
}
|
||||||
case wrapper:
|
case wrapper:
|
||||||
for j := range part.items {
|
if len(part.items) > 0 {
|
||||||
part.items[j] = wrapNode(
|
cc0, cc1 = c0, c1
|
||||||
t,
|
}
|
||||||
c0-t,
|
|
||||||
c1-t,
|
switch part.mode {
|
||||||
part.items[j],
|
case line:
|
||||||
)
|
c0, c1 = c0-t, c1-t
|
||||||
|
var w int
|
||||||
|
for j, ni := range part.items {
|
||||||
|
if w > 0 && w+len(part.sep)+ni.len > c0 {
|
||||||
|
w = 0
|
||||||
|
part.lineWrappers = append(
|
||||||
|
part.lineWrappers,
|
||||||
|
j,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if w > 0 {
|
||||||
|
w += len(part.sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
w += ni.len
|
||||||
|
}
|
||||||
|
|
||||||
|
n.parts[i] = part
|
||||||
|
c0, c1 = c0+t, c1+t
|
||||||
|
default:
|
||||||
|
for j := range part.items {
|
||||||
|
part.items[j] = wrapNode(
|
||||||
|
t,
|
||||||
|
c0-t,
|
||||||
|
c1-t,
|
||||||
|
part.items[j],
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,35 +175,60 @@ func fprint(w *writer, t int, n node) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < t; i++ {
|
|
||||||
w.write("\t")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range n.parts {
|
for _, p := range n.parts {
|
||||||
switch part := p.(type) {
|
switch part := p.(type) {
|
||||||
case node:
|
case node:
|
||||||
fprint(w, 0, part)
|
fprint(w, t, part)
|
||||||
case wrapper:
|
case wrapper:
|
||||||
if len(part.items) == 0 {
|
if len(part.items) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.wrap {
|
if !n.wrap {
|
||||||
w.write("\n")
|
for i, ni := range part.items {
|
||||||
}
|
fprint(w, t, ni)
|
||||||
|
|
||||||
for i, ni := range part.items {
|
|
||||||
if n.wrap {
|
|
||||||
fprint(w, t+1, ni)
|
|
||||||
w.write(part.suffix)
|
|
||||||
w.write("\n")
|
|
||||||
} else {
|
|
||||||
fprint(w, 0, ni)
|
|
||||||
if i < len(part.items)-1 {
|
if i < len(part.items)-1 {
|
||||||
w.write(part.sep)
|
w.write(part.sep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t++
|
||||||
|
switch part.mode {
|
||||||
|
case line:
|
||||||
|
var (
|
||||||
|
wi int
|
||||||
|
lineStarted bool
|
||||||
|
)
|
||||||
|
|
||||||
|
w.line(t)
|
||||||
|
for i, ni := range part.items {
|
||||||
|
if len(part.lineWrappers) > wi &&
|
||||||
|
i == part.lineWrappers[wi] {
|
||||||
|
wi++
|
||||||
|
w.line(t)
|
||||||
|
lineStarted = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if lineStarted {
|
||||||
|
w.write(part.sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
fprint(w, 0, ni)
|
||||||
|
lineStarted = true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
for _, ni := range part.items {
|
||||||
|
w.line(t)
|
||||||
|
fprint(w, t, ni)
|
||||||
|
w.write(part.suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t--
|
||||||
|
w.line(t)
|
||||||
default:
|
default:
|
||||||
w.write(part)
|
w.write(part)
|
||||||
}
|
}
|
||||||
|
206
fprint_test.go
Normal file
206
fprint_test.go
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
package notation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type failingWriter int
|
||||||
|
|
||||||
|
var errTest = errors.New("test")
|
||||||
|
|
||||||
|
func failAfter(n int) *failingWriter {
|
||||||
|
w := failingWriter(n)
|
||||||
|
return &w
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *failingWriter) Write(p []byte) (int, error) {
|
||||||
|
*w = failingWriter(int(*w) - len(p))
|
||||||
|
if *w >= 0 {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(p) + int(*w), errTest
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFailingWriter(t *testing.T) {
|
||||||
|
t.Run("single object", func(t *testing.T) {
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
w := failAfter(9)
|
||||||
|
n, err := Fprint(w, o)
|
||||||
|
if n == 9 && err == errTest {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 9 {
|
||||||
|
t.Fatalf("failed to writ the expected bytes; expected: 9, written: %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != errTest {
|
||||||
|
t.Fatalf("failed to receive the right error; expected: %v, received: %v", errTest, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("multiple objects, fail first", func(t *testing.T) {
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
w := failAfter(9)
|
||||||
|
n, err := Fprint(w, o, o)
|
||||||
|
if n == 9 && err == errTest {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 9 {
|
||||||
|
t.Fatalf("failed to writ the expected bytes; expected: 9, written: %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != errTest {
|
||||||
|
t.Fatalf("failed to receive the right error; expected: %v, received: %v", errTest, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("multiple objects, fail second", func(t *testing.T) {
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
w := failAfter(18)
|
||||||
|
n, err := Fprint(w, o, o)
|
||||||
|
if n == 9 && err == errTest {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 18 {
|
||||||
|
t.Fatalf("failed to writ the expected bytes; expected: 9, written: %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != errTest {
|
||||||
|
t.Fatalf("failed to receive the right error; expected: %v, received: %v", errTest, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFprint(t *testing.T) {
|
||||||
|
t.Run("Fprint", func(t *testing.T) {
|
||||||
|
const expect = `{fooBarBaz: 42}`
|
||||||
|
var b bytes.Buffer
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
n, err := Fprint(&b, o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(expect) {
|
||||||
|
t.Fatalf("invalid write length; expected: %d, got: %d", len(expect), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != expect {
|
||||||
|
t.Fatalf("invalid output; expected: %s, got: %s", expect, b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Fprintw", func(t *testing.T) {
|
||||||
|
const expect = `{
|
||||||
|
fooBarBaz: 42,
|
||||||
|
}`
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
n, err := Fprintw(&b, o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(expect) {
|
||||||
|
t.Fatalf("invalid write length; expected: %d, got: %d", len(expect), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != expect {
|
||||||
|
t.Fatalf("invalid output; expected: %s, got: %s", expect, b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Fprintt", func(t *testing.T) {
|
||||||
|
const expect = `struct{fooBarBaz int}{fooBarBaz: 42}`
|
||||||
|
var b bytes.Buffer
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
n, err := Fprintt(&b, o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(expect) {
|
||||||
|
t.Fatalf("invalid write length; expected: %d, got: %d", len(expect), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != expect {
|
||||||
|
t.Fatalf("invalid output; expected: %s, got: %s", expect, b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Fprintwt", func(t *testing.T) {
|
||||||
|
const expect = `struct{
|
||||||
|
fooBarBaz int
|
||||||
|
}{
|
||||||
|
fooBarBaz: 42,
|
||||||
|
}`
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
n, err := Fprintwt(&b, o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(expect) {
|
||||||
|
t.Fatalf("invalid write length; expected: %d, got: %d", len(expect), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != expect {
|
||||||
|
t.Fatalf("invalid output; expected: %s, got: %s", expect, b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Fprintv", func(t *testing.T) {
|
||||||
|
const expect = `struct{fooBarBaz int}{fooBarBaz: int(42)}`
|
||||||
|
var b bytes.Buffer
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
n, err := Fprintv(&b, o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(expect) {
|
||||||
|
t.Fatalf("invalid write length; expected: %d, got: %d", len(expect), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != expect {
|
||||||
|
t.Fatalf("invalid output; expected: %s, got: %s", expect, b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Fprintv", func(t *testing.T) {
|
||||||
|
const expect = `struct{
|
||||||
|
fooBarBaz int
|
||||||
|
}{
|
||||||
|
fooBarBaz: int(42),
|
||||||
|
}`
|
||||||
|
var b bytes.Buffer
|
||||||
|
o := struct{ fooBarBaz int }{42}
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
n, err := Fprintwv(&b, o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(expect) {
|
||||||
|
t.Fatalf("invalid write length; expected: %d, got: %d", len(expect), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.String() != expect {
|
||||||
|
t.Fatalf("invalid output; expected: %s, got: %s", expect, b.String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
68
notation.go
68
notation.go
@ -2,6 +2,7 @@ package notation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -18,17 +19,63 @@ const (
|
|||||||
types
|
types
|
||||||
skipTypes
|
skipTypes
|
||||||
allTypes
|
allTypes
|
||||||
|
randomMaps
|
||||||
)
|
)
|
||||||
|
|
||||||
type node struct {
|
type wrapLen struct {
|
||||||
len, wlen, wlen0, wlenLast int
|
first, max, last int
|
||||||
wrap bool
|
|
||||||
parts []interface{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
len int
|
||||||
|
wrapLen wrapLen
|
||||||
|
fullWrap wrapLen
|
||||||
|
wrap bool
|
||||||
|
parts []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type wrapMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
block wrapMode = iota
|
||||||
|
line
|
||||||
|
)
|
||||||
|
|
||||||
type wrapper struct {
|
type wrapper struct {
|
||||||
sep, suffix string
|
mode wrapMode
|
||||||
items []node
|
sep, suffix string
|
||||||
|
items []node
|
||||||
|
lineWrappers []int
|
||||||
|
}
|
||||||
|
|
||||||
|
type writer struct {
|
||||||
|
w io.Writer
|
||||||
|
n int
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n node) String() string {
|
||||||
|
var b bytes.Buffer
|
||||||
|
w := &writer{w: &b}
|
||||||
|
fprint(w, 0, n)
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writer) write(o interface{}) {
|
||||||
|
if w.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := fmt.Fprint(w.w, o)
|
||||||
|
w.n += n
|
||||||
|
w.err = err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *writer) line(t int) {
|
||||||
|
w.write("\n")
|
||||||
|
for i := 0; i < t; i++ {
|
||||||
|
w.write("\t")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeOf(parts ...interface{}) node {
|
func nodeOf(parts ...interface{}) node {
|
||||||
@ -55,8 +102,13 @@ func config(name string, dflt int) int {
|
|||||||
|
|
||||||
func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
|
func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
|
||||||
tab := config("TABWIDTH", 8)
|
tab := config("TABWIDTH", 8)
|
||||||
cols0 := config("LINEWIDTH", 80-8)
|
cols0 := config("LINEWIDTH", 80-tab)
|
||||||
cols1 := config("LINEWIDTH1", (cols0+8)*3/2-8)
|
cols1 := config("LINEWIDTH1", (cols0+tab)*3/2-tab)
|
||||||
|
sortMaps := config("MAPSORT", 1)
|
||||||
|
if sortMaps == 0 {
|
||||||
|
o |= randomMaps
|
||||||
|
}
|
||||||
|
|
||||||
wr := &writer{w: w}
|
wr := &writer{w: w}
|
||||||
for i, vi := range v {
|
for i, vi := range v {
|
||||||
if wr.err != nil {
|
if wr.err != nil {
|
||||||
|
60
reflect.go
60
reflect.go
@ -46,34 +46,51 @@ func reflectPrimitive(o opts, r reflect.Value, v interface{}, suppressType ...st
|
|||||||
return nodeOf(tn, "(", s, ")")
|
return nodeOf(tn, "(", s, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
func reflectNil(o opts, r reflect.Value) node {
|
func reflectNil(o opts, groupUnnamedType bool, r reflect.Value) node {
|
||||||
if _, _, a := withType(o); !a {
|
if _, _, a := withType(o); !a {
|
||||||
return nodeOf("nil")
|
return nodeOf("nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeOf(reflectType(r.Type()), "(nil)")
|
rt := r.Type()
|
||||||
|
if groupUnnamedType && rt.Name() == "" {
|
||||||
|
return nodeOf("(", reflectType(rt), ")(nil)")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeOf(reflectType(rt), "(nil)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func reflectItems(o opts, prefix string, r reflect.Value) node {
|
func reflectItems(o opts, prefix string, r reflect.Value) node {
|
||||||
items := wrapper{sep: ", ", suffix: ","}
|
typ := r.Type()
|
||||||
itemOpts := o | skipTypes
|
var items wrapper
|
||||||
for i := 0; i < r.Len(); i++ {
|
if typ.Elem().Name() == "uint8" {
|
||||||
items.items = append(
|
items = wrapper{sep: " ", mode: line}
|
||||||
items.items,
|
for i := 0; i < r.Len(); i++ {
|
||||||
reflectValue(itemOpts, r.Index(i)),
|
items.items = append(
|
||||||
)
|
items.items,
|
||||||
|
nodeOf(fmt.Sprintf("%02x", r.Index(i).Uint())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
items = wrapper{sep: ", ", suffix: ","}
|
||||||
|
itemOpts := o | skipTypes
|
||||||
|
for i := 0; i < r.Len(); i++ {
|
||||||
|
items.items = append(
|
||||||
|
items.items,
|
||||||
|
reflectValue(itemOpts, r.Index(i)),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, t, _ := withType(o); !t {
|
if _, t, _ := withType(o); !t {
|
||||||
return nodeOf(prefix, "{", items, "}")
|
return nodeOf(prefix, "{", items, "}")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeOf(reflectType(r.Type()), "{", items, "}")
|
return nodeOf(reflectType(typ), "{", items, "}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func reflectHidden(o opts, hidden string, r reflect.Value) node {
|
func reflectHidden(o opts, hidden string, r reflect.Value) node {
|
||||||
if r.IsNil() {
|
if r.IsNil() {
|
||||||
return reflectNil(o, r)
|
return reflectNil(o, true, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, t, _ := withType(o); !t {
|
if _, t, _ := withType(o); !t {
|
||||||
@ -97,7 +114,7 @@ func reflectFunc(o opts, r reflect.Value) node {
|
|||||||
|
|
||||||
func reflectInterface(o opts, r reflect.Value) node {
|
func reflectInterface(o opts, r reflect.Value) node {
|
||||||
if r.IsNil() {
|
if r.IsNil() {
|
||||||
return reflectNil(o, r)
|
return reflectNil(o, false, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := reflectValue(o, r.Elem())
|
e := reflectValue(o, r.Elem())
|
||||||
@ -115,7 +132,7 @@ func reflectInterface(o opts, r reflect.Value) node {
|
|||||||
|
|
||||||
func reflectMap(o opts, r reflect.Value) node {
|
func reflectMap(o opts, r reflect.Value) node {
|
||||||
if r.IsNil() {
|
if r.IsNil() {
|
||||||
return reflectNil(o, r)
|
return reflectNil(o, true, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -140,7 +157,10 @@ func reflectMap(o opts, r reflect.Value) node {
|
|||||||
sn[skey] = nk
|
sn[skey] = nk
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(skeys)
|
if o&randomMaps == 0 {
|
||||||
|
sort.Strings(skeys)
|
||||||
|
}
|
||||||
|
|
||||||
for _, skey := range skeys {
|
for _, skey := range skeys {
|
||||||
items.items = append(
|
items.items = append(
|
||||||
items.items,
|
items.items,
|
||||||
@ -161,7 +181,7 @@ func reflectMap(o opts, r reflect.Value) node {
|
|||||||
|
|
||||||
func reflectPointer(o opts, r reflect.Value) node {
|
func reflectPointer(o opts, r reflect.Value) node {
|
||||||
if r.IsNil() {
|
if r.IsNil() {
|
||||||
return reflectNil(o, r)
|
return reflectNil(o, true, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := reflectValue(o, r.Elem())
|
e := reflectValue(o, r.Elem())
|
||||||
@ -174,7 +194,7 @@ func reflectPointer(o opts, r reflect.Value) node {
|
|||||||
|
|
||||||
func reflectList(o opts, r reflect.Value) node {
|
func reflectList(o opts, r reflect.Value) node {
|
||||||
if r.IsNil() {
|
if r.IsNil() {
|
||||||
return reflectNil(o, r)
|
return reflectNil(o, true, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
return reflectItems(o, "[]", r)
|
return reflectItems(o, "[]", r)
|
||||||
@ -221,7 +241,7 @@ func reflectString(o opts, r reflect.Value) node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func reflectStruct(o opts, r reflect.Value) node {
|
func reflectStruct(o opts, r reflect.Value) node {
|
||||||
wr := wrapper{sep: ", "}
|
wr := wrapper{sep: ", ", suffix: ","}
|
||||||
|
|
||||||
fieldOpts := o | skipTypes
|
fieldOpts := o | skipTypes
|
||||||
rt := r.Type()
|
rt := r.Type()
|
||||||
@ -249,7 +269,7 @@ func reflectStruct(o opts, r reflect.Value) node {
|
|||||||
|
|
||||||
func reflectUnsafePointer(o opts, r reflect.Value) node {
|
func reflectUnsafePointer(o opts, r reflect.Value) node {
|
||||||
if r.IsNil() {
|
if r.IsNil() {
|
||||||
return reflectNil(o, r)
|
return reflectNil(o, false, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, _, a := withType(o); !a {
|
if _, _, a := withType(o); !a {
|
||||||
@ -298,11 +318,9 @@ func reflectValue(o opts, r reflect.Value) node {
|
|||||||
return reflectList(o, r)
|
return reflectList(o, r)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return reflectString(o, r)
|
return reflectString(o, r)
|
||||||
case reflect.Struct:
|
|
||||||
return reflectStruct(o, r)
|
|
||||||
case reflect.UnsafePointer:
|
case reflect.UnsafePointer:
|
||||||
return reflectUnsafePointer(o, r)
|
return reflectUnsafePointer(o, r)
|
||||||
default:
|
default:
|
||||||
return nodeOf("<invalid>")
|
return reflectStruct(o, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package notation
|
package notation
|
||||||
|
|
||||||
import (
|
import "reflect"
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
func reflectFuncBaseType(t reflect.Type) node {
|
func reflectFuncBaseType(t reflect.Type) node {
|
||||||
|
isVariadic := t.IsVariadic()
|
||||||
args := func(num func() int, typ func(int) reflect.Type) []node {
|
args := func(num func() int, typ func(int) reflect.Type) []node {
|
||||||
var t []node
|
var t []node
|
||||||
for i := 0; i < num(); i++ {
|
for i := 0; i < num(); i++ {
|
||||||
|
if i == num()-1 && isVariadic {
|
||||||
|
t = append(t, nodeOf("...", reflectType(typ(i).Elem())))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
t = append(t, reflectType(typ(i)))
|
t = append(t, reflectType(typ(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,14 +25,14 @@ func reflectFuncBaseType(t reflect.Type) node {
|
|||||||
if len(in) == 1 {
|
if len(in) == 1 {
|
||||||
n.parts = append(n.parts, in[0])
|
n.parts = append(n.parts, in[0])
|
||||||
} else if len(in) > 1 {
|
} else if len(in) > 1 {
|
||||||
n.parts = append(n.parts, wrapper{sep: ", ", items: in})
|
n.parts = append(n.parts, wrapper{sep: ", ", suffix: ",", items: in})
|
||||||
}
|
}
|
||||||
|
|
||||||
n.parts = append(n.parts, ")")
|
n.parts = append(n.parts, ")")
|
||||||
if len(out) == 1 {
|
if len(out) == 1 {
|
||||||
n.parts = append(n.parts, " ", out[0])
|
n.parts = append(n.parts, " ", out[0])
|
||||||
} else if len(out) > 1 {
|
} else if len(out) > 1 {
|
||||||
n.parts = append(n.parts, " (", wrapper{sep: ", ", items: out}, ")")
|
n.parts = append(n.parts, " (", wrapper{sep: ", ", suffix: ",", items: out}, ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
return n
|
return n
|
||||||
@ -103,7 +107,12 @@ func reflectStructType(t reflect.Type) node {
|
|||||||
|
|
||||||
func reflectType(t reflect.Type) node {
|
func reflectType(t reflect.Type) node {
|
||||||
if t.Name() != "" {
|
if t.Name() != "" {
|
||||||
return nodeOf(t.Name())
|
name := t.Name()
|
||||||
|
if name == "uint8" {
|
||||||
|
name = "byte"
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeOf(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
@ -121,9 +130,7 @@ func reflectType(t reflect.Type) node {
|
|||||||
return reflectPointerType(t)
|
return reflectPointerType(t)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return reflectListType(t)
|
return reflectListType(t)
|
||||||
case reflect.Struct:
|
|
||||||
return reflectStructType(t)
|
|
||||||
default:
|
default:
|
||||||
return nodeOf("<invalid>")
|
return reflectStructType(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1072
sprint_test.go
1072
sprint_test.go
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user