utter

package module
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2024 License: ISC Imports: 14 Imported by: 10

README

utter

Build status Coverage Status

utter is a fork of the outstanding go-spew tool. Where go-spew is an aid for debugging, providing annotation of dumped datastructures, utter is a tool for taking snapshots of data structures to include in tests or other code. An utter dump will not construct cyclic structure literals and a number of pseudo-code representations of pointer-based structures will require subsequent processing.

A comprehensive suite of tests with near 100% test coverage is provided to ensure proper functionality. utter is licensed under the liberal ISC license, so it may be used in open source or commercial projects.

Documentation

GoDoc

Full go doc style documentation for the project can be viewed online without installing this package by using the excellent GoDoc site here: http://godoc.org/github.com/kortschak/utter

You can also view the documentation locally once the package is installed with the godoc tool by running godoc -http=":6060" and pointing your browser to http://localhost:6060/pkg/github.com/kortschak/utter

Installation

$ go get -u github.com/kortschak/utter

Quick Start

To dump a variable with full newlines, indentation, type, and pointer information use Dump, Fdump, or Sdump:

utter.Dump(myVar1)
utter.Fdump(someWriter, myVar1)
str := utter.Sdump(myVar1)

Sample Dump Output

main.Foo{
 unexportedField: &main.Bar{
  flag: main.Flag(1),
  data: uintptr(0),
 },
 ExportedField: map[interface{}]interface{}{
  string("one"): bool(true),
 },
}
[]uint8{
 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // |........|
 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, // |....... |
 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // |!"#$%&'(|
 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, // |)*+,-./0|
 0x31, 0x32, /*                               */ // |12|
}

Configuration Options

Configuration of utter is handled by fields in the ConfigState type. For convenience, all of the top-level functions use a global state available via the utter.Config global.

It is also possible to create a ConfigState instance that provides methods equivalent to the top-level functions. This allows concurrent configuration options. See the ConfigState documentation for more details.

* Indent
	String to use for each indentation level for Dump functions.
	It is a single space by default.  A popular alternative is "\t".

* NumericWidth
	NumericWidth specifies the number of columns to use when dumping
	a numeric slice or array (including bool). Zero specifies all entries
	on one line.

* StringWidth
	StringWidth specifies the number of columns to use when dumping
	a string slice or array. Zero specifies all entries on one line.

* BytesWidth
	Number of byte columns to use when dumping byte slices and arrays.

* CommentBytes
	Specifies whether ASCII comment annotations are attached to byte
	slice and array dumps.

* CommentPointers
	CommentPointers specifies whether pointer information will be added
	as comments.

* IgnoreUnexported
	Specifies that unexported fields should be ignored.

* ElideType
	ElideType specifies that type information defined by context should
	not be printed in a dump.

* OmitZero specifies that zero values should not be printed in a dump.

* SortKeys
	Specifies map keys should be sorted before being printed. Use
	this to have a more deterministic, diffable output.  Note that
	only native types (bool, int, uint, floats, uintptr and string)
	are supported with other types sorted according to the
	reflect.Value.String() output which guarantees display stability.
	Natural map order is used by default.

License

utter is licensed under the liberal ISC License.

Documentation

Overview

Package utter implements a deep pretty printer for Go data structures to aid data snapshotting.

A quick overview of the additional features utter provides over the built-in printing facilities for Go data types are as follows:

  • Pointers are dereferenced and followed
  • Circular data structures are detected and annotated
  • Byte arrays and slices are dumped in a way similar to the hexdump -C command which includes byte values in hex, and ASCII output

The approach utter allows for dumping Go data structures is less flexible than its parent tool. It has just a:

  • Dump style which prints with newlines and customizable indentation

Quick Start

This section demonstrates how to quickly get started with utter. See the sections below for further details on formatting and configuration options.

To dump a variable with full newlines, indentation, type, and pointer information use Dump, Fdump, or Sdump:

utter.Dump(myVar1)
utter.Fdump(someWriter, myVar1)
str := utter.Sdump(myVar1)

Configuration Options

Configuration of utter is handled by fields in the ConfigState type. For convenience, all of the top-level functions use a global state available via the utter.Config global.

It is also possible to create a ConfigState instance that provides methods equivalent to the top-level functions. This allows concurrent configuration options. See the ConfigState documentation for more details.

The following configuration options are available:

  • Indent String to use for each indentation level for Dump functions. It is a single space by default. A popular alternative is "\t".

  • NumericWidth NumericWidth specifies the number of columns to use when dumping a numeric slice or array (including bool). Zero specifies all entries on one line.

  • StringWidth StringWidth specifies the number of columns to use when dumping a string slice or array. Zero specifies all entries on one line.

  • BytesWidth Number of byte columns to use when dumping byte slices and arrays.

  • CommentBytes Specifies whether ASCII comment annotations are attached to byte slice and array dumps.

  • CommentPointers CommentPointers specifies whether pointer information will be added as comments.

  • IgnoreUnexported Specifies that unexported fields should be ignored.

  • ElideType ElideType specifies that type information defined by context should not be printed in a dump.

  • SortKeys Specifies map keys should be sorted before being printed. Use this to have a more deterministic, diffable output. Note that only native types (bool, int, uint, floats, uintptr and string) are supported with other types sorted according to the reflect.Value.String() output which guarantees display stability. Natural map order is used by default.

Dump Usage

Simply call utter.Dump with a list of variables you want to dump:

utter.Dump(myVar1)

You may also call utter.Fdump if you would prefer to output to an arbitrary io.Writer. For example, to dump to standard error:

utter.Fdump(os.Stderr, myVar1)

A third option is to call utter.Sdump to get the formatted output as a string:

str := utter.Sdump(myVar1)

Sample Dump Output

See the Dump example for details on the setup of the types and variables being shown here.

main.Foo{
 unexportedField: &main.Bar{
  flag: main.Flag(1),
  data: uintptr(0),
 },
 ExportedField: map[interface{}]interface{}{
  string("one"): bool(true),
 },
}

Byte (and uint8) arrays and slices are displayed uniquely, similar to the hexdump -C command as shown.

[]uint8{
 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, // |........|
 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, // |....... |
 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // |!"#$%&'(|
 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, // |)*+,-./0|
 0x31, 0x32,                                     // |12|
}

Index

Examples

Constants

This section is empty.

Variables

View Source
var Config = ConfigState{
	Indent:       " ",
	NumericWidth: 1,
	StringWidth:  1,
	BytesWidth:   16,
	CommentBytes: true,
}

Config is the active configuration of the top-level functions. The configuration can be changed by modifying the contents of utter.Config.

Functions

func Dump

func Dump(a interface{})

Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package:

  • Pointers are dereferenced and followed
  • Circular data structures are detected and annotated
  • Byte arrays and slices are dumped in a way similar to the hexdump -C command, which includes byte values in hex, and ASCII output

The configuration options are controlled by an exported package global, utter.Config. See ConfigState for options documentation.

See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string.

Example

This example demonstrates how to use Dump to dump variables to stdout.

package main

import (
	"fmt"

	"github.com/kortschak/utter"
)

type Flag int

const (
	flagOne Flag = iota
	flagTwo
)

var flagStrings = map[Flag]string{
	flagOne: "flagOne",
	flagTwo: "flagTwo",
}

func (f Flag) String() string {
	if s, ok := flagStrings[f]; ok {
		return s
	}
	return fmt.Sprintf("Unknown flag (%d)", int(f))
}

type Bar struct {
	flag Flag
	data uintptr
}

type Foo struct {
	unexportedField Bar
	ExportedField   map[interface{}]interface{}
}

func main() {
	// The following package level declarations are assumed for this example:
	/*
		type Flag int

		const (
			flagOne Flag = iota
			flagTwo
		)

		var flagStrings = map[Flag]string{
			flagOne: "flagOne",
			flagTwo: "flagTwo",
		}

		func (f Flag) String() string {
			if s, ok := flagStrings[f]; ok {
				return s
			}
			return fmt.Sprintf("Unknown flag (%d)", int(f))
		}

		type Bar struct {
			flag Flag
			data uintptr
		}

		type Foo struct {
			unexportedField Bar
			ExportedField   map[interface{}]interface{}
		}
	*/

	// Setup some sample data structures for the example.
	bar := Bar{Flag(flagTwo), uintptr(0)}
	s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
	f := Flag(5)
	b := []byte{
		0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
		0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
		0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
		0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
		0x31, 0x32,
	}

	// Dump!
	utter.Dump([]interface{}{s1, f, b})

}
Output:


[]interface{}{
 utter_test.Foo{
  unexportedField: utter_test.Bar{
   flag: utter_test.Flag(1),
   data: uintptr(0),
  },
  ExportedField: map[interface{}]interface{}{
   string("one"): bool(true),
  },
 },
 utter_test.Flag(5),
 []uint8{
  0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, // |............... |
  0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, // |!"#$%&'()*+,-./0|
  0x31, 0x32, /*                                                                               */ // |12|
 },
}

func Fdump

func Fdump(w io.Writer, a interface{})

Fdump formats and displays the passed arguments to io.Writer w. It formats exactly the same as Dump.

func Sdump

func Sdump(a interface{}) string

Sdump returns a string with the passed arguments formatted exactly the same as Dump.

Types

type ConfigState

type ConfigState struct {
	// Indent specifies the string to use for each indentation level.  The
	// global config instance that all top-level functions use set this to a
	// single space by default.  If you would like more indentation, you might
	// set this to a tab with "\t" or perhaps two spaces with "  ".
	Indent string

	// NumericWidth specifies the number of columns to use when dumping
	// a numeric slice or array (including bool). Zero specifies all entries
	// on one line.
	NumericWidth int

	// StringWidth specifies the number of columns to use when dumping
	// a string slice or array. Zero specifies all entries on one line.
	StringWidth int

	// Quoting specifies the quoting strategy to use when printing strings.
	Quoting Quoting

	// BytesWidth specifies the number of byte columns to use when dumping a
	// byte slice or array. If this is not set or negative, a value of 16
	// is used.
	BytesWidth int

	// CommentBytes specifies whether byte slice or array dumps have ASCII
	// comment annotations.
	CommentBytes bool

	// AddressBytes specifies whether byte slice or array dumps have index
	// annotations.
	AddressBytes bool

	// CommentPointers specifies whether pointer information will be added
	// as comments.
	CommentPointers bool

	// IgnoreUnexported specifies that unexported struct fields should be
	// ignored during a dump.
	IgnoreUnexported bool

	// OmitZero specifies that zero values should not be printed in a dump.
	OmitZero bool

	// LocalPackage specifies a package selector to trim from type information.
	LocalPackage string

	// ElideType specifies that type information defined by context should
	// not be printed in a dump.
	ElideType bool

	// SortKeys specifies map keys should be sorted before being printed. Use
	// this to have a more deterministic, diffable output.  Note that only
	// native types (bool, int, uint, floats, uintptr and string) are supported
	// with other types sorted according to the reflect.Value.String() output
	// which guarantees display stability.
	SortKeys bool
}

ConfigState houses the configuration options used by utter to format and display values. There is a global instance, Config, that is used to control all top-level Formatter and Dump functionality. Each ConfigState instance provides methods equivalent to the top-level functions.

The zero value for ConfigState provides no indentation. You would typically want to set it to a space or a tab.

Alternatively, you can use NewDefaultConfig to get a ConfigState instance with default settings. See the documentation of NewDefaultConfig for default values.

Example

This example demonstrates how to use a ConfigState.

package main

import (
	"github.com/kortschak/utter"
)

func main() {
	// Modify the indent level of the ConfigState only.  The global
	// configuration is not modified.
	scs := utter.ConfigState{Indent: "\t"}

	// Output using the ConfigState instance.
	v := map[string]int{"one": 1}
	scs.Dump(v)

}
Output:


map[string]int{
	string("one"): int(1),
}

func NewDefaultConfig

func NewDefaultConfig() *ConfigState

NewDefaultConfig returns a ConfigState with the following default settings.

	Indent: " "
 NumericWidth: 1,
 StringWidth: 1,
	BytesWidth: 16
	CommentBytes: true
	CommentPointers: false
 IgnoreUnexported: false
 ElideType: false
	SortKeys: false

func (*ConfigState) Dump

func (c *ConfigState) Dump(a interface{})

Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package:

  • Pointers are dereferenced and followed
  • Circular data structures are detected and handled properly
  • Byte arrays and slices are dumped in a way similar to the hexdump -C command which includes byte values in hex, and ASCII output

The configuration options are controlled by modifying the public members of c. See ConfigState for options documentation.

See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string.

Example

This example demonstrates how to use ConfigState.Dump to dump variables to stdout

package main

import (
	"fmt"

	"github.com/kortschak/utter"
)

type Flag int

const (
	flagOne Flag = iota
	flagTwo
)

var flagStrings = map[Flag]string{
	flagOne: "flagOne",
	flagTwo: "flagTwo",
}

func (f Flag) String() string {
	if s, ok := flagStrings[f]; ok {
		return s
	}
	return fmt.Sprintf("Unknown flag (%d)", int(f))
}

type Bar struct {
	flag Flag
	data uintptr
}

type Foo struct {
	unexportedField Bar
	ExportedField   map[interface{}]interface{}
}

func main() {
	// See the top-level Dump example for details on the types used in this
	// example.

	// Create two ConfigState instances with different indentation.
	scs := utter.ConfigState{Indent: "\t"}
	scs2 := utter.ConfigState{Indent: " "}

	// Setup some sample data structures for the example.
	bar := Bar{Flag(flagTwo), uintptr(0)}
	s1 := Foo{bar, map[interface{}]interface{}{"one": true}}

	// Dump using the ConfigState instances.
	scs.Dump(s1)
	scs2.Dump(s1)

}
Output:


utter_test.Foo{
	unexportedField: utter_test.Bar{
		flag: utter_test.Flag(1),
		data: uintptr(0),
	},
	ExportedField: map[interface{}]interface{}{
		string("one"): bool(true),
	},
}
utter_test.Foo{
 unexportedField: utter_test.Bar{
  flag: utter_test.Flag(1),
  data: uintptr(0),
 },
 ExportedField: map[interface{}]interface{}{
  string("one"): bool(true),
 },
}

func (*ConfigState) Fdump

func (c *ConfigState) Fdump(w io.Writer, a interface{})

Fdump formats and displays the passed arguments to io.Writer w. It formats exactly the same as Dump.

func (*ConfigState) Sdump

func (c *ConfigState) Sdump(a interface{}) string

Sdump returns a string with the passed arguments formatted exactly the same as Dump.

type Quoting added in v1.5.0

type Quoting uint

Quoting describes string quoting strategies.

The numerical values of quoting constants are not guaranteed to be stable.

const (
	// Quote strings with double quotes.
	DoubleQuote Quoting = 0

	// AvoidEscapes quotes strings using backquotes to avoid escape
	// sequences if possible, otherwise double quotes are used.
	AvoidEscapes Quoting = 1 << iota

	// Backquote always quotes strings using backquotes where possible
	// within the string. For sections of strings that can not be
	// backquoted, additional double quote syntax is used.
	Backquote

	// Force is a modifier of AvoidEscapes that adds additional double
	// quote syntax to represent parts that cannot be backquoted.
	Force
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL