-
Notifications
You must be signed in to change notification settings - Fork 7
/
tabular.go
134 lines (117 loc) · 3.5 KB
/
tabular.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package tabular
import (
"fmt"
"strings"
)
// Output - parsed table's header, subheader and format specifier
type Output struct {
Header string
SubHeader string
Format string
}
// Table - maps and orders short names of columns to their structure defining:
// full name, length and whether it's right justified
type Table struct {
Columns map[string]*Column
order *[]string
}
// Column - defines column's name, length and if it's right justified
type Column struct {
Name string
Length int
RightJustified bool
}
// All - pass this to Print() or Parse() to print or parse all columns of a table
const All = "*"
// New - Creates a new table
func New() Table {
return Table{
Columns: map[string]*Column{},
order: &[]string{},
}
}
// Print - does the following:
//
// 1) prints a table style heading for a given list of columns,
// for example, if Columns are defined as:
//
// "env": Column{Name: "Environment", Length: 14},
// "cls": Column{Name: "Cluster", Length: 40},
// "srv": Column{Name: "Service", Length: 35},
//
// It'll produce:
//
// Environment Cluster Service
// -------------- ---------------------------------------- -----------------------------------
//
// 2) Returns an fmt style format specifier string that you can use
// to output values under the above heading via Printf(format,...):
//
// %-14v %-40v %-35v
func (tbl Table) Print(cols ...string) string {
t := tbl.parse(cols...)
fmt.Println(t.Header)
fmt.Println(t.SubHeader)
return t.Format
}
// Parse - constructs Table's Output structure containing it's header,
// sub-header and format modifier out of a given list of columns.
//
// To simply print the table's title call Print() instead.
//
// Parse() is usefull when you need to control where
// to output the title, for example to a log or a trace file.
func (tbl Table) Parse(cols ...string) Output {
return tbl.parse(cols...)
}
// Col - adds a new column to an existing table
func (tbl Table) Col(shortName, fullName string, columnLength int) {
tbl.Columns[shortName] = &Column{Name: fullName, Length: columnLength}
tbl.appendColumn(shortName)
}
// ColRJ - adds a new Right Justified column to an existing table
func (tbl Table) ColRJ(shortName, fullName string, columnLength int) {
tbl.Columns[shortName] = &Column{Name: fullName, Length: columnLength, RightJustified: true}
tbl.appendColumn(shortName)
}
func (tbl Table) appendColumn(shortName string) {
*tbl.order = append(*tbl.order, shortName)
}
func (tbl Table) parse(cols ...string) Output {
var header string
var subHeader string
var format string
var space string
if len(cols) == 1 && cols[0] == All {
cols = *tbl.order
}
for _, c := range cols {
cf := tbl.Columns[c].f()
header = header + space + fmt.Sprintf(cf, tbl.Columns[c].Name)
subHeader = subHeader + space + fmt.Sprintf(cf, r(tbl.Columns[c].Length))
format = format + space + cf
space = " "
}
return Output{
Header: header,
SubHeader: subHeader,
Format: format + "\n",
}
}
// f() returns fmt formatting, for example:
//
// Column{Name: "Environment", Length: 14, RightJustified: false}
// result => %-14v
//
// Column{Name: "PCT", Length: 5, RightJustified: true}
// result => %5v
func (c *Column) f() string {
pad := "-"
if c.RightJustified {
pad = ""
}
return fmt.Sprintf("%%%s%dv", pad, c.Length)
}
// r() returns a dashed line for table formatting "------"
// with it's length set to the length of l
func r(l int) string { return strings.Repeat("-", l) }