documentation
This commit is contained in:
parent
f999a77ff9
commit
1becff5c5d
445
README.md
Normal file
445
README.md
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
# Notation - Print Go objects
|
||||||
|
|
||||||
|
This package can be used to print (or sprint) Go objects with optional wrapping (indentation) and optional type
|
||||||
|
information for debugging purposes.
|
||||||
|
|
||||||
|
### Alternatives
|
||||||
|
|
||||||
|
Notation is similar to the following great, more established and mature packages:
|
||||||
|
|
||||||
|
- [go-spew](https://github.com/davecgh/go-spew/)
|
||||||
|
- [litter](https://github.com/sanity-io/litter)
|
||||||
|
- [utter](https://github.com/kortschak/utter)
|
||||||
|
|
||||||
|
Notation differs from these primarily in the 'flavour' of printing and the package interface.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
`go get github.com/aryszka/notation`
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Pass in the Go object(s) to be printed to one of the notation functions. These functions can be categorized into
|
||||||
|
four groups:
|
||||||
|
|
||||||
|
- **Println:** the Println type functions print Go objects to stderr with an additional newline at the end.
|
||||||
|
- **Print:** similar to Println but without the extra newline.
|
||||||
|
- **Fprint:** the Fprint type functions print Go objects to an arbitrary writer passed in as an argument.
|
||||||
|
- **Sprint:** the Sprint type functions return the string representation of Go objects instead of printing them.
|
||||||
|
|
||||||
|
The format and the verbosity can be controlled with the suffixed variants of the above functions. By default,
|
||||||
|
the input arguments are printed without types on a single line. The following suffixes are available:
|
||||||
|
|
||||||
|
- **`w`**: wrap the output based on Go-style indentation
|
||||||
|
- **`t`**: print moderately verbose type information, omitting where it can be trivially inferred
|
||||||
|
- **`v`**: print verbose type information
|
||||||
|
|
||||||
|
When **`t`** or **`v`** are used together with **`w`**, they must follow **`w`**. The suffixes **`t`** and
|
||||||
|
**`v`** cannot be used together.
|
||||||
|
|
||||||
|
Wrapping is **not eager**. It doesn't wrap a line when it can fit on 72 columns. It also tolerates longer lines up
|
||||||
|
to 112 columns, when the output is considered to be more readable that way. This means very simple Go objects
|
||||||
|
are not wrapped even with the **`w`** variant of the functions.
|
||||||
|
|
||||||
|
For the available functions, see also the [godoc](https://godoc.org/github.com/aryszka/notation).
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
Assuming to have the required types defined, if we do the following:
|
||||||
|
|
||||||
|
```go
|
||||||
|
b := bike{
|
||||||
|
frame: frame{
|
||||||
|
fork: fork{},
|
||||||
|
saddlePost: saddlePost{},
|
||||||
|
},
|
||||||
|
driveTrain: driveTrain{
|
||||||
|
bottomBracket: bracket{},
|
||||||
|
crank: crank{wheels: 2},
|
||||||
|
brakes: []brake{{discSize: 160}, {discSize: 140}},
|
||||||
|
derailleurs: []derailleur{{gears: 2}, {gears: 11}},
|
||||||
|
cassette: cassette{wheels: 11},
|
||||||
|
chain: chain{},
|
||||||
|
levers: []lever{{true}, {true}},
|
||||||
|
},
|
||||||
|
wheels: []wheel{{size: 70}, {size: 70}},
|
||||||
|
handlebar: handlebar{},
|
||||||
|
saddle: saddle{},
|
||||||
|
}
|
||||||
|
|
||||||
|
b.frame.fork.wheel = &b.wheels[0]
|
||||||
|
b.frame.fork.handlebar = &b.handlebar
|
||||||
|
b.frame.fork.handlebar.levers = []*lever{&b.driveTrain.levers[0], &b.driveTrain.levers[1]}
|
||||||
|
b.frame.fork.frontBrake = &b.driveTrain.brakes[0]
|
||||||
|
b.frame.saddlePost.saddle = &b.saddle
|
||||||
|
b.frame.bottomBracket = &b.driveTrain.bottomBracket
|
||||||
|
b.frame.frontDerailleur = &b.driveTrain.derailleurs[0]
|
||||||
|
b.frame.rearDerailleur = &b.driveTrain.derailleurs[1]
|
||||||
|
b.frame.rearBrake = &b.driveTrain.brakes[1]
|
||||||
|
b.frame.rearWheel = &b.wheels[1]
|
||||||
|
b.frame.bottomBracket.crank = &b.driveTrain.crank
|
||||||
|
b.frame.bottomBracket.crank.chain = &b.driveTrain.chain
|
||||||
|
b.frame.rearWheel.cassette = &b.driveTrain.cassette
|
||||||
|
b.frame.rearWheel.cassette.chain = &b.driveTrain.chain
|
||||||
|
|
||||||
|
s := notation.Sprintw(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
We get the following string:
|
||||||
|
|
||||||
|
```go
|
||||||
|
{
|
||||||
|
frame: {
|
||||||
|
fork: {
|
||||||
|
wheel: {size: 70, cassette: nil},
|
||||||
|
handlebar: {levers: []{{withShift: true}, {withShift: true}}},
|
||||||
|
frontBrake: {discSize: 160},
|
||||||
|
},
|
||||||
|
saddlePost: {saddle: {}},
|
||||||
|
bottomBracket: {crank: {wheels: 2, chain: {}}},
|
||||||
|
frontDerailleur: {gears: 2},
|
||||||
|
rearDerailleur: {gears: 11},
|
||||||
|
rearBrake: {discSize: 140},
|
||||||
|
rearWheel: {size: 70, cassette: {wheels: 11, chain: {}}},
|
||||||
|
},
|
||||||
|
driveTrain: {
|
||||||
|
bottomBracket: {crank: {wheels: 2, chain: {}}},
|
||||||
|
crank: {wheels: 2, chain: {}},
|
||||||
|
brakes: []{{discSize: 160}, {discSize: 140}},
|
||||||
|
derailleurs: []{{gears: 2}, {gears: 11}},
|
||||||
|
cassette: {wheels: 11, chain: {}},
|
||||||
|
chain: {},
|
||||||
|
levers: []{{withShift: true}, {withShift: true}},
|
||||||
|
},
|
||||||
|
wheels: []{{size: 70, cassette: nil}, {size: 70, cassette: {wheels: 11, chain: {}}}},
|
||||||
|
handlebar: {levers: []{{withShift: true}, {withShift: true}}},
|
||||||
|
saddle: {},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `notation.Sprintwv` instead of `notation.Sprintw`, we would get the following string:
|
||||||
|
|
||||||
|
```go
|
||||||
|
bike{
|
||||||
|
frame: frame{
|
||||||
|
fork: fork{
|
||||||
|
wheel: *wheel{size: float64(70), cassette: (*cassette)(nil)},
|
||||||
|
handlebar: *handlebar{
|
||||||
|
levers: []*lever{
|
||||||
|
*lever{withShift: bool(true)},
|
||||||
|
*lever{withShift: bool(true)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
frontBrake: *brake{discSize: float64(160)},
|
||||||
|
},
|
||||||
|
saddlePost: saddlePost{saddle: *saddle{}},
|
||||||
|
bottomBracket: *bracket{crank: *crank{wheels: int(2), chain: *chain{}}},
|
||||||
|
frontDerailleur: *derailleur{gears: int(2)},
|
||||||
|
rearDerailleur: *derailleur{gears: int(11)},
|
||||||
|
rearBrake: *brake{discSize: float64(140)},
|
||||||
|
rearWheel: *wheel{
|
||||||
|
size: float64(70),
|
||||||
|
cassette: *cassette{wheels: int(11), chain: *chain{}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
driveTrain: driveTrain{
|
||||||
|
bottomBracket: bracket{crank: *crank{wheels: int(2), chain: *chain{}}},
|
||||||
|
crank: crank{wheels: int(2), chain: *chain{}},
|
||||||
|
brakes: []brake{brake{discSize: float64(160)}, brake{discSize: float64(140)}},
|
||||||
|
derailleurs: []derailleur{
|
||||||
|
derailleur{gears: int(2)},
|
||||||
|
derailleur{gears: int(11)},
|
||||||
|
},
|
||||||
|
cassette: cassette{wheels: int(11), chain: *chain{}},
|
||||||
|
chain: chain{},
|
||||||
|
levers: []lever{lever{withShift: bool(true)}, lever{withShift: bool(true)}},
|
||||||
|
},
|
||||||
|
wheels: []wheel{
|
||||||
|
wheel{size: float64(70), cassette: (*cassette)(nil)},
|
||||||
|
wheel{size: float64(70), cassette: *cassette{wheels: int(11), chain: *chain{}}},
|
||||||
|
},
|
||||||
|
handlebar: handlebar{levers: []*lever{*lever{withShift: bool(true)}, *lever{withShift: bool(true)}}},
|
||||||
|
saddle: saddle{},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Subtleties
|
||||||
|
|
||||||
|
Notation doesn't provide configuration options, we can just pick the preferred function and call it with the
|
||||||
|
objects to be printed. The following details describe some of the behavior to be expected in case of various
|
||||||
|
input objects.
|
||||||
|
|
||||||
|
##### Numbers
|
||||||
|
|
||||||
|
Numbers are printed based on the `fmt` package's default formatting. When printing with moderate type
|
||||||
|
information, the type for the `int`, default witdth signed integers, will be omitted.
|
||||||
|
|
||||||
|
```go
|
||||||
|
i := 42
|
||||||
|
notation.Printlnt(i)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
42
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Strings
|
||||||
|
|
||||||
|
When printing strings, by default they are escaped using the `strconv.Quote` function. However, when wrapping
|
||||||
|
long strings, and the string contains a newline and doesn't contain a backquote '`', then the string is printed
|
||||||
|
as a raw string literal, delimited by '`'.
|
||||||
|
|
||||||
|
Short string:
|
||||||
|
|
||||||
|
```go
|
||||||
|
s := `foobar
|
||||||
|
baz`
|
||||||
|
notation.Printlnw(s)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
"foobar\nbaz"
|
||||||
|
```
|
||||||
|
|
||||||
|
Long string:
|
||||||
|
|
||||||
|
```go
|
||||||
|
s := `The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
||||||
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
||||||
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog.`
|
||||||
|
|
||||||
|
notation.Println(s)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
`The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
||||||
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
||||||
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog.`
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Arrays/Slices
|
||||||
|
|
||||||
|
Slices are are printed by printing their elements between braces, prefixed either by '[]' or the type of the
|
||||||
|
slice. Example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
l := []int{1, 2, 3}
|
||||||
|
notation.Println(l)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
[]{1, 2, 3}
|
||||||
|
```
|
||||||
|
|
||||||
|
To differentiate arrays from slices, arrays are always prefixed with their type or square brackets containing
|
||||||
|
the length of the array:
|
||||||
|
|
||||||
|
```go
|
||||||
|
a := [...]{1, 2, 3}
|
||||||
|
notation.Println(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
[3]{1, 2, 3}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Bytes
|
||||||
|
|
||||||
|
When the type of a slice is `uint8`, or an alias of it, e.g. `byte`, then it is printed as []byte, with the hexa
|
||||||
|
representation of its bytes:
|
||||||
|
|
||||||
|
```go
|
||||||
|
b := []byte(
|
||||||
|
`The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
||||||
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
||||||
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog.`,
|
||||||
|
)
|
||||||
|
|
||||||
|
notation.Printlnwt(b)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
[]byte{
|
||||||
|
54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a
|
||||||
|
75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f
|
||||||
|
67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f
|
||||||
|
78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79
|
||||||
|
20 64 6f 67 2e 20 54 68 65 0a 71 75 69 63 6b 20 62 72 6f 77 6e
|
||||||
|
20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c
|
||||||
|
61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72
|
||||||
|
6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68
|
||||||
|
65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b
|
||||||
|
20 62 72 6f 77 6e 0a 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72
|
||||||
|
20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75
|
||||||
|
69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f
|
||||||
|
76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65
|
||||||
|
20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70
|
||||||
|
73 0a 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20
|
||||||
|
54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a
|
||||||
|
75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f
|
||||||
|
67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f
|
||||||
|
78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79
|
||||||
|
0a 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e
|
||||||
|
20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c
|
||||||
|
61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72
|
||||||
|
6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68
|
||||||
|
65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 0a 71 75 69 63 6b
|
||||||
|
20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72
|
||||||
|
20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Maps
|
||||||
|
|
||||||
|
Maps are printed with their entries sorted by the string representation of their keys:
|
||||||
|
|
||||||
|
```go
|
||||||
|
m := map[string]int{"b": 1, "c": 2, "a": 3}
|
||||||
|
notation.Println(m)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
map{"a": 3, "b": 1, "c": 2}
|
||||||
|
```
|
||||||
|
|
||||||
|
This way a map is printed always the same way. If, for a reason, this is undesired, then this behavior can be
|
||||||
|
disabled via the `MAPSORT=0` environment variable.
|
||||||
|
|
||||||
|
##### Hidden values: channels, functions
|
||||||
|
|
||||||
|
Certain values, like channels and functions are printed without expanding their internals, e.g. channee state or
|
||||||
|
function body. When printing with types, the signature of these objects is printed:
|
||||||
|
|
||||||
|
```go
|
||||||
|
f := func(int) int { return 42 }
|
||||||
|
notation.Println(f)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func()
|
||||||
|
```
|
||||||
|
|
||||||
|
With types:
|
||||||
|
|
||||||
|
```go
|
||||||
|
f := func(int) int { return 42 }
|
||||||
|
notation.Printlnt(f)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func(int) int
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Wrapping
|
||||||
|
|
||||||
|
Whe 'w' variant of the printing functions wraps the output with Go style indentation where the lines would be
|
||||||
|
too long otherwise. The wrapping is not eager, it only aims for fitting the lines on 72 columns. To measure the
|
||||||
|
indentation, it assumes 8 character width tabs. In certain cases, it tolerates longer lines up to 112 columns,
|
||||||
|
when the output would probably more readable that way. Of course, readability is subjective.
|
||||||
|
|
||||||
|
As a hidden feature, when it's really necessary, it is possible to change the above control values via
|
||||||
|
environmetn variables. TABWIDTH controls the measuring of the indentation. LINEWIDTH sets the aimed column width
|
||||||
|
of the printed lines. LINEWIDTH1 sets the tolerated threshold for those lines that are allowed to exceed the
|
||||||
|
default line width. E.g. if somebody uses two-character wide tabs in their console, they can use the package
|
||||||
|
like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
TABWIDTH=2 go test -v -count 1
|
||||||
|
```
|
||||||
|
|
||||||
|
As a consequence, it is also possible to wrap all lines:
|
||||||
|
|
||||||
|
```
|
||||||
|
TABWIDTH=0 LINEWIDTH=0 LINEWIDTH1=0 go test -v -count 1
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Types
|
||||||
|
|
||||||
|
Using the 't' or 'v' suffixed variants of the printing functions, notation prints the types together with the
|
||||||
|
values. When the name of a type is available, the name is printed instead of the literal representation of the
|
||||||
|
type. The package path is not printed.
|
||||||
|
|
||||||
|
Named type:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type t struct{foo int}
|
||||||
|
v := t{42}
|
||||||
|
notation.Printlnt(v)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
t{foo: 42}
|
||||||
|
```
|
||||||
|
|
||||||
|
Unnamed type:
|
||||||
|
|
||||||
|
```go
|
||||||
|
v := struct{foo int}{42}
|
||||||
|
notation.Printlnt(v)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
struct{foo int}{foo: 42}
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the 't' suffixed variants of the printing functions, displaying only moderately verbose type information,
|
||||||
|
the types of certain values is omitted, where it can be inferred from the context:
|
||||||
|
|
||||||
|
```go
|
||||||
|
v := []struct{foo int}{{42}, {84}}
|
||||||
|
notation.Printlnt(os.Stdout, v)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
[]struct{foo int}{{foo: 42}, {foo: 84}}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Cyclic references
|
||||||
|
|
||||||
|
Cyclic references are detected based on an approach similar to the one in the stdlib's reflect.DeepEqual
|
||||||
|
function. Such occurences are displayed in the output with references:
|
||||||
|
|
||||||
|
```go
|
||||||
|
l := []interface{}{"foo"}
|
||||||
|
l[0] = l
|
||||||
|
notation.Fprint(os.Stdout, l)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
```go
|
||||||
|
r0=[]{r0}
|
||||||
|
```
|
292
example_test.go
Normal file
292
example_test.go
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
package notation_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/aryszka/notation"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bike struct {
|
||||||
|
frame frame
|
||||||
|
driveTrain driveTrain
|
||||||
|
wheels []wheel
|
||||||
|
handlebar handlebar
|
||||||
|
saddle saddle
|
||||||
|
}
|
||||||
|
type frame struct {
|
||||||
|
fork fork
|
||||||
|
saddlePost saddlePost
|
||||||
|
bottomBracket *bracket
|
||||||
|
frontDerailleur *derailleur
|
||||||
|
rearDerailleur *derailleur
|
||||||
|
rearBrake *brake
|
||||||
|
rearWheel *wheel
|
||||||
|
}
|
||||||
|
type driveTrain struct {
|
||||||
|
bottomBracket bracket
|
||||||
|
crank crank
|
||||||
|
brakes []brake
|
||||||
|
derailleurs []derailleur
|
||||||
|
cassette cassette
|
||||||
|
chain chain
|
||||||
|
levers []lever
|
||||||
|
}
|
||||||
|
type wheel struct {
|
||||||
|
size float64
|
||||||
|
cassette *cassette
|
||||||
|
}
|
||||||
|
type handlebar struct{ levers []*lever }
|
||||||
|
type saddle struct{}
|
||||||
|
type fork struct {
|
||||||
|
wheel *wheel
|
||||||
|
handlebar *handlebar
|
||||||
|
frontBrake *brake
|
||||||
|
}
|
||||||
|
type saddlePost struct{ saddle *saddle }
|
||||||
|
type bracket struct{ crank *crank }
|
||||||
|
type derailleur struct{ gears int }
|
||||||
|
type brake struct{ discSize float64 }
|
||||||
|
type crank struct {
|
||||||
|
wheels int
|
||||||
|
chain *chain
|
||||||
|
}
|
||||||
|
type cassette struct {
|
||||||
|
wheels int
|
||||||
|
chain *chain
|
||||||
|
}
|
||||||
|
type chain struct{}
|
||||||
|
type lever struct{ withShift bool }
|
||||||
|
|
||||||
|
func Example() {
|
||||||
|
b := bike{
|
||||||
|
frame: frame{
|
||||||
|
fork: fork{},
|
||||||
|
saddlePost: saddlePost{},
|
||||||
|
},
|
||||||
|
driveTrain: driveTrain{
|
||||||
|
bottomBracket: bracket{},
|
||||||
|
crank: crank{wheels: 2},
|
||||||
|
brakes: []brake{{discSize: 160}, {discSize: 140}},
|
||||||
|
derailleurs: []derailleur{{gears: 2}, {gears: 11}},
|
||||||
|
cassette: cassette{wheels: 11},
|
||||||
|
chain: chain{},
|
||||||
|
levers: []lever{{true}, {true}},
|
||||||
|
},
|
||||||
|
wheels: []wheel{{size: 70}, {size: 70}},
|
||||||
|
handlebar: handlebar{},
|
||||||
|
saddle: saddle{},
|
||||||
|
}
|
||||||
|
|
||||||
|
b.frame.fork.wheel = &b.wheels[0]
|
||||||
|
b.frame.fork.handlebar = &b.handlebar
|
||||||
|
b.frame.fork.handlebar.levers = []*lever{&b.driveTrain.levers[0], &b.driveTrain.levers[1]}
|
||||||
|
b.frame.fork.frontBrake = &b.driveTrain.brakes[0]
|
||||||
|
b.frame.saddlePost.saddle = &b.saddle
|
||||||
|
b.frame.bottomBracket = &b.driveTrain.bottomBracket
|
||||||
|
b.frame.frontDerailleur = &b.driveTrain.derailleurs[0]
|
||||||
|
b.frame.rearDerailleur = &b.driveTrain.derailleurs[1]
|
||||||
|
b.frame.rearBrake = &b.driveTrain.brakes[1]
|
||||||
|
b.frame.rearWheel = &b.wheels[1]
|
||||||
|
b.frame.bottomBracket.crank = &b.driveTrain.crank
|
||||||
|
b.frame.bottomBracket.crank.chain = &b.driveTrain.chain
|
||||||
|
b.frame.rearWheel.cassette = &b.driveTrain.cassette
|
||||||
|
b.frame.rearWheel.cassette.chain = &b.driveTrain.chain
|
||||||
|
|
||||||
|
notation.Fprintw(os.Stdout, b)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// frame: {
|
||||||
|
// fork: {
|
||||||
|
// wheel: {size: 70, cassette: nil},
|
||||||
|
// handlebar: {levers: []{{withShift: true}, {withShift: true}}},
|
||||||
|
// frontBrake: {discSize: 160},
|
||||||
|
// },
|
||||||
|
// saddlePost: {saddle: {}},
|
||||||
|
// bottomBracket: {crank: {wheels: 2, chain: {}}},
|
||||||
|
// frontDerailleur: {gears: 2},
|
||||||
|
// rearDerailleur: {gears: 11},
|
||||||
|
// rearBrake: {discSize: 140},
|
||||||
|
// rearWheel: {size: 70, cassette: {wheels: 11, chain: {}}},
|
||||||
|
// },
|
||||||
|
// driveTrain: {
|
||||||
|
// bottomBracket: {crank: {wheels: 2, chain: {}}},
|
||||||
|
// crank: {wheels: 2, chain: {}},
|
||||||
|
// brakes: []{{discSize: 160}, {discSize: 140}},
|
||||||
|
// derailleurs: []{{gears: 2}, {gears: 11}},
|
||||||
|
// cassette: {wheels: 11, chain: {}},
|
||||||
|
// chain: {},
|
||||||
|
// levers: []{{withShift: true}, {withShift: true}},
|
||||||
|
// },
|
||||||
|
// wheels: []{{size: 70, cassette: nil}, {size: 70, cassette: {wheels: 11, chain: {}}}},
|
||||||
|
// handlebar: {levers: []{{withShift: true}, {withShift: true}}},
|
||||||
|
// saddle: {},
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_int() {
|
||||||
|
i := 42
|
||||||
|
notation.Fprintt(os.Stdout, i)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// 42
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_short_string() {
|
||||||
|
s := `foobar
|
||||||
|
baz`
|
||||||
|
notation.Fprintw(os.Stdout, s)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// "foobar\nbaz"
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_long_string() {
|
||||||
|
s := `The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
||||||
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
||||||
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog.`
|
||||||
|
|
||||||
|
notation.Fprintw(os.Stdout, s)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// `The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
// quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
// fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
||||||
|
// over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
||||||
|
// dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
// quick brown fox jumps over the lazy dog.`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_slice() {
|
||||||
|
l := []int{1, 2, 3}
|
||||||
|
notation.Fprint(os.Stdout, l)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// []{1, 2, 3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_array() {
|
||||||
|
a := [...]int{1, 2, 3}
|
||||||
|
notation.Fprint(os.Stdout, a)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// [3]{1, 2, 3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_bytes() {
|
||||||
|
b := []byte(
|
||||||
|
`The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown
|
||||||
|
fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps
|
||||||
|
over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy
|
||||||
|
dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The
|
||||||
|
quick brown fox jumps over the lazy dog.`,
|
||||||
|
)
|
||||||
|
|
||||||
|
notation.Fprintwt(os.Stdout, b)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// []byte{
|
||||||
|
// 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a
|
||||||
|
// 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f
|
||||||
|
// 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f
|
||||||
|
// 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79
|
||||||
|
// 20 64 6f 67 2e 20 54 68 65 0a 71 75 69 63 6b 20 62 72 6f 77 6e
|
||||||
|
// 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c
|
||||||
|
// 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72
|
||||||
|
// 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68
|
||||||
|
// 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b
|
||||||
|
// 20 62 72 6f 77 6e 0a 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72
|
||||||
|
// 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75
|
||||||
|
// 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f
|
||||||
|
// 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65
|
||||||
|
// 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70
|
||||||
|
// 73 0a 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e 20
|
||||||
|
// 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f 78 20 6a
|
||||||
|
// 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79 20 64 6f
|
||||||
|
// 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e 20 66 6f
|
||||||
|
// 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c 61 7a 79
|
||||||
|
// 0a 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72 6f 77 6e
|
||||||
|
// 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68 65 20 6c
|
||||||
|
// 61 7a 79 20 64 6f 67 2e 20 54 68 65 20 71 75 69 63 6b 20 62 72
|
||||||
|
// 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72 20 74 68
|
||||||
|
// 65 20 6c 61 7a 79 20 64 6f 67 2e 20 54 68 65 0a 71 75 69 63 6b
|
||||||
|
// 20 62 72 6f 77 6e 20 66 6f 78 20 6a 75 6d 70 73 20 6f 76 65 72
|
||||||
|
// 20 74 68 65 20 6c 61 7a 79 20 64 6f 67 2e
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_maps_sorted_by_keys() {
|
||||||
|
m := map[string]int{"b": 1, "c": 2, "a": 3}
|
||||||
|
notation.Fprint(os.Stdout, m)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// map{"a": 3, "b": 1, "c": 2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_function() {
|
||||||
|
f := func(int) int { return 42 }
|
||||||
|
notation.Fprint(os.Stdout, f)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// func()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_function_signature() {
|
||||||
|
f := func(int) int { return 42 }
|
||||||
|
notation.Fprintt(os.Stdout, f)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// func(int) int
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_named_type() {
|
||||||
|
type t struct{ foo int }
|
||||||
|
v := t{42}
|
||||||
|
notation.Fprintt(os.Stdout, v)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// t{foo: 42}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_unnamed() {
|
||||||
|
v := struct{ foo int }{42}
|
||||||
|
notation.Fprintt(os.Stdout, v)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// struct{foo int}{foo: 42}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_type_inferred() {
|
||||||
|
v := []struct{ foo int }{{42}, {84}}
|
||||||
|
notation.Fprintt(os.Stdout, v)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// []struct{foo int}{{foo: 42}, {foo: 84}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Example_cyclic_reference() {
|
||||||
|
l := []interface{}{"foo"}
|
||||||
|
l[0] = l
|
||||||
|
notation.Fprint(os.Stdout, l)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
//
|
||||||
|
// r0=[]{r0}
|
||||||
|
}
|
54
notation.go
54
notation.go
@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
Package notation can be used to print (or sprint) Go objects with optional wrapping (pretty printing) and
|
||||||
|
optional type information.
|
||||||
|
*/
|
||||||
package notation
|
package notation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -199,98 +203,148 @@ func sprintValues(o opts, v []interface{}) string {
|
|||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fprint prints the provided objects to the provided writer. When multiple objects are printed, they'll be
|
||||||
|
// separated by a space.
|
||||||
func Fprint(w io.Writer, v ...interface{}) (int, error) {
|
func Fprint(w io.Writer, v ...interface{}) (int, error) {
|
||||||
return fprintValues(w, none, v)
|
return fprintValues(w, none, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fprintw prints the provided objects to the provided writer, with wrapping (pretty-printing) where necessary.
|
||||||
|
// When multiple objects are printed, they'll be separated by a newline.
|
||||||
func Fprintw(w io.Writer, v ...interface{}) (int, error) {
|
func Fprintw(w io.Writer, v ...interface{}) (int, error) {
|
||||||
return fprintValues(w, wrap, v)
|
return fprintValues(w, wrap, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fprintt prints the provided objects to the provided writer with moderate type information. When multiple
|
||||||
|
// objects are printed, they'll be separated by a space.
|
||||||
func Fprintt(w io.Writer, v ...interface{}) (int, error) {
|
func Fprintt(w io.Writer, v ...interface{}) (int, error) {
|
||||||
return fprintValues(w, types, v)
|
return fprintValues(w, types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fprintwt prints the provided objects to the provided writer, with wrapping (pretty-printing) where necessary,
|
||||||
|
// and with moderate type information. When multiple objects are printed, they'll be separated by a newline.
|
||||||
func Fprintwt(w io.Writer, v ...interface{}) (int, error) {
|
func Fprintwt(w io.Writer, v ...interface{}) (int, error) {
|
||||||
return fprintValues(w, wrap|types, v)
|
return fprintValues(w, wrap|types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fprintv prints the provided objects to the provided writer with verbose type information. When multiple
|
||||||
|
// objects are printed, they'll be separated by a space.
|
||||||
func Fprintv(w io.Writer, v ...interface{}) (int, error) {
|
func Fprintv(w io.Writer, v ...interface{}) (int, error) {
|
||||||
return fprintValues(w, allTypes, v)
|
return fprintValues(w, allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fprintwv prints the provided objects to the provided writer, with wrapping (pretty-printing) where necessary,
|
||||||
|
// and with verbose type information. When multiple objects are printed, they'll be separated by a newline.
|
||||||
func Fprintwv(w io.Writer, v ...interface{}) (int, error) {
|
func Fprintwv(w io.Writer, v ...interface{}) (int, error) {
|
||||||
return fprintValues(w, wrap|allTypes, v)
|
return fprintValues(w, wrap|allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print prints the provided objects to stderr. When multiple objects are printed, they'll be separated by a
|
||||||
|
// space.
|
||||||
func Print(v ...interface{}) (int, error) {
|
func Print(v ...interface{}) (int, error) {
|
||||||
return printValues(none, v)
|
return printValues(none, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printw prints the provided objects to stderr, with wrapping (pretty-printing) where necessary. When multiple
|
||||||
|
// objects are printed, they'll be separated by a newline.
|
||||||
func Printw(v ...interface{}) (int, error) {
|
func Printw(v ...interface{}) (int, error) {
|
||||||
return printValues(wrap, v)
|
return printValues(wrap, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printt prints the provided objects to stderr with moderate type information. When multiple objects are
|
||||||
|
// printed, they'll be separated by a space.
|
||||||
func Printt(v ...interface{}) (int, error) {
|
func Printt(v ...interface{}) (int, error) {
|
||||||
return printValues(types, v)
|
return printValues(types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printwt prints the provided objects to stderr, with wrapping (pretty-printing) where necessary, and with
|
||||||
|
// moderate type information. When multiple objects are printed, they'll be separated by a newline.
|
||||||
func Printwt(v ...interface{}) (int, error) {
|
func Printwt(v ...interface{}) (int, error) {
|
||||||
return printValues(wrap|types, v)
|
return printValues(wrap|types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printv prints the provided objects to stderr with verbose type information. When multiple objects are
|
||||||
|
// printed, they'll be separated by a space.
|
||||||
func Printv(v ...interface{}) (int, error) {
|
func Printv(v ...interface{}) (int, error) {
|
||||||
return printValues(allTypes, v)
|
return printValues(allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printwv prints the provided objects to stderr, with wrapping (pretty-printing) where necessary, and with
|
||||||
|
// verbose type information. When multiple objects are printed, they'll be separated by a newline.
|
||||||
func Printwv(v ...interface{}) (int, error) {
|
func Printwv(v ...interface{}) (int, error) {
|
||||||
return printValues(wrap|allTypes, v)
|
return printValues(wrap|allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Println prints the provided objects to stderr with a closing newline. When multiple objects are printed,
|
||||||
|
// they'll be separated by a space.
|
||||||
func Println(v ...interface{}) (int, error) {
|
func Println(v ...interface{}) (int, error) {
|
||||||
return printlnValues(none, v)
|
return printlnValues(none, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printlnw prints the provided objects to stderr with a closing newline, with wrapping (pretty-printing) where
|
||||||
|
// necessary. When multiple objects are printed, they'll be separated by a newline.
|
||||||
func Printlnw(v ...interface{}) (int, error) {
|
func Printlnw(v ...interface{}) (int, error) {
|
||||||
return printlnValues(wrap, v)
|
return printlnValues(wrap, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printlnt prints the provided objects to stderr with a closing newline, and with moderate type information. When
|
||||||
|
// multiple objects are printed, they'll be separated by a space.
|
||||||
func Printlnt(v ...interface{}) (int, error) {
|
func Printlnt(v ...interface{}) (int, error) {
|
||||||
return printlnValues(types, v)
|
return printlnValues(types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printlnwt prints the provided objects to stderr with a closing newline, with wrapping (pretty-printing) where
|
||||||
|
// necessary, and with moderate type information. When multiple objects are printed, they'll be separated by a
|
||||||
|
// newline.
|
||||||
func Printlnwt(v ...interface{}) (int, error) {
|
func Printlnwt(v ...interface{}) (int, error) {
|
||||||
return printlnValues(wrap|types, v)
|
return printlnValues(wrap|types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printlnv prints the provided objects to stderr with a closing newline, and with verbose type information. When
|
||||||
|
// multiple objects are printed, they'll be separated by a space.
|
||||||
func Printlnv(v ...interface{}) (int, error) {
|
func Printlnv(v ...interface{}) (int, error) {
|
||||||
return printlnValues(allTypes, v)
|
return printlnValues(allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Printlnwv prints the provided objects to stderr with a closing newline, with wrapping (pretty-printing) where
|
||||||
|
// necessary, and with verbose type information. When multiple objects are printed, they'll be separated by a
|
||||||
|
// newline.
|
||||||
func Printlnwv(v ...interface{}) (int, error) {
|
func Printlnwv(v ...interface{}) (int, error) {
|
||||||
return printlnValues(wrap|allTypes, v)
|
return printlnValues(wrap|allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint returns the string representation of the Go objects. When multiple objects are provided, they'll be
|
||||||
|
// seprated by a space.
|
||||||
func Sprint(v ...interface{}) string {
|
func Sprint(v ...interface{}) string {
|
||||||
return sprintValues(none, v)
|
return sprintValues(none, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint returns the string representation of the Go objects, with wrapping (pretty-printing) where necessary.
|
||||||
|
// When multiple objects are provided, they'll be seprated by a newline.
|
||||||
func Sprintw(v ...interface{}) string {
|
func Sprintw(v ...interface{}) string {
|
||||||
return sprintValues(wrap, v)
|
return sprintValues(wrap, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint returns the string representation of the Go objects, with moderate type information. When multiple
|
||||||
|
// objects are provided, they'll be seprated by a space.
|
||||||
func Sprintt(v ...interface{}) string {
|
func Sprintt(v ...interface{}) string {
|
||||||
return sprintValues(types, v)
|
return sprintValues(types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint returns the string representation of the Go objects, with wrapping (pretty-printing) where necessary,
|
||||||
|
// and with moderate type information. When multiple objects are provided, they'll be seprated by a newline.
|
||||||
func Sprintwt(v ...interface{}) string {
|
func Sprintwt(v ...interface{}) string {
|
||||||
return sprintValues(wrap|types, v)
|
return sprintValues(wrap|types, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint returns the string representation of the Go objects, with verbose type information. When multiple
|
||||||
|
// objects are provided, they'll be seprated by a space.
|
||||||
func Sprintv(v ...interface{}) string {
|
func Sprintv(v ...interface{}) string {
|
||||||
return sprintValues(allTypes, v)
|
return sprintValues(allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sprint returns the string representation of the Go objects, with wrapping (pretty-printing) where necessary,
|
||||||
|
// and with verbose type information. When multiple objects are provided, they'll be seprated by a newline.
|
||||||
func Sprintwv(v ...interface{}) string {
|
func Sprintwv(v ...interface{}) string {
|
||||||
return sprintValues(wrap|allTypes, v)
|
return sprintValues(wrap|allTypes, v)
|
||||||
}
|
}
|
||||||
|
36
reflect.go
36
reflect.go
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -136,12 +137,7 @@ func reflectMap(o opts, p *pending, r reflect.Value) node {
|
|||||||
return reflectNil(o, true, r)
|
return reflectNil(o, true, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var skeys []string
|
||||||
nkeys []node
|
|
||||||
skeys []string
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: simplify this when no sorting is required
|
|
||||||
items := wrapper{sep: ", ", suffix: ","}
|
items := wrapper{sep: ", ", suffix: ","}
|
||||||
itemOpts := o | skipTypes
|
itemOpts := o | skipTypes
|
||||||
keys := r.MapKeys()
|
keys := r.MapKeys()
|
||||||
@ -150,7 +146,6 @@ func reflectMap(o opts, p *pending, r reflect.Value) node {
|
|||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
nk := reflectValue(itemOpts, p, key)
|
nk := reflectValue(itemOpts, p, key)
|
||||||
nkeys = append(nkeys, nk)
|
|
||||||
wr := writer{w: &b}
|
wr := writer{w: &b}
|
||||||
fprint(&wr, 0, nk)
|
fprint(&wr, 0, nk)
|
||||||
skey := b.String()
|
skey := b.String()
|
||||||
@ -208,32 +203,7 @@ func reflectList(o opts, p *pending, r reflect.Value) node {
|
|||||||
|
|
||||||
func reflectString(o opts, r reflect.Value) node {
|
func reflectString(o opts, r reflect.Value) node {
|
||||||
sv := r.String()
|
sv := r.String()
|
||||||
b := []byte(sv)
|
s := str{val: strconv.Quote(sv)}
|
||||||
e := make([]byte, 0, len(b))
|
|
||||||
for _, c := range b {
|
|
||||||
switch c {
|
|
||||||
case '\\':
|
|
||||||
e = append(e, '\\', '\\')
|
|
||||||
case '"':
|
|
||||||
e = append(e, '\\', '"')
|
|
||||||
case '\b':
|
|
||||||
e = append(e, '\\', 'b')
|
|
||||||
case '\f':
|
|
||||||
e = append(e, '\\', 'f')
|
|
||||||
case '\n':
|
|
||||||
e = append(e, '\\', 'n')
|
|
||||||
case '\r':
|
|
||||||
e = append(e, '\\', 'r')
|
|
||||||
case '\t':
|
|
||||||
e = append(e, '\\', 't')
|
|
||||||
case '\v':
|
|
||||||
e = append(e, '\\', 'v')
|
|
||||||
default:
|
|
||||||
e = append(e, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s := str{val: fmt.Sprintf("\"%s\"", string(e))}
|
|
||||||
if !strings.Contains(sv, "`") && strings.Contains(sv, "\n") {
|
if !strings.Contains(sv, "`") && strings.Contains(sv, "\n") {
|
||||||
s.raw = fmt.Sprintf("`%s`", sv)
|
s.raw = fmt.Sprintf("`%s`", sv)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user