Browse Source

Add a "pretty" formatter

Thomas Jost 3 years ago
parent
commit
6ff60420f6
Signed by: Thomas Jost <schnouki@schnouki.net> GPG Key ID: 3F3B990246141762
4 changed files with 191 additions and 3 deletions
  1. 183
    0
      format/pretty.go
  2. 1
    1
      format/value.go
  3. 6
    2
      glide.lock
  4. 1
    0
      glide.yaml

+ 183
- 0
format/pretty.go View File

@@ -0,0 +1,183 @@
1
+package format
2
+
3
+import (
4
+	"fmt"
5
+	"strings"
6
+
7
+	"github.com/fatih/color"
8
+	"github.com/mattn/go-tty"
9
+
10
+	"islas/fav"
11
+)
12
+
13
+func init() {
14
+	Register("pretty", &PrettyFormatter{})
15
+}
16
+
17
+const (
18
+	prettyTimeColSpace  = 4
19
+	prettyTableColSpace = 8
20
+)
21
+
22
+var (
23
+	prettyLineNumber = color.New(color.FgHiBlue, color.Bold)
24
+	prettyStopName   = color.New(color.FgHiWhite, color.Bold)
25
+	prettyDirection  = color.New(color.FgBlue, color.Faint)
26
+	prettyTime       = color.New()
27
+	prettyTimeSoon   = color.New(color.Bold)
28
+	prettyTimeRT     = color.New(color.FgGreen)
29
+	prettyTimeSoonRT = color.New(color.FgGreen, color.Bold)
30
+)
31
+
32
+func max(a, b int) int {
33
+	if a > b {
34
+		return a
35
+	}
36
+	return b
37
+}
38
+
39
+func center(s string, l, w int) string {
40
+	lp := (w - l) / 2
41
+	ls := w - l - lp
42
+	return strings.Repeat(" ", lp) + s + strings.Repeat(" ", ls)
43
+}
44
+
45
+// PrettyFormatter is a pretty time table formatter.
46
+type PrettyFormatter struct {
47
+	tables   []prettyTable
48
+	maxWidth int
49
+}
50
+
51
+type prettyLine struct {
52
+	text   string
53
+	length int
54
+}
55
+
56
+type prettyTable struct {
57
+	header        string
58
+	lines         []prettyLine
59
+	headerLength  int
60
+	maxLineLength int
61
+}
62
+
63
+func (t *prettyTable) format(width int) []string {
64
+	res := []string{}
65
+
66
+	// Header
67
+	res = append(res, center(t.header, t.headerLength, width))
68
+
69
+	// 1 or 2 columns? For 2 columns, we the length of longest line + 4 spaces (to have some padding…)
70
+	if t.maxLineLength+prettyTimeColSpace <= width/2 {
71
+		// 2 columns!
72
+		w1 := width / 2
73
+		w2 := width - w1
74
+		block := []string{}
75
+
76
+		for idx := 0; idx <= len(t.lines)/2; idx++ {
77
+			// 1st column
78
+			pl := t.lines[idx]
79
+			block = append(block, center(pl.text, pl.length, w1))
80
+			lb := len(block) - 1
81
+
82
+			// Is there a 2nd column?
83
+			idx2 := idx + len(t.lines)/2 + 1
84
+			if idx2 < len(t.lines) {
85
+				// Yep
86
+				pl2 := t.lines[idx2]
87
+				block[lb] += center(pl2.text, pl2.length, w2)
88
+			} else {
89
+				// Nope: add padding
90
+				block[lb] += strings.Repeat(" ", w2)
91
+			}
92
+		}
93
+
94
+		res = append(res, block...)
95
+	} else {
96
+		// 1 column: much easier!
97
+		for _, pl := range t.lines {
98
+			res = append(res, center(pl.text, pl.length, width))
99
+		}
100
+	}
101
+
102
+	return res
103
+}
104
+
105
+func (f *PrettyFormatter) Add(tt *fav.TimeTable) {
106
+	t := prettyTable{}
107
+
108
+	t.headerLength = len([]rune(fmt.Sprintf("[%s] %s → %s", tt.LineNumber, tt.StopName, tt.Direction)))
109
+	t.header = prettyLineNumber.Sprintf("[%s]", tt.LineNumber)
110
+	t.header += " " + prettyStopName.Sprint(tt.StopName)
111
+	t.header += " → " + prettyDirection.Sprint(tt.Direction)
112
+
113
+	for ptidx, pt := range tt.PassingTimes {
114
+		col := prettyTime
115
+		if pt.Realtime {
116
+			col = prettyTimeRT
117
+		}
118
+		delta := pt.Time.DeltaNow()
119
+		s := ""
120
+		if delta <= 15 || ptidx == 0 {
121
+			col = prettyTimeSoon
122
+			if pt.Realtime {
123
+				col = prettyTimeSoonRT
124
+			}
125
+			s = fmt.Sprintf("%d min", delta)
126
+		} else {
127
+			s = pt.Time.String()
128
+		}
129
+		pl := prettyLine{
130
+			text:   col.Sprint(s),
131
+			length: len([]rune(s)),
132
+		}
133
+		t.maxLineLength = max(t.maxLineLength, pl.length)
134
+		t.lines = append(t.lines, pl)
135
+	}
136
+
137
+	f.tables = append(f.tables, t)
138
+	f.maxWidth = max(f.maxWidth, max(t.headerLength, t.maxLineLength))
139
+}
140
+
141
+func (f *PrettyFormatter) Format() string {
142
+	termWidth := 80
143
+	if t, err := tty.Open(); err != nil {
144
+		panic(err)
145
+	} else if w, _, err := t.Size(); err != nil {
146
+		panic(err)
147
+	} else {
148
+		termWidth = w
149
+	}
150
+
151
+	res := ""
152
+
153
+	// How many tables in a "row"?
154
+	cols := (termWidth + prettyTableColSpace) / (f.maxWidth + prettyTableColSpace)
155
+
156
+	// Row by row…
157
+	for row := 0; row*cols < len(f.tables); row++ {
158
+		lines := []string{}
159
+		for col := 0; col < cols; col++ {
160
+			idx := row*cols + col
161
+			if idx >= len(f.tables) {
162
+				continue
163
+			}
164
+			table := f.tables[idx]
165
+
166
+			for l, text := range table.format(f.maxWidth) {
167
+				if l >= len(lines) {
168
+					lines = append(lines, strings.Repeat(" ", col*(f.maxWidth+prettyTableColSpace)))
169
+				}
170
+				lines[l] += text
171
+				if col < cols-1 {
172
+					lines[l] += strings.Repeat(" ", prettyTableColSpace)
173
+				}
174
+			}
175
+		}
176
+
177
+		for _, line := range lines {
178
+			res += line + "\n"
179
+		}
180
+	}
181
+
182
+	return res
183
+}

+ 1
- 1
format/value.go View File

@@ -1,7 +1,7 @@
1 1
 package format
2 2
 
3 3
 const (
4
-	defaultFormatter = "color"
4
+	defaultFormatter = "pretty"
5 5
 )
6 6
 
7 7
 type FormatterValue struct {

+ 6
- 2
glide.lock View File

@@ -1,5 +1,5 @@
1
-hash: dd525f3fad74afea247ef4b66fbcc8d8461f2d5e097d4801f45c041df02662c4
2
-updated: 2018-06-26T12:39:11.0342272+02:00
1
+hash: 898f9f6675e4e8f73bbd0352291095f89eb1c795805aa84529440abdac0a7b91
2
+updated: 2018-06-26T15:25:59.773720707+02:00
3 3
 imports:
4 4
 - name: github.com/casimir/xdg-go
5 5
   version: 372ccc2180dab73316615641d5617c5ed3e35529
@@ -19,10 +19,14 @@ imports:
19 19
   version: 0dae4fefe7c0e190f7b5a78dac28a1c82cc8d849
20 20
   subpackages:
21 21
   - reflectx
22
+- name: github.com/mattn/go-colorable
23
+  version: efa589957cd060542a26d2dd7832fd6a6c6c3ade
22 24
 - name: github.com/mattn/go-isatty
23 25
   version: 6ca4dbf54d38eea1a992b3c722a76a5d1c4cb25c
24 26
 - name: github.com/mattn/go-sqlite3
25 27
   version: 25ecb14adfc7543176f7d85291ec7dba82c6f7e4
28
+- name: github.com/mattn/go-tty
29
+  version: 931426f7535ac39720c8909d70ece5a41a2502a6
26 30
 - name: github.com/sirupsen/logrus
27 31
   version: c155da19408a8799da419ed3eeb0cb5db0ad5dbc
28 32
 - name: github.com/spf13/cobra

+ 1
- 0
glide.yaml View File

@@ -17,3 +17,4 @@ import:
17 17
   version: ^0.8.0
18 18
 - package: github.com/fatih/color
19 19
   version: ^1.7.0
20
+- package: github.com/mattn/go-tty

Loading…
Cancel
Save