tableprinter

package module
v0.0.0-...-89e81fc Latest Latest
Warning

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

Go to latest
Published: Nov 25, 2020 License: Apache-2.0 Imports: 15 Imported by: 134

README

TablePrinter

tableprinter is an intelligent value-to-table formatter and writer. It uses a customized version of olekukonko/tablewriter to render a result table.

It checks every in data and transforms those data(structure values, slices, maps, single lists that may contain different type of values such as go standard values like int, string even a value that implements the fmt.Stringer interface) to a table formatted text and outputs it to an io.Writer. Like encoding/json#Encode but for tables.

build status report card godoc examples

Installation

The only requirement is the Go Programming Language, at least version 1.10.

$ go get -u github.com/lensesio/tableprinter
package main

import (
    "os"
    "sort"

    "github.com/kataras/tablewriter"
    "github.com/lensesio/tableprinter"
)

type person struct {
    Firstname string `header:"first name"`
    Lastname  string `header:"last name"`
}

func main() {
    printer := tableprinter.New(os.Stdout)
    persons := []person{
        {"Chris", "Doukas"},
        {"Georgios", "Callas"},
        {"Ioannis", "Christou"},
        {"Nikolaos", "Doukas"},
        {"Dimitrios", "Dellis"},
    }

    sort.Slice(persons, func(i, j int) bool {
        return persons[j].Firstname > persons[i].Firstname
    })

    // Optionally, customize the table, import of the underline 'tablewriter' package is required for that.
    printer.BorderTop, printer.BorderBottom, printer.BorderLeft, printer.BorderRight = true, true, true, true
    printer.CenterSeparator = "│"
    printer.ColumnSeparator = "│"
    printer.RowSeparator = "─"
    printer.HeaderBgColor = tablewriter.BgBlackColor
    printer.HeaderFgColor = tablewriter.FgGreenColor

    // Print the slice of structs as table, as shown above.
    printer.Print(persons)
}
Examples

Versioning

Current: v0.0.3

Read more about Semantic Versioning 2.0.0

License

Distributed under Apache Version 2.0, see LICENSE for more information.

Documentation

Index

Constants

View Source
const (
	// HeaderTag usage: Field string `header:"Name"`
	HeaderTag = "header"
	// InlineHeaderTag usage: Embedded Struct `header:"inline"`
	InlineHeaderTag = "inline"
	// NumberHeaderTag usage: NumberButString string `header:"Age,number"`
	NumberHeaderTag = "number"
	// CountHeaderTag usage: List []any `header:"MyList,count"`
	CountHeaderTag = "count"
	// ForceTextHeaderTag usage: ID int `header:"ID,text"`
	ForceTextHeaderTag = "text"

	// TimestampHeaderTag usage: Timestamp int64 `json:"timestamp" yaml:"Timestamp" header:"At,timestamp(ms|utc|02 Jan 2006 15:04)"`
	TimestampHeaderTag = "timestamp"
	// TimestampFromMillisecondsHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms)"`
	TimestampFromMillisecondsHeaderTag = "ms"
	// TimestampAsUTCHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc)"`
	TimestampAsUTCHeaderTag = "utc"
	// TimestampAsLocalHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|local)"`
	TimestampAsLocalHeaderTag = "local"
	// TimestampFormatHumanHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|human)"`
	TimestampFormatHumanHeaderTag = "human"
	// TimestampFormatANSICHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|ANSIC)"`
	TimestampFormatANSICHeaderTag = "ANSIC"
	// TimestampFormatUnixDateCHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|UnixDate)"`
	TimestampFormatUnixDateCHeaderTag = "UnixDate"
	// TimestampFormatRubyDateHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RubyDate)"`
	TimestampFormatRubyDateHeaderTag = "RubyDate"
	// TimestampFormatRFC822HeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC822)"`
	TimestampFormatRFC822HeaderTag = "RFC822"
	// TimestampFormatRFC822ZHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC822Z)"`
	TimestampFormatRFC822ZHeaderTag = "RFC822Z"
	// TimestampFormatRFC850HeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC850)"`
	TimestampFormatRFC850HeaderTag = "RFC850"
	// TimestampFormatRFC1123HeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC1123)"`
	TimestampFormatRFC1123HeaderTag = "RFC1123"
	// TimestampFormatRFC1123ZHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC1123Z)"`
	TimestampFormatRFC1123ZHeaderTag = "RFC1123Z" // default one.
	// TimestampFormatRFC3339HeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC3339)"`
	TimestampFormatRFC3339HeaderTag = "RFC3339"
	// TimestampFormatARFC3339NanoHeaderTag usage: Timestamp int64 `header:"Start,timestamp(ms|utc|RFC3339Nano)"`
	TimestampFormatARFC3339NanoHeaderTag = "RFC3339Nano"

	// DurationHeaderTag usage: Uptime int64 `header:"Uptime,unixduration"`
	DurationHeaderTag = "unixduration"
	// DateHeaderTag usage: Start string `header:"Start,date"`, the field's value should be formatted as time.RFC3339
	DateHeaderTag = "date"
)

Variables

View Source
var (
	StructParser = &structParser{TagsOnly: true}
	SliceParser  = &sliceParser{TagsOnly: true}
	MapParser    = &mapParser{TagsOnly: false}
	JSONParser   = new(jsonParser)
)

The built'n type parsers, all except `JSONParser` are directly linked to the `Print/PrintHeadList` functions.

View Source
var Default = Printer{

	AutoFormatHeaders: true,
	AutoWrapText:      false,

	BorderTop:    false,
	BorderLeft:   false,
	BorderRight:  false,
	BorderBottom: false,

	HeaderLine:      true,
	HeaderAlignment: AlignLeft,

	RowLine:         false,
	ColumnSeparator: " ",
	NewLine:         "\n",
	CenterSeparator: " ",
	RowSeparator:    tablewriter.ROW,
	RowCharLimit:    60,
	RowTextWrap:     true,

	DefaultAlignment: AlignLeft,
	NumbersAlignment: AlignRight,

	RowLengthTitle: func(rowsLength int) bool {

		return rowsLength > 3
	},

	AllowRowsOnly: true,
	// contains filtered or unexported fields
}

Default is the default Table Printer.

View Source
var (
	StructHeaders = make(map[reflect.Type][]StructHeader) // type is the root struct.

)

StructHeaders are being cached from the root-level structure to print out. They can be customized for custom head titles.

Header can also contain the necessary information about its values, useful for its presentation such as alignment, alternative value if main is empty, if the row should print the number of elements inside a list or if the column should be formated as number.

Functions

func CanAcceptRow

func CanAcceptRow(in reflect.Value, filters []RowFilter) bool

CanAcceptRow accepts a value of row and a set of filter and returns true if it can be printed, otherwise false. If no filters passed then it returns true.

func Print

func Print(w io.Writer, in interface{}, filters ...interface{}) int

Print outputs whatever "in" value passed as a table to the "w", filters cna be used to control what rows can be visible or hidden. Usage: Print(os.Stdout, values, func(t MyStruct) bool { /* or any type, depends on the type(s) of the "t" */

	return t.Visibility != "hidden"
})

Returns the total amount of rows written to the table or -1 if printer was unable to find a matching parser or if headers AND rows were empty.

func PrintHeadList

func PrintHeadList(w io.Writer, list interface{}, header string, filters ...interface{}) int

PrintHeadList prints whatever "list" as a table to the "w" with a single header. The "list" should be a slice of something, however that list can also contain different type of values, even interface{}, the function will parse each of its elements differently if needed.

It can be used when want to print a simple list of string, i.e names []string, a single column each time.

Returns the total amount of rows written to the table.

func PrintJSON

func PrintJSON(w io.Writer, in []byte, filters ...interface{}) int

PrintJSON prints the json-bytes as a table to the "w", filters cna be used to control what rows can be visible or hidden.

Returns the total amount of rows written to the table or -1 if headers AND rows were empty.

func RegisterParser

func RegisterParser(kind reflect.Kind, parser Parser)

RegisterParser sets a parser based on its kind of type. It overrides any existing element on that kind, each Parser reflects a single kind of type.

It can be used at the initialization of the program to register a custom Parser, see `StructParser` for example. It's not designed to be safe to use it inside many different routines at the same time.

func RemoveStructHeader

func RemoveStructHeader(original interface{}, fieldName string) interface{}

RemoveStructHeader will dynamically remove a specific header tag from a struct's field based on the "fieldName" which must be a valid exported field of the struct. It returns the new, converted, struct value.

If "original" is not a struct or the "fieldName" was unable to be found then the "item" is returned as it was before this call.

See `SetStructHeader` too.

func Render

func Render(w io.Writer, headers []string, rows [][]string, numbersColsPosition []int, reset bool) int

Render prints a table based on the rules of this "p" Printer.

It's used to customize manually the parts of a table like the headers. If need to append a row after its creation you should create a new `Printer` instance by calling the `New` function and use its `RenderRow` instead, because the "w" writer is different on each package-level printer function.

Returns the total amount of rows written to the table.

func SetStructHeader

func SetStructHeader(original interface{}, fieldName string, newHeaderValue string) interface{}

SetStructHeader dynamically sets the "newHeaderValue" to a specific struct's field's header tag's value based on the "fieldName" which must be a valid exported field of the struct.

It returns the new, converted, struct value.

If "original" is not a struct or the "fieldName" was unable to be found then the "item" is returned as it was before this call.

If the "newValue" is empty then the whole header will be removed, see `RemoveStructHeader` too.

Types

type Alignment

type Alignment int

Alignment is the alignment type (int).

See `Printer#DefaultColumnAlignment` and `Printer#DefaultColumnAlignment` too.

const (
	// AlignDefault is the default alignment (0).
	AlignDefault Alignment = iota
	// AlignCenter is the center aligment (1).
	AlignCenter
	// AlignRight is the right aligment (2).
	AlignRight
	// AlignLeft is the left aligment (3).
	AlignLeft
)

type Parser

type Parser interface {
	// Why not `ParseRows` and `ParseHeaders`?
	// Because type map has not a specific order, order can change at different runtimes,
	// so we must keep record on the keys order the first time we fetche them (=> see `MapParser#ParseRows`, `MapParser#ParseHeaders`).
	Parse(v reflect.Value, filters []RowFilter) (headers []string, rows [][]string, numbers []int)
}

Parser should be implemented by all available reflect-based parsers.

See `StructParser`(struct{} type), `SliceParser`(slice[] type), `MapParser`(map type) and `JSONParser`(any type). Manually registering of a parser is a valid option (although not a recommendation), see `RegisterParser` for more.

func WhichParser

func WhichParser(typ reflect.Type) Parser

WhichParser returns the available `Parser` for the "typ" type; Slice, Map, Struct...

type Printer

type Printer struct {
	AutoFormatHeaders bool
	AutoWrapText      bool

	BorderTop, BorderLeft, BorderRight, BorderBottom bool

	HeaderLine      bool
	HeaderAlignment Alignment
	HeaderColors    []tablewriter.Colors
	HeaderBgColor   int
	HeaderFgColor   int

	RowLine         bool
	ColumnSeparator string
	NewLine         string
	CenterSeparator string
	RowSeparator    string
	RowCharLimit    int
	RowTextWrap     bool // if RowCharLimit > 0 && RowTextWrap == true then wrap the line otherwise replace the trailing with "...".

	DefaultAlignment Alignment // see `NumbersAlignment` too.
	NumbersAlignment Alignment

	RowLengthTitle func(int) bool
	AllowRowsOnly  bool // if true then `Print/Render` will print the headers even if parsed rows where no found. Useful for putting rows to a table manually.
	// contains filtered or unexported fields
}

Printer contains some information about the final table presentation. Look its `Print` function for more.

func New

func New(w io.Writer) *Printer

New creates and initializes a Printer with the default values based on the "w" target writer.

See its `Print`, `PrintHeadList` too.

func (*Printer) Print

func (p *Printer) Print(in interface{}, filters ...interface{}) int

Print outputs whatever "in" value passed as a table, filters can be used to control what rows can be visible and which not. Usage: Print(values, func(t MyStruct) bool { /* or any type, depends on the type(s) of the "t" */

	return t.Visibility != "hidden"
})

Returns the total amount of rows written to the table or -1 if printer was unable to find a matching parser or if headers AND rows were empty.

func (*Printer) PrintHeadList

func (p *Printer) PrintHeadList(list interface{}, header string, filters ...interface{}) int

PrintHeadList prints whatever "list" as a table with a single header. The "list" should be a slice of something, however that list can also contain different type of values, even interface{}, the function will parse each of its elements differently if needed.

It can be used when want to print a simple list of string, i.e names []string, a single column each time.

Returns the total amount of rows written to the table.

func (*Printer) PrintJSON

func (p *Printer) PrintJSON(in interface{}, filters ...interface{}) int

PrintJSON prints the json-bytes as a table, filters cna be used to control what rows can be visible or hidden.

Returns the total amount of rows written to the table or -1 if headers AND rows were empty.

func (*Printer) Render

func (p *Printer) Render(headers []string, rows [][]string, numbersColsPosition []int, reset bool) int

Render prints a table based on the rules of this "p" Printer.

It's used to customize manually the parts of a table like the headers. It can be used side by side with the `RenderRow`, first and once `Render`, after and maybe many `RenderRow`.

Returns the total amount of rows written to the table.

func (*Printer) RenderRow

func (p *Printer) RenderRow(row []string, numbersColsPosition []int) int

RenderRow prints a row based on the same alignment rules to the last `Print` or `Render`. It can be used to live update the table.

Returns the total amount of rows written to the table.

type RowFilter

type RowFilter func(reflect.Value) bool

RowFilter is the row's filter, accepts the reflect.Value of the custom type, and returns true if the particular row can be included in the final result.

func MakeFilters

func MakeFilters(in reflect.Value, genericFilters ...interface{}) (f []RowFilter)

MakeFilters accept a value of row and generic filters and returns a set of typed `RowFilter`.

Usage: in := reflect.ValueOf(myNewStructValue) filters := MakeFilters(in, func(v MyStruct) bool { return _custom logic here_ }) if CanAcceptRow(in, filters) { _custom logic here_ }

type StructHeader

type StructHeader struct {
	Name string
	// Position is the horizontal position (start from zero) of the header.
	Position int

	ValueAsNumber    bool
	ValueAsCountable bool
	ValueAsText      bool
	ValueAsTimestamp bool
	TimestampValue   TimestampHeaderTagValue
	ValueAsDate      bool
	ValueAsDuration  bool

	AlternativeValue string
}

StructHeader contains the name of the header extracted from the struct's `HeaderTag` field tag.

type TimestampHeaderTagValue

type TimestampHeaderTagValue struct {
	FromMilliseconds bool

	UTC   bool
	Local bool

	Human bool

	Format string
}

TimestampHeaderTagValue the header's value of a "timestamp" header tag functionality.

Directories

Path Synopsis
_examples

Jump to

Keyboard shortcuts

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