dapper

package module
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Apr 7, 2024 License: MIT Imports: 15 Imported by: 1

README

Dapper

Dapper is a pretty-printer for Go values.

Documentation Latest Version Build Status Code Coverage

Dapper is not intended to be used directly as a debugging tool, but as a library for applications that need to describe Go values to humans, such as testing frameworks.

Some features and design goals include:

  • Concise formatting, without type ambiguity
  • Deterministic output, useful for generating diffs using standard tools
  • A filter system for producing customized output on a per-value basis

Example

This example renders a basic tree structure. Note that the output only includes type names where the value's type can not be inferred from the context.

Code
package main

import (
	"fmt"
	"github.com/dogmatiq/dapper"
)

type TreeNode struct {
	Name     string
	Value    any
	Children []*TreeNode
}

type NodeValue struct{}

func main() {
	v := TreeNode{
		Name: "root",
		Children: []*TreeNode{
			{
				Name:  "branch #1",
				Value: 100,
			},
			{
				Name:  "branch #2",
				Value: NodeValue{},
			},
		},
	}

	dapper.Print(v)
}
Output
main.TreeNode{
    Name:     "root"
    Value:    nil
    Children: {
        {
            Name:     "branch #1"
            Value:    int(100)
            Children: nil
        }
        {
            Name:     "branch #2"
            Value:    main.NodeValue{}
            Children: nil
        }
    }
}

Documentation

Overview

Package dapper is a deterministic pretty-printer with minimal output.

Index

Examples

Constants

View Source
const (
	// DefaultZeroValueMarker is the default string to display when rendering a
	// zero-value struct.
	DefaultZeroValueMarker = "<zero>"

	// DefaultRecursionMarker is the default string to display when recursion
	// is detected within a Go value.
	DefaultRecursionMarker = "<recursion>"
)
View Source
const DefaultIndent = "    "

DefaultIndent is the default indent string used to indent nested values.

Variables

DefaultPrinter is the printer used by Write(), Format() and Print().

Functions

func AsConcrete added in v0.5.0

func AsConcrete[T any](v Value) (T, bool)

AsConcrete returns a v as type T if its dynamic type is exactly T.

func AsImplementationOf added in v0.5.0

func AsImplementationOf[T any](v Value) (T, bool)

AsImplementationOf returns v as a value of type T if it directly implements T.

func ErrorFilter added in v0.5.0

func ErrorFilter(r Renderer, v Value)

ErrorFilter is a Filter that formats implementations of [error].

func Format

func Format(v any) string

Format returns a pretty-printed representation of v.

Example
s := Format(123)
fmt.Println(s)
Output:

int(123)

func Is added in v0.5.0

func Is[T any](v Value) bool

Is returns true if v's type is exactly T.

func Print added in v0.2.0

func Print(values ...any)

Print writes a pretty-printed representation of v to os.Stdout.

Example
Print(123, 456.0)
Output:

int(123)
float64(456)

func ProtoFilter added in v0.5.0

func ProtoFilter(r Renderer, v Value)

ProtoFilter is a Filter that formats implementations of proto.Message.

func ReflectFilter added in v0.5.0

func ReflectFilter(r Renderer, v Value)

ReflectFilter is a Filter that formats various types from the reflect package.

func StringerFilter added in v0.4.4

func StringerFilter(r Renderer, v Value)

StringerFilter is a Filter that formats implementations of dapper.Stringer.

func SyncFilter added in v0.3.4

func SyncFilter(r Renderer, v Value)

SyncFilter is a filter that formats various types from the sync package.

func TimeFilter added in v0.3.4

func TimeFilter(r Renderer, v Value)

TimeFilter is a filter that formats various values from the time package.

func Write

func Write(w io.Writer, v any) (int, error)

Write writes a pretty-printed representation of v to w using the default printer settings.

It returns the number of bytes written.

Example
w := &bytes.Buffer{}

if _, err := Write(w, 123); err != nil {
	panic(err)
}

w.WriteTo(os.Stdout)
Output:

int(123)

Types

type Config added in v0.4.0

type Config struct {
	// Filters is the set of filters to apply when formatting values.
	Filters []Filter

	// Indent is the string used to indent nested values.
	// If it is empty, DefaultIndent is used.
	Indent string

	// ZeroValueMarker is a string that is displayed instead of a structs field
	// list when it is the zero-value. If it is empty, DefaultZeroValueMarker is
	// used.
	ZeroValueMarker string

	// RecursionMarker is a string that is displayed instead of a value's
	// representation when recursion has been detected.
	// If it is empty, DefaultRecursionMarker is used.
	RecursionMarker string

	// OmitPackagePaths, when true, causes the printer to omit the
	// fully-qualified package path from the rendered type names.
	OmitPackagePaths bool

	// OmitUnexportedFields omits unexported struct fields when set to true
	OmitUnexportedFields bool
}

Config holds the configuration for a printer.

type Filter added in v0.3.0

type Filter func(r Renderer, v Value)

Filter is a function that provides custom formatting logic for a specific type or value.

The filter uses r to render v. If r is unused v is rendered using the default formatting logic.

type Printer

type Printer struct {
	// Config is the configuration for the printer.
	Config Config
}

Printer generates human-readable representations of Go values.

The output format is intended to be as minimal as possible, without being ambiguous. To that end, type information is only included where it can not be reliably inferred from the structure of the value.

Example
type TreeNode struct {
	Name     string
	Value    any
	Children []*TreeNode
}

type NodeValue struct{}

v := TreeNode{
	Name: "root",
	Children: []*TreeNode{
		{
			Name:  "branch #1",
			Value: 100,
		},
		{
			Name:  "branch #2",
			Value: NodeValue{},
		},
	},
}

p := Printer{}
s := p.Format(v)
fmt.Println(s)
Output:

github.com/dogmatiq/dapper_test.TreeNode{
    Name:     "root"
    Value:    nil
    Children: {
        {
            Name:     "branch #1"
            Value:    int(100)
            Children: nil
        }
        {
            Name:     "branch #2"
            Value:    github.com/dogmatiq/dapper_test.NodeValue{}
            Children: nil
        }
    }
}

func (*Printer) Format

func (p *Printer) Format(v any) string

Format returns a pretty-printed representation of v.

func (*Printer) Write

func (p *Printer) Write(w io.Writer, v any) (_ int, err error)

Write writes a pretty-printed representation of v to w.

It returns the number of bytes written.

type Renderer added in v0.5.0

type Renderer interface {
	io.Writer

	Config() Config

	FormatType(Value) string
	WriteType(Value)

	WriteValue(Value)
	FormatValue(Value) string

	Indent()
	Outdent()
	Print(format string, args ...any)

	WithModifiedConfig(func(*Config)) Renderer
}

Renderer is an interface for rendering human-readable representations of arbitrary values.

type Stringer added in v0.4.4

type Stringer interface {
	DapperString() string
}

Stringer is an interface for types that produce their own Dapper representation.

type Value added in v0.3.0

type Value struct {
	// Value is the value to be formatted.
	Value reflect.Value

	// DynamicType is the value's type.
	DynamicType reflect.Type

	// StaticType is the type of the "variable" that the value is stored in,
	// which may not be the same as its dynamic type.
	//
	// For example, when formatting the values within a slice of "any"
	// containing integers, such as []any{1, 2, 3}, the DynamicType will be
	// "int", but the static type will be "any".
	StaticType reflect.Type

	// IsAmbiguousDynamicType is true if the value's dynamic type is not clear from
	// the context of what has already been rendered.
	IsAmbiguousDynamicType bool

	// IsAmbiguousStaticType is true if the value's static type is not clear from
	// the context of what has already been rendered.
	IsAmbiguousStaticType bool

	// IsUnexported is true if this value was obtained from an unexported struct
	// field. If so, it is not possible to extract the underlying value.
	IsUnexported bool
}

Value contains information about a Go value that is to be formatted.

func (*Value) IsAmbiguousType added in v0.3.0

func (v *Value) IsAmbiguousType() bool

IsAmbiguousType returns true if either the dynamic type or the static type is ambiguous.

func (*Value) IsAnonymousType added in v0.3.0

func (v *Value) IsAnonymousType() bool

IsAnonymousType returns true if the value has an anonymous type.

Directories

Path Synopsis
internal
stream
Package stream provides utilities for working with IO streams.
Package stream provides utilities for working with IO streams.

Jump to

Keyboard shortcuts

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