col

package
v2.2.1 Latest Latest
Warning

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

Go to latest
Published: Dec 31, 2020 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package col helps you to print a nicely formatted report to the terminal.

You can specify columns with multi-line headers and it will automatically align the headers correctly for the column and format the data to fit neatly under the headers.

You start by creating a header object, this can be used to set various different behaviours - see the HdrOpt... functions for details of what options are available. This cannot be used for anything except passing to the constructor for the report object

Then you create a report object passing it the newly created header object and a list of one or more columns.

Then to make use of all your work above you call the PrintRow... methods on the report object that you just created.

Example (Report)

Example_report demonstrates how the col package might be used to generate a report. Notice how we have multi-line column headings and how common header text is shared between adjacent columns (this makes for more concise reports)

package main

import (
	"fmt"
	"os"

	"github.com/nickwells/col.mod/v2/col"
	"github.com/nickwells/col.mod/v2/col/colfmt"
)

func main() {
	// First, create the header
	h, err := col.NewHeader()
	if err != nil {
		fmt.Println("Error found while constructing the header:", err)
		return
	}

	// Now create the report. List the columns we want giving the format
	// types and the column headings
	rpt, err := col.NewReport(h, os.Stdout,
		col.New(&colfmt.Int{}, "Date"),
		col.New(&colfmt.Int{W: 2}, "Number of", "Boys"),
		col.New(&colfmt.Int{W: 2}, "Number of", "Girls"),
		col.New(&colfmt.Int{W: 3}, "Class", "Size"),
		col.New(&colfmt.Float{Prec: 2}, "Ratio", "Boys-Girls"),
	)
	if err != nil {
		fmt.Println("Error found while constructing the report:", err)
		return
	}

	type rowStruct struct {
		y     int
		boys  int
		girls int
	}
	for _, v := range []rowStruct{
		{y: 2011, boys: 14, girls: 13},
		{y: 2012, boys: 12, girls: 16},
		{y: 2013, boys: 13, girls: 13},
	} {
		err = rpt.PrintRow(v.y,
			v.boys, v.girls,
			v.boys+v.girls,
			float64(v.boys)/float64(v.girls))
		if err != nil {
			fmt.Println("Error found while printing the report:", err)
			break
		}
	}
}
Output:

     -Number of- Class      Ratio
Date  Boys Girls  Size Boys-Girls
====  ==== =====  ==== ==========
2011    14    13    27       1.08
2012    12    16    28       0.75
2013    13    13    26       1.00
Example (Report2)

Example_report2 demonstrates how the col package might be used to generate a report. This is a more sophisticated report demonstrating how you can customise the header, skip columns and print column totals.

package main

import (
	"fmt"
	"io"
	"os"

	"github.com/nickwells/col.mod/v2/col"
	"github.com/nickwells/col.mod/v2/col/colfmt"
)

func main() {
	// First, create the header
	h, err := col.NewHeader(
		// On the first page only, print a report description
		col.HdrOptPreHdrFunc(func(w io.Writer, n uint64) {
			if n == 0 {
				fmt.Fprintln(w,
					"A report on the variation in class sizes over time")
			}
		}),
		// Use '-' to underline the column headings
		col.HdrOptUnderlineWith('-'),
	)
	if err != nil {
		fmt.Println("Error found while constructing the header:", err)
		return
	}

	// Now create the report. List the columns we want giving the format
	// types and the column headings
	rpt, err := col.NewReport(h, os.Stdout,
		col.New(&colfmt.Int{}, "Academic", "Year"),
		col.New(&colfmt.Int{}, "Date"),
		col.New(&colfmt.Int{W: 2}, "Number of", "Boys"),
		col.New(&colfmt.Int{W: 2}, "Number of", "Girls"),
		col.New(&colfmt.Float{Prec: 2}, "Ratio", "Boys-Girls"),
		col.New(&colfmt.Int{W: 3}, "Class", "Size"),
	)
	if err != nil {
		fmt.Println("Error found while constructing the report:", err)
		return
	}

	type rowStruct struct {
		year  int
		date  int
		boys  int
		girls int
	}

	lastYear := 0
	totBoys := 0
	totGirls := 0
	count := 0

	for _, v := range []rowStruct{
		{year: 4, date: 2011, boys: 14, girls: 13},
		{year: 4, date: 2012, boys: 12, girls: 16},
		{year: 4, date: 2013, boys: 13, girls: 13},
		{year: 5, date: 2011, boys: 14, girls: 13},
		{year: 5, date: 2012, boys: 12, girls: 16},
		{year: 5, date: 2013, boys: 13, girls: 13},
		{year: 6, date: 2011, boys: 13, girls: 13},
	} {
		count++
		totBoys += v.boys
		totGirls += v.girls
		tot := v.boys + v.girls
		ratio := float64(v.boys) / float64(v.girls)
		var ratioVal interface{}
		if ratio >= 1.005 || ratio <= 0.995 {
			ratioVal = interface{}(ratio)
		} else {
			ratioVal = interface{}(col.Skip{})
		}
		if v.year == lastYear {
			// This illustrates the use of the PrintRowSkipCols func. Note
			// that this could equally have been done by passing col.Skip{}
			// as the first value
			err = rpt.PrintRowSkipCols(1,
				v.date, v.boys, v.girls, ratioVal, tot)
		} else {
			err = rpt.PrintRow(v.year, v.date, v.boys, v.girls, ratioVal, tot)
		}
		if err != nil {
			fmt.Println("Error found while printing the report:", err)
			break
		}
		lastYear = v.year
	}

	// now print the column totals using PrintFooterVals
	ratio := float64(totBoys) / float64(totGirls)
	avgClassSize := (totBoys + totGirls) / count
	err = rpt.PrintFooterVals(2, totBoys, totGirls, ratio, avgClassSize)
	if err != nil {
		fmt.Println("Error found while printing the report footer:", err)
	}
}
Output:

A report on the variation in class sizes over time
Academic      -Number of-      Ratio Class
    Year Date  Boys Girls Boys-Girls  Size
    ---- ----  ---- ----- ----------  ----
       4 2011    14    13       1.08    27
         2012    12    16       0.75    28
         2013    13    13               26
       5 2011    14    13       1.08    27
         2012    12    16       0.75    28
         2013    13    13               26
       6 2011    13    13               26
              ----- ----- ---------- -----
                 91    97       0.94    26

Index

Examples

Constants

View Source
const DfltColSep = " "

Variables

This section is empty.

Functions

func HdrOptDontPrint

func HdrOptDontPrint(h *Header) error

HdrOptDontPrint prevents the header from being printed

func HdrOptDontSpanDups

func HdrOptDontSpanDups(h *Header) error

HdrOptDontSpanDups prevents the header from spanning common headers

func HdrOptDontUnderline

func HdrOptDontUnderline(h *Header) error

HdrOptDontUnderline prevents the header from being underlined

Types

type Col

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

Col holds the values needed in order to represent a column

func New

func New(f Formatter, colHead ...string) *Col

New creates a new Col object

func (*Col) SetSep

func (c *Col) SetSep(s string) *Col

SetSep sets the separator for the column from the default value (see DfltColSep) to the value passed

type Formatter

type Formatter interface {
	// Formatted should return the value as a string
	Formatted(interface{}) string
	// Width should return the expected width of the string printed with the
	// format string. Note that the actual width of the string may be greater
	// than this depending on the width of the column header
	Width() int
	// Just should return whether the resultant string is left or right
	// justified. This information is needed when deciding how to print the
	// header
	Just() Justification
}

Formatter is an interface which describes the methods to be provided by a column formatter. Various instances of the Formatter interface are given in the col/colfmt package. These should cover many common requirements.

type HdrOptionFunc

type HdrOptionFunc func(*Header) error

HdrOptionFunc is the signature of the function that is passed to the NewHeader function to set the header options

func HdrOptPreHdrFunc

func HdrOptPreHdrFunc(f PreHdrFunc) HdrOptionFunc

HdrOptPreHdrFunc returns a HdrOptionFunc that will set the pre-header function

func HdrOptRepeat

func HdrOptRepeat(n uint64) HdrOptionFunc

HdrOptRepeat returns a HdrOptionFunc that will set the number of lines of data that should be printed before the header is printed again. If this value is not set then the header is only printed once

func HdrOptUnderlineWith

func HdrOptUnderlineWith(r rune) HdrOptionFunc

HdrOptUnderlineWith returns a HdrOptionFunc that will set the rune used to underline the final header line

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

Header holds the parameters which control how and when the header is printed

func NewHeader

func NewHeader(options ...HdrOptionFunc) (*Header, error)

NewHeader creates a new Header object. It will return an error if any of the options returns an error.

func NewHeaderOrPanic added in v2.2.0

func NewHeaderOrPanic(options ...HdrOptionFunc) *Header

NewHeaderOrPanic creates a new Header object. It will panic if any of the options returns an error.

type Justification

type Justification int

Justification represents how a column is justified

const (
	Left Justification = iota
	Right
)

The justification types:

Left means left-justified
Right means right-justified

type PreHdrFunc

type PreHdrFunc func(io.Writer, uint64)

PreHdrFunc is the signature of a function to be called immediately before the header itself is printed. It is intended for printing a report preamble or, if the header is periodically repeated, it could be used, for instance, to print sub-totals. The int64 parameter passes the number of data rows printed, if this is zero then the header is being printed for the first time

type Report

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

Report holds a collection of columns and header details

func NewReport

func NewReport(hdr *Header, w io.Writer, cols ...*Col) (*Report, error)

NewReport creates a new Report object. it will return a non-nil error if no columns have been given.

func NewReportOrPanic added in v2.2.0

func NewReportOrPanic(hdr *Header, w io.Writer, cols ...*Col) *Report

NewReportOrPanic creates a new Report object and panics if any error is reported

func (Report) PrintFooterVals

func (rpt Report) PrintFooterVals(skip uint, vals ...interface{}) error

PrintFooterVals prints values for the footer. It does not print the header or increment the number of rows printed. It will print Header.underlineCh characters under the columns being printed

func (*Report) PrintRow

func (rpt *Report) PrintRow(vals ...interface{}) error

PrintRow will print the values according to the specification of each corresponding column. It will also print the header as specified. It will return an error if there are not the same number of values as columns.

func (*Report) PrintRowSkipCols

func (rpt *Report) PrintRowSkipCols(skip uint, vals ...interface{}) error

PrintRowSkipCols will print the values according to the specification of each corresponding column. It will also print the header as specified. It will skip the first columns as specified. The most likely use for this is if you have several leading columns you want to skip. To skip individual columns you can use a col.Skip{}

type Skip

type Skip struct{}

Skip is a type that can be passed as a column value that will print a blank value. It is an empty place-holder for a column.

Directories

Path Synopsis
The colfmt package supplies various implementations of the col.Formatter interface.
The colfmt package supplies various implementations of the col.Formatter interface.

Jump to

Keyboard shortcuts

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