-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbox.go
82 lines (66 loc) · 1.82 KB
/
box.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
package box
import (
"fmt"
"strings"
"unicode/utf8"
)
const singleLineFormat = "%[1]s%[2]s%[3]s%[2]s%[4]s%[1]s"
const blockFormat = "%[1]s\n%s\n%[1]s\n"
type Box struct {
HorizontalSeparator string
VerticalSeparator string
SideMargin int
}
func New() *Box {
return &Box{
HorizontalSeparator: "=",
VerticalSeparator: "|",
SideMargin: 2,
}
}
func (b *Box) String(lines ...string) string {
sideMargin := strings.Repeat(" ", b.SideMargin)
longestLine := longestLine(lines)
// create top and bottom bars
bar := strings.Repeat(b.HorizontalSeparator, longestLine+b.SideMargin+4)
// create lines to print
var texts []string
for _, line := range lines {
length := utf8.RuneCountInString(line)
// use later
var space string
var oddSpace string
// if current text is shorter than the longest one
// center the text, so it looks better
if length < longestLine {
// difference between longest and current one
diff := longestLine - length
// the spaces to add on each side
toAdd := diff / 2
space = strings.Repeat(" ", toAdd)
// if the difference between the longest and current one
// is odd, we have to add one additional space before the last vertical separator
if diff%2 != 0 {
oddSpace = " "
}
}
texts = append(texts, fmt.Sprintf(singleLineFormat, b.VerticalSeparator, space+sideMargin, line, oddSpace))
}
return fmt.Sprintf(blockFormat, bar, strings.Join(texts, "\n"))
}
func (b *Box) Print(lines ...string) {
fmt.Print(b.String(lines...))
}
// Println adds a newline before and after the box
func (b *Box) Println(lines ...string) {
fmt.Printf("\n%s\n", b.String(lines...))
}
func longestLine(lines []string) (longest int) {
for _, line := range lines {
length := utf8.RuneCountInString(line)
if length > longest {
longest = length
}
}
return
}