Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit b72a1a0

Browse files
authored
Merge pull request #3 from InVisionApp/select-star
supports select * style of table parsing and printing
2 parents 7afe17a + 5772e53 commit b72a1a0

5 files changed

Lines changed: 136 additions & 113 deletions

File tree

README.md

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,17 @@ import (
2424
"github.com/InVisionApp/tabular"
2525
)
2626

27-
var tab tabular.Columns
27+
var tab tabular.Table
2828

2929
func init() {
3030
tab = tabular.New()
3131
tab.Col("env", "Environment", 14)
3232
tab.Col("cls", "Cluster", 10)
3333
tab.Col("svc", "Service", 15)
3434
tab.Col("hst", "Database Host", 20)
35-
tab.Col("pct", "%CPU", 7)
36-
tab["pct"].RightJustified = true
35+
tab.ColRJ("pct", "%CPU", 7)
3736
}
3837

39-
// Sample data-set
4038
var data = []struct {
4139
e, c, s, d string
4240
v float64
@@ -72,30 +70,24 @@ var data = []struct {
7270
}
7371

7472
func main() {
75-
// Print Environments and Clusters
73+
// Print a subset of columns (Environments and Clusters)
7674
format := tab.Print("env", "cls")
7775
for _, x := range data {
7876
fmt.Printf(format, x.e, x.c)
7977
}
8078

81-
// Print Environments, Clusters and Services
82-
format = tab.Print("env", "cls", "svc")
79+
// Print All Columns
80+
format = tab.Print("*")
8381
for _, x := range data {
84-
fmt.Printf(format, x.e, x.c, x.s)
82+
fmt.Printf(format, x.e, x.c, x.s, x.d, x.v)
8583
}
8684

87-
// Print Everything
88-
format = tab.Print("cls", "svc", "hst", "pct")
89-
for _, x := range data {
90-
fmt.Printf(format, x.c, x.s, x.d, x.v)
91-
}
92-
93-
// Print Everything to a custom destination such as a log
94-
table := tab.Parse("cls", "svc", "hst", "pct")
85+
// Print All Columns to a custom destination such as a log
86+
table := tab.Parse("*")
9587
log.Println(table.Header)
9688
log.Println(table.SubHeader)
9789
for _, x := range data {
98-
log.Printf(table.Format, x.c, x.s, x.d, x.v)
90+
log.Printf(table.Format, x.e, x.c, x.s, x.d, x.v)
9991
}
10092
}
10193
```
@@ -110,24 +102,17 @@ production cluster-1
110102
production cluster-2
111103
production cluster-2
112104
113-
Environment Cluster Service
114-
-------------- ---------- ---------------
115-
production cluster-1 service-a
116-
production cluster-1 service-b
117-
production cluster-2 service-a
118-
production cluster-2 service-b
119-
120-
Cluster Service Database Host %CPU
121-
---------- --------------- -------------------- -------
122-
cluster-1 service-a database-host-1 70.01
123-
cluster-1 service-b database-host-2 99.51
124-
cluster-2 service-a database-host-1 70.01
125-
cluster-2 service-b database-host-2 99.51
126-
127-
2018/04/26 10:17:27 Cluster Service Database Host %CPU
128-
2018/04/26 10:17:27 ---------- --------------- -------------------- -------
129-
2018/04/26 10:17:27 cluster-1 service-a database-host-1 70.01
130-
2018/04/26 10:17:27 cluster-1 service-b database-host-2 99.51
131-
2018/04/26 10:17:27 cluster-2 service-a database-host-1 70.01
132-
2018/04/26 10:17:27 cluster-2 service-b database-host-2 99.51
105+
Environment Cluster Service Database Host %CPU
106+
-------------- ---------- --------------- -------------------- -------
107+
production cluster-1 service-a database-host-1 70.01
108+
production cluster-1 service-b database-host-2 99.51
109+
production cluster-2 service-a database-host-1 70.01
110+
production cluster-2 service-b database-host-2 99.51
111+
112+
2018/05/14 11:19:41 Environment Cluster Service Database Host %CPU
113+
2018/05/14 11:19:41 -------------- ---------- --------------- -------------------- -------
114+
2018/05/14 11:19:41 production cluster-1 service-a database-host-1 70.01
115+
2018/05/14 11:19:41 production cluster-1 service-b database-host-2 99.51
116+
2018/05/14 11:19:41 production cluster-2 service-a database-host-1 70.01
117+
2018/05/14 11:19:41 production cluster-2 service-b database-host-2 99.51
133118
```

example/example.go

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,15 @@ import (
77
"github.com/InVisionApp/tabular"
88
)
99

10-
var tab tabular.Columns
10+
var tab tabular.Table
1111

1212
func init() {
1313
tab = tabular.New()
1414
tab.Col("env", "Environment", 14)
1515
tab.Col("cls", "Cluster", 10)
1616
tab.Col("svc", "Service", 15)
1717
tab.Col("hst", "Database Host", 20)
18-
tab.Col("pct", "%CPU", 7)
19-
tab["pct"].RightJustified = true
18+
tab.ColRJ("pct", "%CPU", 7)
2019
}
2120

2221
var data = []struct {
@@ -54,29 +53,23 @@ var data = []struct {
5453
}
5554

5655
func main() {
57-
// Print Environments and Clusters
56+
// Print a subset of columns (Environments and Clusters)
5857
format := tab.Print("env", "cls")
5958
for _, x := range data {
6059
fmt.Printf(format, x.e, x.c)
6160
}
6261

63-
// Print Environments, Clusters and Services
64-
format = tab.Print("env", "cls", "svc")
62+
// Print All Columns
63+
format = tab.Print("*")
6564
for _, x := range data {
66-
fmt.Printf(format, x.e, x.c, x.s)
65+
fmt.Printf(format, x.e, x.c, x.s, x.d, x.v)
6766
}
6867

69-
// Print Clusters, Services and Database Hosts
70-
format = tab.Print("cls", "svc", "hst", "pct")
71-
for _, x := range data {
72-
fmt.Printf(format, x.c, x.s, x.d, x.v)
73-
}
74-
75-
// Print to a custom destination such as a log
76-
table := tab.Parse("cls", "svc", "hst", "pct")
68+
// Print All Columns to a custom destination such as a log
69+
table := tab.Parse("*")
7770
log.Println(table.Header)
7871
log.Println(table.SubHeader)
7972
for _, x := range data {
80-
log.Printf(table.Format, x.c, x.s, x.d, x.v)
73+
log.Printf(table.Format, x.e, x.c, x.s, x.d, x.v)
8174
}
8275
}

format_test.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,37 +8,41 @@ import (
88

99
func TestFormat(t *testing.T) {
1010
tab := tabular.New()
11-
tab.Col("id", "ID", 6)
11+
tab.ColRJ("id", "ID", 6)
1212
tab.Col("env", "Environment", 14)
1313
tab.Col("cls", "Cluster", 10)
1414
tab.Col("svc", "Service", 25)
1515
tab.Col("hst", "Database Host", 25)
16-
tab.Col("pct", "%CPU", 5)
17-
tab["id"].RightJustified = true
18-
tab["pct"].RightJustified = true
16+
tab.ColRJ("pct", "%CPU", 5)
1917

20-
tWant := tabular.Table{
18+
// Test Partial Printing
19+
want := "%6v %-14v %-10v\n"
20+
if got := tab.Print("id", "env", "cls"); got != want {
21+
t.Errorf("ERROR: tab.Print() failed\n want: %q\n got: %q", want, got)
22+
}
23+
24+
tWant := tabular.Output{
2125
Header: " ID Environment Cluster Service Database Host %CPU",
2226
SubHeader: "------ -------------- ---------- ------------------------- ------------------------- -----",
2327
Format: "%6v %-14v %-10v %-25v %-25v %5v\n",
2428
}
2529

26-
// Test Printing
27-
want := tWant.Format
28-
if got := tab.Print("id", "env", "cls", "svc", "hst", "pct"); got != want {
29-
t.Errorf("ERROR: tab.Print() failed\n want: %q\n got: %q", want, got)
30+
// Test Printing All
31+
want = tWant.Format
32+
if got := tab.Print(tabular.All); got != want {
33+
t.Errorf("ERROR: tab.Print(All) failed\n want: %q\n got: %q", want, got)
3034
}
3135

3236
// Test Parsing
3337
if tGot := tab.Parse("id", "env", "cls", "svc", "hst", "pct"); tGot != tWant {
3438
if tGot.Header != tWant.Header {
35-
t.Errorf("ERROR: tab.Parse() failed\n want: %v\n got: %v", tWant.Header, tGot.Header)
39+
t.Errorf("ERROR: tab.Parse() failed\n want: %q\n got: %q", tWant.Header, tGot.Header)
3640
}
3741
if tGot.SubHeader != tWant.SubHeader {
38-
t.Errorf("ERROR: tab.Parse() failed\n want: %v\n got: %v", tWant.SubHeader, tGot.SubHeader)
42+
t.Errorf("ERROR: tab.Parse() failed\n want: %q\n got: %q", tWant.SubHeader, tGot.SubHeader)
3943
}
4044
if tGot.Format != tWant.Format {
41-
t.Errorf("ERROR: tab.Parse() failed\n want: %v\n got: %v", tWant.Format, tGot.Format)
45+
t.Errorf("ERROR: tab.Parse() failed\n want: %q\n got: %q", tWant.Format, tGot.Format)
4246
}
4347
}
4448
}

tabular.go

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,19 @@ import (
55
"strings"
66
)
77

8-
// Table - parsed table's header, subheader and format specifier
9-
type Table struct {
8+
// Output - parsed table's header, subheader and format specifier
9+
type Output struct {
1010
Header string
1111
SubHeader string
1212
Format string
1313
}
1414

15-
// Columns - maps short names of columns to their structure defining:
16-
// full name, length and whether it's right justified
17-
//
18-
// For Example:
19-
// "env": Column{Name: "Environment", Length: 14},
20-
// "cls": Column{Name: "Cluster", Length: 40},
21-
// "srv": Column{Name: "Service", Length: 35},
22-
// "hst": Column{Name: "Host", Length: 45},
23-
// "pct": Column{Name: "%CPU", Length: 7, RightJustified: true},
24-
type Columns map[string]*Column
15+
// Table - maps and orders short names of columns to their structure defining:
16+
// full name, length and whether it's right justified
17+
type Table struct {
18+
Columns map[string]*Column
19+
order *[]string
20+
}
2521

2622
// Column - defines column's name, length and if it's right justified
2723
type Column struct {
@@ -30,64 +26,88 @@ type Column struct {
3026
RightJustified bool
3127
}
3228

33-
// New - Creates a map of tabular Columns
34-
func New() Columns { return Columns{} }
29+
// All - pass this to Print() or Parse() to print or parse all columns of a table
30+
const All = "*"
31+
32+
// New - Creates a new table
33+
func New() Table {
34+
return Table{
35+
Columns: map[string]*Column{},
36+
order: &[]string{},
37+
}
38+
}
3539

3640
// Print - does the following:
3741
//
38-
// 1) prints a table style heading for a given list of columns.
39-
//
40-
// For example if Columns are defined as:
42+
// 1) prints a table style heading for a given list of columns,
43+
// for example, if Columns are defined as:
4144
//
4245
// "env": Column{Name: "Environment", Length: 14},
4346
// "cls": Column{Name: "Cluster", Length: 40},
4447
// "srv": Column{Name: "Service", Length: 35},
4548
//
46-
// It'll produce:
49+
// It'll produce:
4750
//
4851
// Environment Cluster Service
4952
// -------------- ---------------------------------------- -----------------------------------
5053
//
5154
// 2) Returns an fmt style format specifier string that you can use
52-
// to output values under the above heading via Printf(format,...):
55+
// to output values under the above heading via Printf(format,...):
5356
//
5457
// %-14v %-40v %-35v
55-
func (cl Columns) Print(cols ...string) string {
56-
t := cl.parse(cols...)
58+
func (tbl Table) Print(cols ...string) string {
59+
t := tbl.parse(cols...)
5760
fmt.Println(t.Header)
5861
fmt.Println(t.SubHeader)
5962
return t.Format
6063
}
6164

62-
// Parse - builds a Table out of a given list of columns
65+
// Parse - constructs Table's Output structure containing it's header,
66+
// sub-header and format modifier out of a given list of columns.
6367
//
64-
// To simply print the table's title call Print() instead
68+
// To simply print the table's title call Print() instead.
6569
//
6670
// Parse() is usefull when you need to control where
67-
// to output the title, for example to a log or a trace file
68-
func (cl Columns) Parse(cols ...string) Table {
69-
return cl.parse(cols...)
71+
// to output the title, for example to a log or a trace file.
72+
func (tbl Table) Parse(cols ...string) Output {
73+
return tbl.parse(cols...)
7074
}
7175

72-
// Col - adds a new column to existing tabular Format
73-
func (cl Columns) Col(shortName, fullName string, columnLength int) {
74-
cl[shortName] = &Column{Name: fullName, Length: columnLength}
76+
// Col - adds a new column to an existing table
77+
func (tbl Table) Col(shortName, fullName string, columnLength int) {
78+
tbl.Columns[shortName] = &Column{Name: fullName, Length: columnLength}
79+
tbl.appendColumn(shortName)
7580
}
7681

77-
func (cl Columns) parse(cols ...string) Table {
82+
// ColRJ - adds a new Right Justified column to an existing table
83+
func (tbl Table) ColRJ(shortName, fullName string, columnLength int) {
84+
tbl.Columns[shortName] = &Column{Name: fullName, Length: columnLength, RightJustified: true}
85+
tbl.appendColumn(shortName)
86+
}
87+
88+
func (tbl Table) appendColumn(shortName string) {
89+
*tbl.order = append(*tbl.order, shortName)
90+
}
91+
92+
func (tbl Table) parse(cols ...string) Output {
7893
var header string
7994
var subHeader string
8095
var format string
8196
var space string
97+
98+
if len(cols) == 1 && cols[0] == All {
99+
cols = *tbl.order
100+
}
101+
82102
for _, c := range cols {
83-
cf := cl[c].f()
84-
header = header + space + fmt.Sprintf(cf, cl[c].Name)
85-
subHeader = subHeader + space + fmt.Sprintf(cf, r(cl[c].Length))
103+
cf := tbl.Columns[c].f()
104+
header = header + space + fmt.Sprintf(cf, tbl.Columns[c].Name)
105+
subHeader = subHeader + space + fmt.Sprintf(cf, r(tbl.Columns[c].Length))
86106
format = format + space + cf
87107
space = " "
88108
}
89109

90-
return Table{
110+
return Output{
91111
Header: header,
92112
SubHeader: subHeader,
93113
Format: format + "\n",

0 commit comments

Comments
 (0)