Documentation ¶
Overview ¶
The tabular package provides for a model of a two-dimensional grid of cells, or a "table". Sub-packages provide for rendering such a table in convenient ways. For many uses, you only need to import the sub-package.
Sub-packages provide for rendering a TextTable which is designed for a fixed-cell grid layout of character cells, such as a Unix TTY; for rendering as an HTML table; for rendering as a CSV.
The core package provides a Table interface; each sub-package embeds a Table in their own core object, so all methods in the Table interface can be directly used upon such objects. These provide for your basic addition of cells, etc.
The API is designed to let you add data quickly, without error-checking every addition. Instead, error containers are used, and errors accumulate therein. The table is an error-container. A row which is not in a table is also an error container, but any such errors get moved into the table's collection when the row is added, and the row thenceforth uses the table's container.
In addition to tables of rows of cells, with virtual columns, we also have "properties" and "property callbacks". People using tables with pre-canned rendering should not need to care about these, but people writing renderers will need to.
Properties are held by cells, rows, columns and tables. They are metadata, designed to be used by sub-packages or anything doing non-trivial table embedding, to register extra data "about" something. They're akin to stdlib's "context", in that the various users can maintained their own namespaced properties, using a similar API, but can be automatically updated by the table.
Examples might include terminal text properties, color, calculation attributes.
Properties are held by anything which satisfies the PropertyOwner interface. Such objects then have GetProperty and SetProperty methods.
There is an API balancing act for callers to decide between registering a property upon the table itself, or wrapping the table: if you want the value to be automatically updated as a table is mutated, the property approach might make the most sense, but then with a simple API to present it via a method of your wrapper object.
A Property Callback is "anything with the UpdateProperties method", which can be registered with something in the table to be called to automatically update properties. These can be registered on a table, row, column or cell; most are applied to cells, but some are applied to larger objects. The registration needs to know what object is to hold the callback, which target the callback is to be applied to, when it should be invoked, and the new callback being registered.
Index ¶
- Constants
- Variables
- func NoProperty() propertySet
- func Versions() []string
- type ATable
- func (t *ATable) AddHeaders(items ...interface{}) Table
- func (t *ATable) AddRow(row *Row) Table
- func (t *ATable) AddRowItems(items ...interface{}) Table
- func (t *ATable) AddSeparator() Table
- func (t *ATable) AllRows() []*Row
- func (t *ATable) AppendNewRow() *Row
- func (t *ATable) CellAt(loc CellLocation) (*Cell, error)
- func (t *ATable) Column(n int) *column
- func (pi *ATable) GetProperty(key interface{}) interface{}
- func (t *ATable) GoString() string
- func (t *ATable) Headers() []Cell
- func (t *ATable) InvokeRenderCallbacks()
- func (t *ATable) NColumns() int
- func (t *ATable) NRows() int
- func (t *ATable) NewRowSizedFor() *Row
- func (tb *ATable) RegisterPropertyCallback(owner PropertyOwner, when callbackTime, target cbTarget, ...) error
- func (pi *ATable) SetProperty(key, value interface{}) error
- type AnonFielder
- type Cell
- func (c *Cell) Empty() bool
- func (pi *Cell) GetProperty(key interface{}) interface{}
- func (cell *Cell) GoString() string
- func (c Cell) Height() int
- func (c Cell) Item() interface{}
- func (c Cell) Lines() []string
- func (c Cell) Location() (loc CellLocation)
- func (pi *Cell) SetProperty(key, value interface{}) error
- func (c Cell) String() string
- func (c Cell) TerminalCellWidth() int
- func (c *Cell) Update()
- type CellLocation
- type ErrorContainer
- type ErrorReceiver
- type ErrorSource
- type Fielder
- type GoStringer
- type Heighter
- type NoSuchCellError
- type PropertyCallback
- type PropertyOwner
- type Row
- func (r *Row) Add(c Cell) *Row
- func (r *Row) AddError(e error)
- func (r *Row) Cells() []Cell
- func (pi *Row) GetProperty(key interface{}) interface{}
- func (row *Row) GoString() string
- func (r *Row) IsSeparator() bool
- func (r *Row) Location() (loc CellLocation)
- func (pi *Row) SetProperty(key, value interface{}) error
- type Stringer
- type Table
- type TerminalCellWidther
Constants ¶
const ( // CB_AT_ADD called when an item is added to a container CB_AT_ADD callbackTime = iota // CB_AT_RENDER_PRECELL for callbacks registered on containers, to be // called before cell's own callbacks. Use before dimensions/etc locked // down. CB_AT_RENDER_PRECELL // CB_AT_RENDER is called for two sets: table (not row/column) and cell // callbacks. An assumption is that it might be used for deriving // properties such as dimensions, the effect of which cascade outwards. CB_AT_RENDER // CB_AT_RENDER_POSTCELL is called after the cell's own callbacks. CB_AT_RENDER_POSTCELL )
These constants are used for callback functions, to control when the function is invoked.
const ( CB_ON_ITSELF cbTarget = iota CB_ON_CELL CB_ON_ROW )
These constants are used when registering a callback to indicate what should be passed to the callback. Eg, a row might have a set of callbacks to update the row itself, and a separate set of callbacks which are invoked upon each cell in the row.
const APIVersion string = "1.0"
Variables ¶
var ErrMissingPropertyHolder = errors.New("tabular: missing item upon which to set a property")
ErrMissingPropertyHolder is returned if you call SetProperty upon a nil object.
var LinkerSpecifiedVersion string
We are a library, not a top-level binary, so we can't depend upon any particular top-level linker action specifying versions. That said, we can provide hooks for applications to cooperate, if they so choose.
*Clients* please consider invoking the `.version` shell-script inside this repo and passing it to the Go linker. See github.com/philpennock/character for an example.
Functions ¶
func NoProperty ¶
func NoProperty() propertySet
Types ¶
type ATable ¶
type ATable struct { *ErrorContainer // contains filtered or unexported fields }
An ATable is the top-level container for a grid in tabular. You should not be declaring fields to be of type ATable; instead, use the Table interface.
An ATable consists of rows of cells; there may also be a header row which defines names for columns. An ATable, a Column, a Row and a Cell can all contain both Properties, and callbacks for updating properties. The callbacks can each individually be registered to activate upon object addition or upon object rendering. Property Callbacks can take various child objects. For instance, a table-level callback upon cells might update a namespaced Property which holds the cell's rendered width when emitted as characters for terminal display.
func (*ATable) AddHeaders ¶
AddHeaders creates a header-row from the passed items and sets it as the table's header row. The table is returned.
func (*ATable) AddRow ¶
AddRow adds a *Row to the *ATable, returning the table to allow for chaining. Any errors accumulate in the table. Any existing errors in the row become table errors.
func (*ATable) AddRowItems ¶
AddRowItems creates a row from the passed items and adds it to the table, returning the table for chaining.
func (*ATable) AddSeparator ¶
AddSeparator adds a rule to the table.
func (*ATable) AppendNewRow ¶
AppendNewRow creates a new row sized for the table (per NewRowSizedFor) and adds it to the Table, returning the row.
func (*ATable) CellAt ¶
func (t *ATable) CellAt(loc CellLocation) (*Cell, error)
CellAt returns a pointer to the cell found at the given row and column coordinates, where the top-left item is 1,1.
func (*ATable) Column ¶
Column returns a representation of a given column in the table. Column counting starts at 1. Providing an invalid column count returns nil. Column 0 also exists but is the implicit defaults column, letting you set default column properties and then override for other columns.
func (*ATable) GetProperty ¶
func (pi *ATable) GetProperty(key interface{}) interface{}
GetProperty returns the property stored for the given key. If no such property has been stored, then nil will be returned. Thus we can't tell the difference between "nil stored" and "nothing stored", thus property storage is free to treat storing "nil" as "remove".
func (*ATable) Headers ¶
Headers returns the headers of a table, as Cells TODO v2: what if we have multiple header rows? How does this change?
func (*ATable) InvokeRenderCallbacks ¶
func (t *ATable) InvokeRenderCallbacks()
InvokeRenderCallbacks is used by rendering packages to trigger a table-wide invocation of render-time callbacks.
We first invoke pre-cell callbacks going: table->column->row->cell We then invoke regular render callbacks cell->row->column->table
func (*ATable) NewRowSizedFor ¶
NewRowSizedFor creates a new Row sized for the given table which it is called upon, assuming that NColumns() is usefully available.
func (*ATable) RegisterPropertyCallback ¶
func (tb *ATable) RegisterPropertyCallback( owner PropertyOwner, when callbackTime, target cbTarget, theNewCallback PropertyCallback, ) error
RegisterPropertyCallback is used to register your object, which has the UpdateProperties method available, upon something within the table, to be invoked against something (else, perhaps), at a specified time.
func (*ATable) SetProperty ¶
func (pi *ATable) SetProperty(key, value interface{}) error
SetProperty sets the value stored for a given key, removing any other values stored for that key first. If the value is nil then no value will be stored.
type AnonFielder ¶
type AnonFielder interface {
AnonFields() []interface{}
}
AnonFielder to avoid caller having to iterate an []interface{} to construct strings; we then just do cell breakdown on each.
type Cell ¶
type Cell struct {
// contains filtered or unexported fields
}
A Cell is one item in a table; it holds an object and fields calculated from it. If the object added is mutated after addition, it is the mutator's responsibility to call Update.
func NewCell ¶
func NewCell(object interface{}) Cell
NewCell creates a Cell, handling object rendering at init time. TODO: handle rune as rune, or as int? Any special flags to use?
func (*Cell) Empty ¶ added in v1.1.0
Empty returns true if the cell is "empty", whatever that might mean. This includes nothing stored, a cell of nil, or an empty string.
func (*Cell) GetProperty ¶
func (pi *Cell) GetProperty(key interface{}) interface{}
GetProperty returns the property stored for the given key. If no such property has been stored, then nil will be returned. Thus we can't tell the difference between "nil stored" and "nothing stored", thus property storage is free to treat storing "nil" as "remove".
func (Cell) Height ¶
Height returns the height of a cell; usually this is the number of lines in the string representation of the object stored in the cell, as returned by Lines, but an object which has a Height method will override this.
func (Cell) Lines ¶
Lines returns the string representation of the content of a cell, as a splice of strings, one per line, without newlines; if the string has a final \n then there will NOT be an extra empty in the result for the "empty" final segment.
func (Cell) Location ¶
func (c Cell) Location() (loc CellLocation)
Location determines the current location of a cell
func (*Cell) SetProperty ¶
func (pi *Cell) SetProperty(key, value interface{}) error
SetProperty sets the value stored for a given key, removing any other values stored for that key first. If the value is nil then no value will be stored.
func (Cell) TerminalCellWidth ¶
TerminalCellWidth returns the number of terminal cells which we believe are necessary to render the contents of the object stored in the cell. This is overriden by a TerminalCellWidth method on the object being stored. To a first approximation, this is how many runes are in a cell, but we handle combining characters, wide characters, etc.
type CellLocation ¶
We measure from 1:1 so that 0:0 means "not initialized" and if either x or y is zero in a cell, we know the data is invalid. For some contexts, one or the other might be zero, to describe an entire row or column or just unknown.
type ErrorContainer ¶
type ErrorContainer struct {
// contains filtered or unexported fields
}
ErrorContainer holds a list of errors. The tabular package uses a batched error model, where errors accumulate in the top-level linked object to which an item is being added.
func NewErrorContainer ¶
func NewErrorContainer() *ErrorContainer
NewErrorContainer creates an object which satisfies both ErrorReceiver and ErrorSource.
func (*ErrorContainer) AddError ¶
func (ec *ErrorContainer) AddError(err error)
AddError puts a Golang error object into the container. If the error is nil, this is a no-op.
func (*ErrorContainer) AddErrorList ¶
func (ec *ErrorContainer) AddErrorList(el []error)
AddErrorList takes a list of errors and adds them to the container. Any errors which are nil will be dropped.
func (*ErrorContainer) Errors ¶
func (ec *ErrorContainer) Errors() []error
Errors returns either a non-empty list of errors, or nil.
type ErrorReceiver ¶
type ErrorReceiver interface {
AddError(error)
}
An ErrorReceiver can accumulate errors for later retrieval.
type ErrorSource ¶
type ErrorSource interface {
Errors() []error
}
An ErrorSource can be interrogated for errors.
type Fielder ¶
type Fielder interface {
Fields() []string
}
Fielder for ability to grab "a row" from a type.
type Heighter ¶
type Heighter interface {
Height() int
}
Heighter lets an object override how tall it is.
type NoSuchCellError ¶
type NoSuchCellError struct { Location CellLocation // contains filtered or unexported fields }
NoSuchCellError is returned when a table is asked for a cell at some coordinates which do not exist within the table.
func (NoSuchCellError) Error ¶
func (e NoSuchCellError) Error() string
type PropertyCallback ¶
type PropertyCallback interface {
UpdateProperties(PropertyOwner) error
}
A PropertyCallback registration is used to update cell properties. Properties are akin to stdlib's "context", in that various users of cells can maintain their own namespaced properties, using a similar API. Examples might include terminal text properties, color, calculation attributes and more. A callback can be registered to be applied to any PropertyOwner, whether cell, row, column or table.
type PropertyOwner ¶
type PropertyOwner interface { SetProperty(interface{}, interface{}) error GetProperty(interface{}) interface{} }
PropertyOwner is the high-level interface satisfied by anything which holds metadata in the form of properties.
type Row ¶
type Row struct { *ErrorContainer // contains filtered or unexported fields }
A Row represents a row in a Table.
func NewRowWithCapacity ¶
NewRowWithCapacity create a new row pre-sized to contain the given number of Cells.
func (*Row) Add ¶
Add adds one cell to this row, and returns the row for chaining, thus r.Add(c1).Add(c2).Add(c3)
func (*Row) Cells ¶
Cells returns an iterable of the cells in a row. If it returns nil then you have a non-cell row (probably a separator).
func (*Row) GetProperty ¶
func (pi *Row) GetProperty(key interface{}) interface{}
GetProperty returns the property stored for the given key. If no such property has been stored, then nil will be returned. Thus we can't tell the difference between "nil stored" and "nothing stored", thus property storage is free to treat storing "nil" as "remove".
func (*Row) IsSeparator ¶
IsSeparator is true iff a row is a "separator".
func (*Row) Location ¶
func (r *Row) Location() (loc CellLocation)
Location returns a row's CellLocation where the column is 0
func (*Row) SetProperty ¶
func (pi *Row) SetProperty(key, value interface{}) error
SetProperty sets the value stored for a given key, removing any other values stored for that key first. If the value is nil then no value will be stored.
type Stringer ¶
type Stringer interface {
String() string
}
Stringer to match fmt's. Embedded newlines will be handled to provide lines.
type Table ¶
type Table interface { AddRow(row *Row) Table AddSeparator() Table NColumns() int NRows() int Headers() []Cell AddHeaders(items ...interface{}) Table AllRows() []*Row NewRowSizedFor() *Row AppendNewRow() *Row AddRowItems(items ...interface{}) Table CellAt(location CellLocation) (*Cell, error) Column(int) *column RegisterPropertyCallback(PropertyOwner, callbackTime, cbTarget, PropertyCallback) error InvokeRenderCallbacks() // Also the other interfaces embedded in ATable: ErrorReceiver ErrorSource PropertyOwner }
The Table interface is a thin wrapper around the actual *ATable struct, so that methods can all be on the interface and objects which embed an unnamed table can be used as tables.
If you want to create and use a table for pre-canned rendering then look at sub-packages for TextTable, HTMLTable, etc wrappers.
type TerminalCellWidther ¶
type TerminalCellWidther interface {
TerminalCellWidth() int
}
TerminalCellWidther should be implemented to override tabular's conception of how "wide" a cell's contents are.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
The html wrapper provides a means for generating HTML from a tabular table.
|
The html wrapper provides a means for generating HTML from a tabular table. |
Markdown core does not support tables; for the most portable support, assuming HTML is the final target, use the `html` sub-package instead.
|
Markdown core does not support tables; for the most portable support, assuming HTML is the final target, use the `html` sub-package instead. |
decoration
The decoration package provides controls for how text tables are decorated for rendering.
|
The decoration package provides controls for how text tables are decorated for rendering. |