psv

package module
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: Jan 30, 2022 License: MIT Imports: 8 Imported by: 0

README

PSV - Pipe Separated Values

(or "Data Table Parser")

psv is a unix command line utility (and go package), to help construct tables of data, with a focus on human readibility and the exchange of intentions rather than a pure, machine-readable data transfer format.

The PSV data format has been used, ad-hoc, by programmers since the dawn of programming, and is similar to CSV, TSV or JSON, but with a different set of objectives.

Introductory Example

When programming, especially when preparing data for testing, it is often useful to define a simple table of example data.

Such Data Tables are also a core part of the Gherkin language used to describe BDD scenarios.

Often, we end up with something similar to JSON:

(The content of each of these examples is identical, we're focussing on readability here)

yumminess = [
            {name:"Schnitzel",region:"Germany",popularity:5,variations:1,difficulty:5},
            {name:"Pizza",region:"Italy",popularity:4,variations:100,difficulty:2},
            {name:"Spaghetti",region:"Italy",popularity:3,variations:5,difficulty:1},
            {name:"Quiche",region:"France",popularity:1,variations:10,difficulty:1},
            {name:"Fried Rice",region:"Asia",popularity:3,variations:50,difficulty:1},
            {name:"Chicken Jalfrezi",region:"India",popularity:3,variations:3,difficulty:5},
            ]

or CSV (Comma Separated Values):

yumminess = 'name,region,popularity,variations,difficulty
Schnitzel,Germany,5,1,5
Pizza,Italy,4,100,2
Spaghetti,Italy,3,4,1
Quiche,France,1,10,1
"Fried Rice",Asia,3,50,1
"Chicken Jalfrezi",India,3,3,5'

or TSV (Tab Separated Values):

yumminess = 'name	region	popularity	variations	difficulty
Schnitzel	Germany	5	1	5
Pizza	Italy	4	100	2
Spaghetti	Italy	3	4	1
Quiche	France	1	10	1
"Fried Rice"	Asia	3	50	1
"Chicken Jalfrezi"	India	3	3	5'

or PSV (Pipe Separated Values or Data Table):

yumminess = '
            +------------------+---------+------------+------------+------------+
            | name             | region  | popularity | variations | difficulty |
            | ================ | ======= | ========== | ========== | ========== |

            Classic European:
            | Schnitzel        | Germany | 5          | 1          | 5          |
            | Pizza            | Italy   | 4          | 100        | 2          |
            | Spaghetti        | Italy   | 3          | 4          | 1          |
            | Quiche           | France  | 1          | 10         | 1          |

            Exotic:
            | Fried Rice       | Asia    | 3          | 50         | 1          |
            | Chicken Jalfrezi | India   | 3          | 3          | 4          |
            +------------------+---------+------------+------------+------------+

            Note: 72% of these statistics are probably 86% inaccurate, or
            completely made up :-)
            '

If you find the last example the easiest to read, then you might like psv.

Intended Usage

psv has two main use cases:

CLI Usage

The psv command reads PSV table data from STDIN and prints the data back to STDOUT with any tabular data formatted nicely 1.

[^1]: to my eyes at least :-)

This can be utilized by many unix text editors, so you type your data into your file and then pipe the table through psv to format it nicely.

Rules for creating tables:

  1. lines that look like separators will generate separator lines to fit the table's columns
  2. lines that begin with | are data rows
  3. anything else is decorative text

Lines outside the table are left unchanged, while all lines within the first and last row of the table are indented and formatted.

CLI Options
  • -i <indent>

    • indents the formatted table by prefixing each table row with the given <indent> string.
    • if <indent> is an unsigned integer less than 64, then the indent will be that number of spaces
    • if <indent> contains non-whitespace characters, those characters will be ignored before table rows while decoding and will be inserted before each table row while encoding.
  • -s

    • squash empty columns and multiple empty table rows or decoration lines
    • squashing only occurs on table rows and rulers
      • decoration lines outside the table are left unchanged
CLI Example

In this example, the text between cat and EOT represents what you might type in your editor, and everything after EOT is what would happen to your text after you run it through psv.

cat <<EOT | psv

A table row is any line beginning with a pipe character
    
    |name|region
    
comments between rows will be indented
|Pizza|Italy

horizontal lines can be generated too:
+--
EOT

A table row is any line beginning with a pipe character

    | name      | region  |

    comments between rows will be indented
    | Schnitzel | Germany |
    | Pizza     | Italy   |
    :           :         :

    horizontal lines can be generated too:
    +-----------+---------+
Go Package

Go encourages programmers to write lots of tests while programming. However, a typical test often looks similar to the JSON example above.

With the psv package, we can do better.

package test

import (
       "testing"

       "codeberg.org/japh/psv"
       )

func TestYummyFood(t *testing) {

    testTable := psv.NewTable(`
                              +-----------+---------+------------+------------+------------+
                              | name      | region  | popularity | variations | difficulty |
                              | ========= | ======= | ========== | ========== | ========== |

                              Classic European:
                              | Schnitzel | Germany | 5          | 1          | 5          |
                              | Pizza     | Italy   | 4          | 100        | 2          |
                              :           :         :            :            :            :
                              :           :         :            :            :            :
                              `)

    for _, test := range testTable.Data {
        ...
    }
}

Remember, we can use the psv command line tool to help keep the table pretty. Inside our test code, we can now use the same psv code to parse our tables and provide us with a [][]string table. ([][]string is go's way of saying a 2D array of strings)

The psv.Table struct provides the following:

- `Data` is the `[][]string` table of data.
  - The `Data` table *only* contains data from the rows beginning with `|`!
  - All data has leading and trailing white-space removed

- `Decorations` is a `[]Decoration` slice, which provides access to the
  non-data lines of the string.

Features

psv classifies each line of text as:

  • a data row
    • any line beginning with '|'
  • a ruler (or separator line)
    • lines which contain only a selection of the characters |, ':', '#', =, ~, -, + or whitespace
  • or text
    • any lines which are neither data rows nor rulers
Data Rows
  • Always begin with a | character (after optional indentation)

    • Are indented to match the indentation of the first data row or ruler
  • The number of columns in each row do not have to be the same in every row

    • Columns are added so that all columns appear from the first to the last row of the table.
  • Columns may be empty

    • Empty trailing columns are always removed automatically
    • psv -s or the psv.Table.Squash option may be used to squash empty columns and multiple empty rows
      • (one empty row in each series of empty rows are kept)
  • Columns do not have to align vertically

    • That's exactly what psv does for you :-)
    • Whitespace around | characters is always re-jiggered so that the columns line up nicely
    • Whitespace within a cell's data is never removed
  • Known issue it is not currently possible to include a '|' character in a cell's data.

    • This restriction should be removed in a future version of psv
  • All data rows are available via the psv.Table.Data struct

Example:

|hello
|           what's up              |           doc
| we're going to | outer s p  a   c   e    !
|too much?||||see|||||||||||

becomes:

| hello          |                           |  |  |     |
| what's up      | doc                       |  |  |     |
| we're going to | outer s p  a   c   e    ! |  |  |     |
| too much?      |                           |  |  | see |
Rulers
(or separator lines)

Rulers are decoration only, but can help separate parts of your table if needed.

As such, rulers are not part of the psv.Table.Data array when parsed, but are, instead stored in psv.Table.Decorations.

Rulers, like data rows, may appear anywhere within the text provided to psv, even if they are not directly adjacent to any data rows. This makes drawing outer boxes easy, just put the top- and bottom rulers wherever you want them to be.

To create a ruler, add a line containing only the characters |, ':', '#', =, ~, -, + or whitespace.

The presence of any other characters will cause the line to be treated as a data row (if the first character is |) or as plain text.

There are two ways to specify how your ruler should look:

  1. via a 1- to 4-character format specification
    • each character specifies the appearance of one aspect of the ruler.
    • in order, the characters are:
      1. the vertical lines used for the outer border of the table
      2. the padding character used on either side of vertical lines
      3. the horizontal line character
      4. the vertical line to use between columns
    • Special case: the | pipe character is never used for padding or horizontal lines!

Example:

+--
| one | two | three | fourty-two |
|=
| -
|  :
|--+
+--

becomes:

+-----+-----+-------+------------+
| one | two | three | fourty-two |
|=====|=====|=======|============|
| --- | --- | ----- | ---------- |
|     :     :       :            |
|-----+-----+-------+------------|
+-----+-----+-------+------------+

Special case:

Lines that only contain |'s are treated specially:

Example:

+-----+-----+-------+------------+
| one | two | three | fourty-two |
|=====|=====|=======|============|
|
||
| |
|||
|  |
||||

becomes:

+-----+-----+-------+------------+
| one | two | three | fourty-two |
|=====|=====|=======|============|
|     |     |       |            |
|     |     |       |            |
|     |     |       |            |
|     |     |       |            |
|     |     |       |            |
|     |     |       |            |
  1. or via a template ruler
    • if more than 4 characters are present, psv tries to use the line as a template.
    • the first two characters are the outer border and padding characters
    • following characters are assumed to be a series of horizontal line characters and possibly some individual column separators.
      • notes:
        • not every constellation of column widths can be parsed unambiguously.
        • hand-made templates are easy to get wrong.
        • rulers which were previously generated by psv are highly likely to be reproduced faithfully.
        • if in doubt, replace the template row with a simple format specification, as they are unambiguous.

Example:

+---------+----------+-------+------------+
| one | two | three | fourty-two |
|==|===|===|====|
|  | - | - | -- |
|  :   :   :    |
|--+---+---+----|
+--+---+---+----+

becomes:

+-----+-----+-------+------------+
| one | two | three | fourty-two |
|=====|=====|=======|============|
| --- | --- | ----- | ---------- |
|     :     :       :            |
|-----+-----+-------+------------|
+-----+-----+-------+------------+
Text

Any lines which are not data rows or rulers are simply text.

Text lines are never modified, except that their indentation will be changed to match the data rows if the text line is within the table.

Lines which have only whitespace are reduced to an empty line.

Example:

                Work Plan
    + -
    | task | due date | done |
    + -

Important:
| read 'the net' | today 

                BOOOORRRING
    | take the rubbish out | never | sure
    + -

What else could I do?

becomes:

                Work Plan
    + -------------------- + -------- + ---- +
    | task                 | due date | done |
    + -------------------- + -------- + ---- +

    Important:
    | read 'the net'       | today    |      |

    BOOOORRRING
    | take the rubbish out | never    | sure |
    + -------------------- + -------- + ---- +

What else could I do?

Documentation

Overview

Package psv provides a way to convert arrays of structs or maps into pretty, pipe-separated text tables, and vice-versa. (psv: pipe separated values)

Example

data := []map[string]string{
    {"name":"Joe", "age":"42"},
    {"name":"Freddie", "age":"41"},
    {"name":"Amy", "age":"don't ask"},
}

tbl := table.Marshal(data)
tbl.Columns = []string{"age","name"}
tbl.Indent = "    "
tbl.Decorations = []table.Decoration{
    {Line:0,Text:`The "who's-who" list of people`},
    {Line:1},
    {Line:2,Ruler:"+ -"},
    {Line:4,Ruler:"|==="},
}
fmt.Println(tbl.Encode())

Output

The "who's-who" list of people

+ --------- + ------- +
| age       | name    |
|=====================|
| 42        | Joe     |
| 41        | Freddie |
| don't ask | Amy     |

The table data and appearance can be set up via any of the following examples:

// convert a string into a table
tbl := table.Decode(string)
// all decorations are retained for re-rendering, e.g.
fmt.Println(tbl.Encode())

// convert a string into a data structure
// data returned in interface{}
table.Unmarshal(string,interface{})

// create a table from scratch (string data only)
tbl := table.NewTable()
tbl.Indent = "..."
tbl.Decorations = []*Decoration{...}
tbl.Data = [][]string{...}
fmt.Println(tbl.Encode())

// convert a data structure into a table (for rendering)
tbl := table.Marshal(interface{})
// optionally modify aspects of the table
tbl.Indent = "..."
tbl.Decorations = []*Decoration{...}
fmt.Println(tbl.Encode())

References

This package focusses on data representation, human readability and the exchange of intentions, which a computer may incidentally be able to make sense of. Mostly, each cell of a table is a simple, single string value, however, with a bit of additional work, the string values may be mapped to slices or maps of slightly more complicated (incl. custom) structures.

The lack of support for every last, complicated, nested structure is intentional.

There a large number of csv, tsv, dsv packages availble on pkg.go.dev, but they all concentrate on "machine readable data exchange". Nevertheless, they served as inspiration for this package as well.

psv always *felt* like the wrong program to write, but I was unable to find an existing program with suitable features:

- simple to use, suitable for as an editor plugin / shell pipe - align columnated data - while ignoring lines which aren't columnated

The unix tools [column] and [tbl] and go's own encoding/csv package all served as a good basis, but they all had different goals.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Version = `v0.0.6`

Functions

This section is empty.

Types

type Decoration

type Decoration struct {
	Line   int    // 1-based number of this line's position in the resulting table
	Indent string // only used to re-construct original indentation outside a table's bounds
	Text   string // un-indented text to be inserted into the table, may be ""
	Ruler  string // ruler specification, see Ruler type
}

Decoration specifies a single non-table text line to be positioned at a specific point in the generated table string.

type Indenter

type Indenter struct {
	// contains filtered or unexported fields
}
Example
inputLines := []string{
	``,
	`hello`,
	`    hello`,
	`// hello`,
	`// // hello`,
	`    //    hello`,
}

patterns := []struct {
	pattern string
	isFinal bool
}{
	{pattern: ""},
	{pattern: ``, isFinal: true},
	{pattern: `0`},
	{pattern: `-1`},
	{pattern: `-0`},
	{pattern: `+1`},
	{pattern: `1`},
	{pattern: `63`},
	{pattern: `64`},
	{pattern: `  `},
	{pattern: `//`},
	{pattern: ` //`},
	{pattern: ` // `},
	{pattern: `> >`},
	{pattern: ` > >`},
	{pattern: ` > > `},
}

PATTERNS:
for _, p := range patterns {
	for _, l := range inputLines {
		i := NewIndenter()

		fmt.Printf("indent option:    %q\n", p.pattern)

		if p.pattern != "" || p.isFinal {
			err := i.SetIndent(p.pattern)
			if err != nil {
				fmt.Printf("failed to set indent: %q\n\n", err)
				continue PATTERNS
			}
		}

		fmt.Printf("indenter:         %s\n", i.String())

		found := i.FindIndent(l)
		i.FinalizeIndent()

		fmt.Printf("input line:       %q\n", l)
		fmt.Printf("detected  indent: %q\n", found)
		fmt.Printf("finalised indent: %q\n", i.Indent()+l[len(found):])
		fmt.Println()
	}
	fmt.Println("----")
}
Output:

indent option:    ""
indenter:         "" (default)
input line:       ""
detected  indent: ""
finalised indent: ""

indent option:    ""
indenter:         "" (default)
input line:       "hello"
detected  indent: ""
finalised indent: "hello"

indent option:    ""
indenter:         "" (default)
input line:       "    hello"
detected  indent: "    "
finalised indent: "    hello"

indent option:    ""
indenter:         "" (default)
input line:       "// hello"
detected  indent: ""
finalised indent: "// hello"

indent option:    ""
indenter:         "" (default)
input line:       "// // hello"
detected  indent: ""
finalised indent: "// // hello"

indent option:    ""
indenter:         "" (default)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: "    //    hello"

----
indent option:    ""
indenter:         "" (finalised)
input line:       ""
detected  indent: ""
finalised indent: ""

indent option:    ""
indenter:         "" (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: "hello"

indent option:    ""
indenter:         "" (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: "hello"

indent option:    ""
indenter:         "" (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: "// hello"

indent option:    ""
indenter:         "" (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: "// // hello"

indent option:    ""
indenter:         "" (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: "//    hello"

----
indent option:    "0"
indenter:         "" (finalised)
input line:       ""
detected  indent: ""
finalised indent: ""

indent option:    "0"
indenter:         "" (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: "hello"

indent option:    "0"
indenter:         "" (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: "hello"

indent option:    "0"
indenter:         "" (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: "// hello"

indent option:    "0"
indenter:         "" (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: "// // hello"

indent option:    "0"
indenter:         "" (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: "//    hello"

----
indent option:    "-1"
failed to set indent: "indent must be an unsigned integer <64 or non-numeric string"

indent option:    "-0"
failed to set indent: "indent must be an unsigned integer <64 or non-numeric string"

indent option:    "+1"
failed to set indent: "indent must be an unsigned integer <64 or non-numeric string"

indent option:    "1"
indenter:         " " (finalised)
input line:       ""
detected  indent: ""
finalised indent: " "

indent option:    "1"
indenter:         " " (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: " hello"

indent option:    "1"
indenter:         " " (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: " hello"

indent option:    "1"
indenter:         " " (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: " // hello"

indent option:    "1"
indenter:         " " (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: " // // hello"

indent option:    "1"
indenter:         " " (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: " //    hello"

----
indent option:    "63"
indenter:         "                                                               " (finalised)
input line:       ""
detected  indent: ""
finalised indent: "                                                               "

indent option:    "63"
indenter:         "                                                               " (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: "                                                               hello"

indent option:    "63"
indenter:         "                                                               " (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: "                                                               hello"

indent option:    "63"
indenter:         "                                                               " (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: "                                                               // hello"

indent option:    "63"
indenter:         "                                                               " (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: "                                                               // // hello"

indent option:    "63"
indenter:         "                                                               " (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: "                                                               //    hello"

----
indent option:    "64"
failed to set indent: "indent must be an unsigned integer <64 or non-numeric string"

indent option:    "  "
indenter:         "  " (finalised)
input line:       ""
detected  indent: ""
finalised indent: "  "

indent option:    "  "
indenter:         "  " (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: "  hello"

indent option:    "  "
indenter:         "  " (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: "  hello"

indent option:    "  "
indenter:         "  " (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: "  // hello"

indent option:    "  "
indenter:         "  " (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: "  // // hello"

indent option:    "  "
indenter:         "  " (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: "  //    hello"

----
indent option:    "//"
indenter:         "//" (default)
input line:       ""
detected  indent: ""
finalised indent: "// "

indent option:    "//"
indenter:         "//" (default)
input line:       "hello"
detected  indent: ""
finalised indent: "// hello"

indent option:    "//"
indenter:         "//" (default)
input line:       "    hello"
detected  indent: "    "
finalised indent: "//    hello"

indent option:    "//"
indenter:         "//" (default)
input line:       "// hello"
detected  indent: "// "
finalised indent: "// hello"

indent option:    "//"
indenter:         "//" (default)
input line:       "// // hello"
detected  indent: "// // "
finalised indent: "// // hello"

indent option:    "//"
indenter:         "//" (default)
input line:       "    //    hello"
detected  indent: "    //    "
finalised indent: "    //    hello"

----
indent option:    " //"
indenter:         " //" (finalised)
input line:       ""
detected  indent: ""
finalised indent: " //"

indent option:    " //"
indenter:         " //" (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: " //hello"

indent option:    " //"
indenter:         " //" (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: " //hello"

indent option:    " //"
indenter:         " //" (finalised)
input line:       "// hello"
detected  indent: "// "
finalised indent: " //hello"

indent option:    " //"
indenter:         " //" (finalised)
input line:       "// // hello"
detected  indent: "// // "
finalised indent: " //hello"

indent option:    " //"
indenter:         " //" (finalised)
input line:       "    //    hello"
detected  indent: "    //    "
finalised indent: " //hello"

----
indent option:    " // "
indenter:         " // " (finalised)
input line:       ""
detected  indent: ""
finalised indent: " // "

indent option:    " // "
indenter:         " // " (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: " // hello"

indent option:    " // "
indenter:         " // " (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: " // hello"

indent option:    " // "
indenter:         " // " (finalised)
input line:       "// hello"
detected  indent: "// "
finalised indent: " // hello"

indent option:    " // "
indenter:         " // " (finalised)
input line:       "// // hello"
detected  indent: "// // "
finalised indent: " // hello"

indent option:    " // "
indenter:         " // " (finalised)
input line:       "    //    hello"
detected  indent: "    //    "
finalised indent: " // hello"

----
indent option:    "> >"
indenter:         "> >" (default)
input line:       ""
detected  indent: ""
finalised indent: "> > "

indent option:    "> >"
indenter:         "> >" (default)
input line:       "hello"
detected  indent: ""
finalised indent: "> > hello"

indent option:    "> >"
indenter:         "> >" (default)
input line:       "    hello"
detected  indent: "    "
finalised indent: "> >    hello"

indent option:    "> >"
indenter:         "> >" (default)
input line:       "// hello"
detected  indent: ""
finalised indent: "> > // hello"

indent option:    "> >"
indenter:         "> >" (default)
input line:       "// // hello"
detected  indent: ""
finalised indent: "> > // // hello"

indent option:    "> >"
indenter:         "> >" (default)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: "> >    //    hello"

----
indent option:    " > >"
indenter:         " > >" (finalised)
input line:       ""
detected  indent: ""
finalised indent: " > >"

indent option:    " > >"
indenter:         " > >" (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: " > >hello"

indent option:    " > >"
indenter:         " > >" (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: " > >hello"

indent option:    " > >"
indenter:         " > >" (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: " > >// hello"

indent option:    " > >"
indenter:         " > >" (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: " > >// // hello"

indent option:    " > >"
indenter:         " > >" (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: " > >//    hello"

----
indent option:    " > > "
indenter:         " > > " (finalised)
input line:       ""
detected  indent: ""
finalised indent: " > > "

indent option:    " > > "
indenter:         " > > " (finalised)
input line:       "hello"
detected  indent: ""
finalised indent: " > > hello"

indent option:    " > > "
indenter:         " > > " (finalised)
input line:       "    hello"
detected  indent: "    "
finalised indent: " > > hello"

indent option:    " > > "
indenter:         " > > " (finalised)
input line:       "// hello"
detected  indent: ""
finalised indent: " > > // hello"

indent option:    " > > "
indenter:         " > > " (finalised)
input line:       "// // hello"
detected  indent: ""
finalised indent: " > > // // hello"

indent option:    " > > "
indenter:         " > > " (finalised)
input line:       "    //    hello"
detected  indent: "    "
finalised indent: " > > //    hello"

----

func NewIndenter

func NewIndenter() *Indenter

func (*Indenter) FinalizeIndent

func (i *Indenter) FinalizeIndent()

func (*Indenter) FindIndent

func (i *Indenter) FindIndent(text string) string

func (*Indenter) Indent

func (i *Indenter) Indent() string

func (*Indenter) Prefix

func (i *Indenter) Prefix() string

func (*Indenter) SetIndent

func (i *Indenter) SetIndent(indent string) error

func (*Indenter) String

func (i *Indenter) String() string

type Options

type Options struct {
	Squash        bool   // squash multiple blank lines into a single blank line when encoding
	Quotes        string // prioritized list of preferred quoting styles
	IndentPattern string // user-provided indent to use
	IndentIsFinal bool   // flag to force the use of Options.Indent (required to force the use of "")
}

type Ruler

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

Ruler represents a horizontal separator to be placed within a table.

Rulers only contain the characters |, :, *, +, - and optional spaces.

When a table is rendered, rulers are generated to fit the column widths of the table.

If the input string contains 4 runes or less, it is intepreted as a format:

e.g.   '| -:'
        |||+--  internal column separator
        ||+---  horizonal line
        |+----  padding
        +-----  outer border

If the input string is more than 4 runes, it is assumed to be a previously-generated ruler, and is analysed to determine the format.

If the format of a ruler cannot be determined, the 'border' rune will be 0 and the original input is used. (non-destructive failure)

func NewRuler

func NewRuler(input string) (*Ruler, error)

NewRuler creates a new ruler based on a format or previously rendered ruler. Note: a returned error is really only a warning! The returned *Ruler is still valid and usable!

func (*Ruler) Encode

func (r *Ruler) Encode(widths []int) string

Encode generates a string using the ruler's format to match the column widths provided in 'widths'

Example
columnWidths := []int{1, 2, 3, 4}
ruler, _ := NewRuler("| -:")

fmt.Println(ruler.Encode(columnWidths))
Output:

| - : -- : --- : ---- |

type Scanner

type Scanner interface {
	Scan() bool
	Text() string
}

type Table

type Table struct {
	Options                   // configuration options
	*Indenter                 // indent matcher and producer
	FirstRow    int           // first row of table data
	LastRow     int           // last row of table data
	Data        [][]string    // 2-Dimensional array of string cells indexed by [row][column]
	Decorations []*Decoration // an array of decorations to add to the table
}

Table is a structure used to encapsulate a table of string data, which can be re-rendered with correct indentation and column alignment. The exported fields of Table may be used to customize the rendered result.

func NewTable

func NewTable() *Table

NewTable creates a new, empty table. Use its public fields to setup the data to be printed. See also: encode_test.go

func (*Table) AnalyseData

func (t *Table) AnalyseData() (rows, cols int, width []int)

func (*Table) Decode

func (t *Table) Decode(input string) error

func (*Table) Encode

func (t *Table) Encode() string

func (*Table) Read

func (t *Table) Read(in Scanner) error

func (*Table) Write

func (t *Table) Write(b Writer)

Encode converts the 2-Dimensional slice of string data in the table into a pretty, pipe-separated table as a single, printable string.

type Writer

type Writer interface {
	WriteString(string) (int, error) // e.g. bytes.Builder or strings.Builder
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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