Documentation
¶
Overview ¶
psv provides methods for handling tables of Pipe-Separated-Values (PSV)
Three basic use cases are supported:
1. Generating PSV tables from code:
doc := &psv.Document{}
doc.AppendRow([]string{"name","score"})
doc.AppendRow([]string{"Alice","3"})
doc.AppendRow([]string{"Bob","2"})
ouput, _ := doc.MarshalText()
fmt.Println(ouput)
| name | score |
| Alice | 3 |
| Bob | 2 |
2. Reading data from PSV tables into code:
input := `
| name | score |
| Alice | 3 |
| Bob | 2 |
`
// read the input
doc := &psv.Document{}
doc.UnmarshalText([]byte(input))
// the input may contain any number of tables
// loop through each table looking for 'interesting' data
for _, table := range doc.Tables() {
// ColumnByNameFunc provides a convenient name => column mapping
value := table.ColumnByNameFunc()
// DataRows() returns all rows except the first row (assumed to be a header)
// AllRows() returns all rows including the first row.
for r, row := range table.DataRows() {
fmt.Printf("%s points were awarded to %q\n",
value(row,"score"),
value(row,"name"),
)
}
}
// Output:
// 3 points were awarded to "Alice"
// 2 points were awarded to "Bob"
3. Re-formatting existing PSV tables via the `psv` command:
% cat input.txt | name | score | Alice | 3 | Bob | 2 % psv < input.txt > output.txt % cat output.txt | name | score | | Alice | 3 | | Bob | 2 |
Usage ¶
Document is the main aggregate for building or accessing PSV data. The Document type fulfills the encoding.TextMarshaler and encoding.TextUnmarshaler interfaces for conversion to and from the document's text form.
Documents are built incrementally via Append methods and may be read as a slice of rows. The ability to edit data or randomly access data is not provided.
Internally, a Document may contain any number of Table objects which can be accessed via the Document.Tables method.
Each table then has its own set of column names, prefix etc.
Ruler objects may be used to add separation lines to a table and may be placed anywhere within a table.
The [Markdown] formatter, however, will ignore all but the ruler that appears directly after the first row of data in the table, thus conforming to markdown's requirements.
e.g.
+---------+-------+ | name | score | | ------- | ----- | | Alice | 25 | | Bob | 17 | | Charlie | 10 | | ------- - ----- | | Dave | 9 | +---------+-------+
When re-formatted for Markdown would become:
| name | score | | ------- | ----- | | Alice | 25 | | Bob | 17 | | Charlie | 10 | | Dave | 9 |
Index ¶
- type Document
- func (doc *Document) AppendRow(row []string)
- func (doc *Document) AppendRuler(ruler *Ruler)
- func (doc *Document) AppendText(line string)
- func (doc *Document) MarshalText() (text []byte, err error)
- func (doc *Document) SetMarshalOptions(opts ...MarshalOption)
- func (doc *Document) SetTablePrefixOnce(prefix *Prefix)
- func (doc *Document) Tables() []*Table
- func (doc *Document) UnmarshalText(text []byte) error
- type DocumentItem
- type MarshalOption
- type Prefix
- type Ruler
- type Table
- func (tbl *Table) AllRows() [][]string
- func (tbl *Table) AppendRow(row []string)
- func (tbl *Table) AppendRuler(ruler *Ruler)
- func (tbl *Table) ColumnByNameFunc() func([]string, string) string
- func (tbl *Table) ColumnNames() []string
- func (tbl *Table) DataRows() [][]string
- func (tbl *Table) SetPrefixOnce(prefix *Prefix)
- type Text
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Document ¶
type Document struct {
*Prefix // prefix to apply to all tables within in the document
// contains filtered or unexported fields
}
Document represents a single text file which may contain any number of tables.
func (*Document) AppendRow ¶
AppendRow appends a row to the end of the current table.
A new table will be added to the document if necessary.
func (*Document) AppendRuler ¶
AppendRuler appends a ruler to the end of the current table.
A new table will be added to the document if necessary.
func (*Document) AppendText ¶
AppendText appends a line of text to the end of the document.
Text lines are in no-way modified and are reproduced verbatim.
Text lines separate multiple tables within a document.
func (*Document) MarshalText ¶
MarshalText returns a text representation of a document, which can be parsed by Document.UnmarshalText
Each table will be re-aligned according to the rules defined via Document.SetMarshalOptions
See also encoding.TextMarshaler
func (*Document) SetMarshalOptions ¶
func (doc *Document) SetMarshalOptions(opts ...MarshalOption)
TODO: 2025-01-22 define how marshaling / unmarshaling shoulg be configured
func (*Document) SetTablePrefixOnce ¶
SetTablePrefixOnce sets the prefix of the current table if it has not already been set. This is intended for use when parsing tables line-by-line, in which case the prefix of the first row should be used for all rows of the table.
A new table will be added to the document if necessary.
func (*Document) UnmarshalText ¶
UnmarshalText parses a psv table into an existing Table object
See also encoding.TextUnmarshaler
type DocumentItem ¶
DocumentItem represents a single block of text or a table within a document.
If both Text and Table are not nil, then the Text is positioned before the table.
type MarshalOption ¶
type MarshalOption struct{}
TODO: 2025-01-22 define how marshaling / unmarshaling shoulg be configured
type Prefix ¶
type Prefix struct {
Pattern string
// contains filtered or unexported fields
}
Prefix can be used to remove or add a prefix from / to each row of a table.
This is useful for re-formatting tables which are embedded in e.g. code comments.
Example ¶
package main
import (
"fmt"
"codeberg.org/japh/psv"
)
func main() {
text := `
// verified scores
| name | scort |
| Alice | 12 |
// unverified scores:
// | name | score |
// | Adam | 6 |
`
doc := &psv.Document{
Prefix: &psv.Prefix{Pattern: `//`},
}
// TODO(Steve): 2025-01-22 UnmarshalText not yet implemented
doc.UnmarshalText([]byte(text))
for tn, tbl := range doc.Tables() {
fmt.Printf("%d: table with indent %q\n", tn, tbl.Prefix.Pattern)
}
// TODO: 2025-01-22 Output:
// 0: table with indent " "
// 1: table with indent " // "
}
type Ruler ¶
type Ruler struct {
Line int
}
Ruler represents a horizontal separator line within a table.
Rulers grow and shrink depending on the width of the data in the column.
Rulers may also include formatting hints for each column individually, e.g. whether the column's data should be aligned to the left, right or center, and whether or not the rows should be sorted by the data in a column.
type Table ¶
type Table struct {
*Prefix
// contains filtered or unexported fields
}
Table represents a single table of data.
func (*Table) AllRows ¶
Example ¶
package main
import (
"fmt"
"codeberg.org/japh/psv"
)
func main() {
tbl := &psv.Table{}
tbl.AppendRow([]string{"name", "score"})
tbl.AppendRow([]string{"Adam", "6"})
for r, row := range tbl.AllRows() {
fmt.Printf("%d: %v\n", r, row)
}
}
Output: 0: [name score] 1: [Adam 6]
func (*Table) AppendRuler ¶ added in v0.1.1
func (*Table) ColumnByNameFunc ¶
ColumnByNameFunc returns a function which returns a column's value from a row of data, indexed by the column name.
func (*Table) ColumnNames ¶ added in v0.1.1
Example ¶
package main
import (
"fmt"
"codeberg.org/japh/psv"
)
func main() {
tbl := &psv.Table{}
tbl.AppendRow([]string{"name", "score"})
tbl.AppendRow([]string{"Adam", "6"})
names := tbl.ColumnNames()
fmt.Printf("column names: %v\n", names)
}
Output: column names: [name score]
func (*Table) DataRows ¶ added in v0.1.1
Example ¶
package main
import (
"fmt"
"codeberg.org/japh/psv"
)
func main() {
tbl := &psv.Table{}
tbl.AppendRow([]string{"name", "score"})
tbl.AppendRow([]string{"Adam", "6"})
for r, row := range tbl.DataRows() {
fmt.Printf("%d: %v\n", r, row)
}
}
Output: 0: [Adam 6]
func (*Table) SetPrefixOnce ¶
SetPrefixOnce sets the prefix for a table.