Skip to content

Commit 5438df9

Browse files
committed
Add initial box content function
Add `BoxContent` function, which creates a very simple string containing a box with a border on the left side as well as a headline and content: Example: ╭ headline │ multi │ line │ content ╵
1 parent 2d1bc1d commit 5438df9

File tree

4 files changed

+257
-7
lines changed

4 files changed

+257
-7
lines changed

box.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright © 2019 The Homeport Team
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package neat
22+
23+
import (
24+
"bufio"
25+
"bytes"
26+
"fmt"
27+
"strings"
28+
29+
"github.com/gonvenience/bunt"
30+
colorful "github.com/lucasb-eyer/go-colorful"
31+
)
32+
33+
// BoxStyle represents a styling option for a content box
34+
type BoxStyle func(*boxOptions)
35+
36+
type boxOptions struct {
37+
headlineColor *colorful.Color
38+
contentColor *colorful.Color
39+
}
40+
41+
// HeadlineColor sets the color of the headline text
42+
func HeadlineColor(color colorful.Color) BoxStyle {
43+
return func(options *boxOptions) {
44+
options.headlineColor = &color
45+
}
46+
}
47+
48+
// ContentColor sets the color of the content text
49+
func ContentColor(color colorful.Color) BoxStyle {
50+
return func(options *boxOptions) {
51+
options.contentColor = &color
52+
}
53+
}
54+
55+
type buntBuffer struct {
56+
buf bytes.Buffer
57+
}
58+
59+
func (b *buntBuffer) Write(format string, a ...interface{}) {
60+
b.buf.WriteString(fmt.Sprintf(format, a...))
61+
}
62+
63+
func (b *buntBuffer) String() string {
64+
return b.buf.String()
65+
}
66+
67+
// ContentBox creates a string for the terminal where content is printed inside
68+
// a simple box shape.
69+
func ContentBox(headline string, content string, opts ...BoxStyle) string {
70+
var (
71+
prefix = "│"
72+
lastline = "╵"
73+
)
74+
75+
options := &boxOptions{}
76+
for _, f := range opts {
77+
f(options)
78+
}
79+
80+
headline = bunt.Sprintf("╭ %s",
81+
bunt.Style(headline, bunt.Bold()),
82+
)
83+
84+
if options.headlineColor != nil {
85+
for _, pointer := range []*string{&headline, &prefix, &lastline} {
86+
*pointer = bunt.Style(
87+
*pointer,
88+
bunt.Foreground(*options.headlineColor),
89+
)
90+
}
91+
}
92+
93+
var buf buntBuffer
94+
buf.Write("%s\n", headline)
95+
96+
scanner := bufio.NewScanner(strings.NewReader(content))
97+
for scanner.Scan() {
98+
text := scanner.Text()
99+
if options.contentColor != nil {
100+
text = bunt.Style(text, bunt.Foreground(*options.contentColor))
101+
}
102+
103+
buf.Write("%s %s\n", prefix, text)
104+
}
105+
106+
buf.Write("%s\n", lastline)
107+
108+
return buf.String()
109+
}

box_test.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// Copyright © 2019 The Homeport Team
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to deal
5+
// in the Software without restriction, including without limitation the rights
6+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
// copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
// THE SOFTWARE.
20+
21+
package neat_test
22+
23+
import (
24+
. "github.com/onsi/ginkgo"
25+
. "github.com/onsi/gomega"
26+
27+
. "github.com/gonvenience/bunt"
28+
. "github.com/gonvenience/neat"
29+
)
30+
31+
var _ = Describe("content box", func() {
32+
BeforeEach(func() {
33+
ColorSetting = ON
34+
TrueColorSetting = ON
35+
})
36+
37+
AfterEach(func() {
38+
ColorSetting = OFF
39+
TrueColorSetting = OFF
40+
})
41+
42+
Context("rendering content boxes", func() {
43+
var (
44+
headline = "headline"
45+
content = `multi
46+
line
47+
content
48+
`
49+
)
50+
51+
It("should create a simply styled content box", func() {
52+
Expect("\n" + ContentBox(headline, content)).To(BeEquivalentTo(Sprintf(`
53+
╭ *headline*
54+
│ multi
55+
│ line
56+
│ content
57+
58+
`)))
59+
})
60+
61+
It("should create styled content box with headline colors", func() {
62+
Expect("\n" + ContentBox(headline, content,
63+
HeadlineColor(DodgerBlue),
64+
)).To(BeEquivalentTo(Sprintf(`
65+
DodgerBlue{╭ *headline*}
66+
DodgerBlue{│} multi
67+
DodgerBlue{│} line
68+
DodgerBlue{│} content
69+
DodgerBlue{╵}
70+
`)))
71+
})
72+
73+
It("should create styled content box with content colors", func() {
74+
Expect("\n" + ContentBox(headline, content,
75+
ContentColor(DimGray),
76+
)).To(BeEquivalentTo(Sprintf(`
77+
╭ *headline*
78+
│ DimGray{multi}
79+
│ DimGray{line}
80+
│ DimGray{content}
81+
82+
`)))
83+
})
84+
85+
It("should create styled content box with headline and content colors", func() {
86+
Expect("\n" + ContentBox(headline, content,
87+
HeadlineColor(DodgerBlue),
88+
ContentColor(DimGray),
89+
)).To(BeEquivalentTo(Sprintf(`
90+
DodgerBlue{╭ *headline*}
91+
DodgerBlue{│} DimGray{multi}
92+
DodgerBlue{│} DimGray{line}
93+
DodgerBlue{│} DimGray{content}
94+
DodgerBlue{╵}
95+
`)))
96+
})
97+
})
98+
99+
Context("rendering content boxes with already colored content", func() {
100+
setupTestStrings := func() (string, string) {
101+
return Sprintf("CornflowerBlue{~headline~}"),
102+
Sprintf(`Red{*multi*}
103+
Green{_line_}
104+
Blue{~content~}
105+
`)
106+
}
107+
108+
It("should preserve already existing colors and text emphasis", func() {
109+
headline, content := setupTestStrings()
110+
Expect("\n" + ContentBox(headline, content)).To(BeEquivalentTo(Sprintf(`
111+
╭ CornflowerBlue{*~headline~*}
112+
│ Red{*multi*}
113+
│ Green{_line_}
114+
│ Blue{~content~}
115+
116+
`)))
117+
})
118+
119+
It("should overwrite existing headline color if it is specified", func() {
120+
headline, content := setupTestStrings()
121+
Expect("\n" + ContentBox(headline, content,
122+
HeadlineColor(DimGray),
123+
)).To(BeEquivalentTo(Sprintf(`
124+
DimGray{╭ *~headline~*}
125+
DimGray{│} Red{*multi*}
126+
DimGray{│} Green{_line_}
127+
DimGray{│} Blue{~content~}
128+
DimGray{╵}
129+
`)))
130+
})
131+
132+
It("should overwrite existing content color if it is specified", func() {
133+
headline, content := setupTestStrings()
134+
Expect("\n" + ContentBox(headline, content,
135+
ContentColor(DimGray),
136+
)).To(BeEquivalentTo(Sprintf(`
137+
╭ CornflowerBlue{*~headline~*}
138+
│ DimGray{*multi*}
139+
│ DimGray{_line_}
140+
│ DimGray{~content~}
141+
142+
`)))
143+
})
144+
})
145+
})

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/gonvenience/neat
33
go 1.12
44

55
require (
6-
github.com/gonvenience/bunt v1.0.5
6+
github.com/gonvenience/bunt v1.0.6
77
github.com/lucasb-eyer/go-colorful v1.0.2
88
github.com/onsi/ginkgo v1.8.0
99
github.com/onsi/gomega v1.5.0

go.sum

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
22
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
33
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
4-
github.com/gonvenience/bunt v1.0.1 h1:105azL3hzdCHh9WtrB1M+Jvs/r1fQAyHutA4vohJAQ8=
5-
github.com/gonvenience/bunt v1.0.1/go.mod h1:lsyhkmNpSAzhVx059BD0fQy5F29rWcS6AHb7UWNlT/s=
6-
github.com/gonvenience/bunt v1.0.2 h1:eiWx8+bO2yIlZXCZ/zNITj+F+CnXrqgXO9SpRKhL+sQ=
7-
github.com/gonvenience/bunt v1.0.2/go.mod h1:lsyhkmNpSAzhVx059BD0fQy5F29rWcS6AHb7UWNlT/s=
8-
github.com/gonvenience/bunt v1.0.5 h1:/iP7ROAPvBfpGab3eaFeyJPEOgdWJVpkkFNj8lfboZA=
9-
github.com/gonvenience/bunt v1.0.5/go.mod h1:lsyhkmNpSAzhVx059BD0fQy5F29rWcS6AHb7UWNlT/s=
4+
github.com/gonvenience/bunt v1.0.6 h1:b3KEkaSlbXx3m4s2Gg5NfKkbo3YR3daCbqeecbDG9IE=
5+
github.com/gonvenience/bunt v1.0.6/go.mod h1:lsyhkmNpSAzhVx059BD0fQy5F29rWcS6AHb7UWNlT/s=
106
github.com/gonvenience/term v1.0.0 h1:joCB/j0Ngmdakd3muuLgAGPMf7DNKdoe708c1I6RiBs=
117
github.com/gonvenience/term v1.0.0/go.mod h1:wohD4Iqso9Eol7qc2VnNhSFFhZxok5PvO7pZhdrAn4E=
128
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=

0 commit comments

Comments
 (0)