| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- // Copyright 2013 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package pretty
- import (
- "bytes"
- "fmt"
- "io"
- "net"
- "reflect"
- "time"
- "github.com/kylelemons/godebug/diff"
- )
- // A Config represents optional configuration parameters for formatting.
- //
- // Some options, notably ShortList, dramatically increase the overhead
- // of pretty-printing a value.
- type Config struct {
- // Verbosity options
- Compact bool // One-line output. Overrides Diffable.
- Diffable bool // Adds extra newlines for more easily diffable output.
- // Field and value options
- IncludeUnexported bool // Include unexported fields in output
- PrintStringers bool // Call String on a fmt.Stringer
- PrintTextMarshalers bool // Call MarshalText on an encoding.TextMarshaler
- SkipZeroFields bool // Skip struct fields that have a zero value.
- // Output transforms
- ShortList int // Maximum character length for short lists if nonzero.
- // Type-specific overrides
- //
- // Formatter maps a type to a function that will provide a one-line string
- // representation of the input value. Conceptually:
- // Formatter[reflect.TypeOf(v)](v) = "v as a string"
- //
- // Note that the first argument need not explicitly match the type, it must
- // merely be callable with it.
- //
- // When processing an input value, if its type exists as a key in Formatter:
- // 1) If the value is nil, no stringification is performed.
- // This allows overriding of PrintStringers and PrintTextMarshalers.
- // 2) The value will be called with the input as its only argument.
- // The function must return a string as its first return value.
- //
- // In addition to func literals, two common values for this will be:
- // fmt.Sprint (function) func Sprint(...interface{}) string
- // Type.String (method) func (Type) String() string
- //
- // Note that neither of these work if the String method is a pointer
- // method and the input will be provided as a value. In that case,
- // use a function that calls .String on the formal value parameter.
- Formatter map[reflect.Type]interface{}
- }
- // Default Config objects
- var (
- // DefaultFormatter is the default set of overrides for stringification.
- DefaultFormatter = map[reflect.Type]interface{}{
- reflect.TypeOf(time.Time{}): fmt.Sprint,
- reflect.TypeOf(net.IP{}): fmt.Sprint,
- reflect.TypeOf((*error)(nil)).Elem(): fmt.Sprint,
- }
- // CompareConfig is the default configuration used for Compare.
- CompareConfig = &Config{
- Diffable: true,
- IncludeUnexported: true,
- Formatter: DefaultFormatter,
- }
- // DefaultConfig is the default configuration used for all other top-level functions.
- DefaultConfig = &Config{
- Formatter: DefaultFormatter,
- }
- )
- func (cfg *Config) fprint(buf *bytes.Buffer, vals ...interface{}) {
- for i, val := range vals {
- if i > 0 {
- buf.WriteByte('\n')
- }
- cfg.val2node(reflect.ValueOf(val)).WriteTo(buf, "", cfg)
- }
- }
- // Print writes the DefaultConfig representation of the given values to standard output.
- func Print(vals ...interface{}) {
- DefaultConfig.Print(vals...)
- }
- // Print writes the configured presentation of the given values to standard output.
- func (cfg *Config) Print(vals ...interface{}) {
- fmt.Println(cfg.Sprint(vals...))
- }
- // Sprint returns a string representation of the given value according to the DefaultConfig.
- func Sprint(vals ...interface{}) string {
- return DefaultConfig.Sprint(vals...)
- }
- // Sprint returns a string representation of the given value according to cfg.
- func (cfg *Config) Sprint(vals ...interface{}) string {
- buf := new(bytes.Buffer)
- cfg.fprint(buf, vals...)
- return buf.String()
- }
- // Fprint writes the representation of the given value to the writer according to the DefaultConfig.
- func Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
- return DefaultConfig.Fprint(w, vals...)
- }
- // Fprint writes the representation of the given value to the writer according to the cfg.
- func (cfg *Config) Fprint(w io.Writer, vals ...interface{}) (n int64, err error) {
- buf := new(bytes.Buffer)
- cfg.fprint(buf, vals...)
- return buf.WriteTo(w)
- }
- // Compare returns a string containing a line-by-line unified diff of the
- // values in a and b, using the CompareConfig.
- //
- // Each line in the output is prefixed with '+', '-', or ' ' to indicate which
- // side it's from. Lines from the a side are marked with '-', lines from the
- // b side are marked with '+' and lines that are the same on both sides are
- // marked with ' '.
- func Compare(a, b interface{}) string {
- return CompareConfig.Compare(a, b)
- }
- // Compare returns a string containing a line-by-line unified diff of the
- // values in got and want according to the cfg.
- func (cfg *Config) Compare(a, b interface{}) string {
- diffCfg := *cfg
- diffCfg.Diffable = true
- return diff.Diff(cfg.Sprint(a), cfg.Sprint(b))
- }
|