format

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 18, 2024 License: MPL-2.0 Imports: 11 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Displayer

type Displayer interface {
	// DefaultFormat returns the Format in which to display the payload if the
	// user does not specify a Format override.
	DefaultFormat() Format

	// Payload is the object to display. Payload may return a single object or a
	// slice of objects.
	Payload() any

	// FieldTemplates returns a slice of Fields. Each Field represents an field
	// based on the payload to display to the user. It is common that the Field
	// is simply a specific field of the payload struct being outputted.
	FieldTemplates() []Field
}

Displayer is the interface for displaying a given payload. By implementing this interface, the payload can be outputted in any of the given Formats.

Example
package main

import (
	"fmt"

	"github.com/hashicorp/hcp/internal/pkg/format"
	"github.com/hashicorp/hcp/internal/pkg/iostreams"
)

func main() {
	// Create the outputter. This is typically passed to the command.
	io := iostreams.Test()
	outputter := format.New(io)

	// Resource is an example resource that we want to display
	type Resource struct {
		Name        string
		ID          string
		Description string
		Bytes       int
	}

	// Build our mock resources. Typically this is the response payload from an API
	// request.
	payload := []Resource{
		{
			Name:        "hello",
			ID:          "123",
			Description: "world",
			Bytes:       100,
		},
		{
			Name:        "another",
			ID:          "456",
			Description: "example",
			Bytes:       1024 * 1024,
		},
	}

	// If you wish to format the values differently, use a Displayer:

	// Define the fields that we want to ExampleDisplayer
	var fields = []format.Field{
		format.NewField("Name", "{{ .Name }}"),
		format.NewField("ID", "{{ .ID }}"),
		format.NewField("Description", "{{ .Description }}"),
		format.NewField("Bytes", "{{ .Bytes }} bytes"),
	}

	// Build the displayer
	d := format.NewDisplayer(payload, format.Pretty, fields)

	// Run the displayer
	if err := outputter.Display(d); err != nil {
		fmt.Printf("error displaying resources: %s\n", err)
	}

	// Since the IO is a test io, manually print it
	fmt.Println(io.Output.String())

}
Output:

Name:        hello
ID:          123
Description: world
Bytes:       100 bytes
---
Name:        another
ID:          456
Description: example
Bytes:       1048576 bytes

func DisplayFields

func DisplayFields[T any](payload T, format Format, fields ...string) Displayer

DisplayFields displays the given fields about the given payload. If no fields are provided, then all fields are displayed. The fields can be specified using either the direct struct field name or the json tag name.

func NewDisplayer

func NewDisplayer[T any](payload T, defaultFormat Format, fields []Field) Displayer

NewDisplayer creates a new Displayer with the given payload, default format, and fields.

type Field

type Field struct {
	// Name is the displayed name of the field to the user.
	Name string

	// ValueFormat is a text/template that controls how the value will be
	// displayed. If the payload is a struct with the following structure:
	//
	//   type Cluster struct {
	//     Name          string
	//     Description   string
	//     CloudProvider string
	//     Region        string
	//     CreatedAt     time.Time
	//  }
	//
	// Example ValueFormat's would be:
	//   '{{ . Name }}' -> "Example"
	//   '{{ .CloudProvider }}/{{ . Region }}' -> "aws/us-east-1"
	//
	// A more advanced example would be using the text/template to invoke a
	// function. This can be done by implementing a function on the Payload type
	// that can be invoked. Function definitions will shadow fields in the
	// returned Payload.
	//
	// func (c *Cluster) CreatedAt() string {
	//   return humanize.Time(d.cluster.CreatedAt)
	// }
	//
	// A ValueFormat of '{{ .CreatedAt }}' will now invoke this function. If the
	// cluster was recently created an output may display "4s ago".
	ValueFormat string
}

Field represents a field to output.

func NewField

func NewField(name, valueFormat string) Field

NewField creates a new Field with the given name and value format string. See the Field struct for more information.

type Format

type Format int

Format captures the output format to use.

const (
	Unset Format = iota

	// Pretty is used to output the payload in a key/value format where each
	// pair is outputted on a new line.
	Pretty Format = iota

	// Table outputs the payload as a table.
	Table Format = iota

	// JSON outputs the values in raw JSON.
	JSON Format = iota
)

func FromString

func FromString(s string) (Format, error)

FromString converts a string representation of a format to a Format.

type Outputter

type Outputter struct {
	// contains filtered or unexported fields
}

Outputter is used to output data to users in a consistent manner. The outputter supports outputting data in a number of Formats.

To output data, the Display function should be called with a Displayer. A Displayer has a default format. The outputter will use this format unless a format has previously been set which overrides the default.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/hashicorp/hcp/internal/pkg/format"
	"github.com/hashicorp/hcp/internal/pkg/iostreams"
)

func main() {
	// Create the outputter. This is typically passed to the command.
	io := iostreams.Test()
	outputter := format.New(io)

	// Resource is an example resource that we want to display
	type Resource struct {
		Name        string
		ID          string
		Description string
		Bytes       int
	}

	// Build our mock resources. Typically this is the response payload from an API
	// request.
	payload := []Resource{
		{
			Name:        "hello",
			ID:          "123",
			Description: "world",
			Bytes:       100,
		},
		{
			Name:        "another",
			ID:          "456",
			Description: "example",
			Bytes:       1024 * 1024,
		},
	}

	// For displaying a table of the exact values, Show can be used:
	_ = outputter.Show(payload, format.Table)

	// Since the IO is a test io, manually print it.
	// We trim the lines to make examples testing pass correctly.
	lines := strings.Split(io.Output.String(), "\n")
	for i, l := range lines {
		lines[i] = strings.TrimSpace(l)
	}
	fmt.Println(strings.Join(lines, "\n"))

}
Output:

Name     ID   Description  Bytes
hello    123  world        100
another  456  example      1048576

func New

func New(io iostreams.IOStreams) *Outputter

New returns an new outputter that will write to the provided IOStreams.

func (*Outputter) Display

func (o *Outputter) Display(d Displayer) error

Display displays the passed Displayer. The format used is the DefaultFormat unless the outputter has had a Format set which overrides the default.

func (*Outputter) GetFormat

func (o *Outputter) GetFormat() Format

GetFormat returns the format if set.

func (*Outputter) SetFormat

func (o *Outputter) SetFormat(f Format)

SetFormat sets the format to output with regardless of the DefaultFormat returned by the displayer.

func (*Outputter) Show

func (o *Outputter) Show(val any, format Format, fields ...string) error

Show outputs the given val using the DisplayFields function. If fields are specified, only those fields are shown, otherwise all fields are shown. The json tag of a field is honored and can be used to specified a field.

This is a simplified version of using .Display, which should be used for all more advanced cases that require formatting fields differently.

This function can accept a slice of values as well and formats them correctly. If the value being considered (directly or within in a slice) is not a struct, it is displayed as is under the field named 'Value'.

type TableFormatter

type TableFormatter interface {
	HeaderFormatter(input string) string
	FirstColumnFormatter(input string) string
}

TableFormatter is an optional interface to implement to customize how a table is outputted.

type TemplatedPayload

type TemplatedPayload interface {
	TemplatedPayload() any
}

TemplatedPayload allows a Displayer to return a different payload if the output will be templated using the field templates. This can be useful when raw output (e.g. JSON) requires a specific payload but the templated output (e.g. table/pretty) would benefit from a different payload type.

Jump to

Keyboard shortcuts

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