Skip to content

Commit ad0bfc2

Browse files
authored
Merge pull request #6 from bbrks/add-shorthand-wrap
Add shorthand wrap func
2 parents d180093 + 5b42b82 commit ad0bfc2

File tree

4 files changed

+354
-327
lines changed

4 files changed

+354
-327
lines changed

wrap.go

Lines changed: 3 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,6 @@
11
package wrap
22

3-
import "strings"
4-
5-
const (
6-
defaultBreakpoints = " -"
7-
defaultNewline = "\n"
8-
)
9-
10-
// Wrapper contains settings for customisable word-wrapping.
11-
type Wrapper struct {
12-
// Breakpoints defines which characters should be able to break a line.
13-
// By default, this follows the usual English rules of spaces, and hyphens.
14-
// Default: " -"
15-
Breakpoints string
16-
17-
// Newline defines which characters should be used to split and create new lines.
18-
// Default: "\n"
19-
Newline string
20-
21-
// OutputLinePrefix is prepended to any output lines. This can be useful
22-
// for wrapping code-comments and prefixing new lines with "// ".
23-
// Default: ""
24-
OutputLinePrefix string
25-
26-
// OutputLineSuffix is appended to any output lines.
27-
// Default: ""
28-
OutputLineSuffix string
29-
30-
// LimitIncludesPrefixSuffix can be set to false if you don't want prefixes
31-
// and suffixes to be included in the length limits.
32-
// Default: true
33-
LimitIncludesPrefixSuffix bool
34-
35-
// TrimPrefix can be set to remove a prefix on each input line.
36-
// This can be paired up with OutputPrefix to create a block of C-style
37-
// comments (/* * */ ) from a long single-line comment.
38-
// Default: ""
39-
TrimInputPrefix string
40-
41-
// TrimSuffix can be set to remove a suffix on each input line.
42-
// Default: ""
43-
TrimInputSuffix string
44-
}
45-
46-
// NewWrapper returns a new instance of a Wrapper initialised with defaults.
47-
func NewWrapper() Wrapper {
48-
return Wrapper{
49-
Breakpoints: defaultBreakpoints,
50-
Newline: defaultNewline,
51-
LimitIncludesPrefixSuffix: true,
52-
}
53-
}
54-
55-
// line will wrap a single line of text at the given length.
56-
// If limit is less than 1, the string remains unwrapped.
57-
func (w Wrapper) line(s string, limit int) string {
58-
if limit < 1 || len(s) < limit {
59-
return w.OutputLinePrefix + s + w.OutputLineSuffix
60-
}
61-
62-
// Find the index of the last breakpoint within the limit.
63-
i := strings.LastIndexAny(s[:limit], w.Breakpoints)
64-
65-
// Can't wrap within the limit, wrap at the next breakpoint instead.
66-
if i < 0 {
67-
i = strings.IndexAny(s, w.Breakpoints)
68-
// Nothing left to do!
69-
if i < 0 {
70-
return w.OutputLinePrefix + s + w.OutputLineSuffix
71-
}
72-
}
73-
74-
// Recurse until we have nothing left to do.
75-
return w.OutputLinePrefix + s[:i] + w.OutputLineSuffix + w.Newline + w.line(s[i+1:], limit)
76-
}
77-
78-
// Wrap will wrap one or more lines of text at the given length.
79-
// If limit is less than 1, the string remains unwrapped.
80-
func (w Wrapper) Wrap(s string, limit int) string {
81-
82-
// Subtract the length of the prefix and suffix from the limit
83-
// so we don't break length limits when using them.
84-
if w.LimitIncludesPrefixSuffix {
85-
limit -= len(w.OutputLinePrefix) + len(w.OutputLineSuffix)
86-
}
87-
88-
var ret string
89-
for _, str := range strings.Split(s, w.Newline) {
90-
str = strings.TrimPrefix(str, w.TrimInputPrefix)
91-
str = strings.TrimSuffix(str, w.TrimInputSuffix)
92-
ret += w.line(str, limit) + w.Newline
93-
}
94-
95-
return ret
3+
// Wrap is shorthand for declaring a new default Wrapper calling its Wrap method
4+
func Wrap(s string, limit int) string {
5+
return NewWrapper().Wrap(s, limit)
966
}

wrap_test.go

Lines changed: 2 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -2,79 +2,15 @@ package wrap_test
22

33
import (
44
"fmt"
5-
"strings"
6-
"testing"
75

86
"github.com/bbrks/wrap"
9-
"github.com/stretchr/testify/assert"
107
)
118

12-
var w = wrap.NewWrapper()
13-
14-
// tests contains various line lengths to test our wrap functions.
15-
var tests = []int{-5, 0, 5, 10, 25, 80, 120, 500}
16-
17-
// loremIpsums contains lorem ipsum of various line-lengths and word-lengths.
18-
var loremIpsums = []string{
19-
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vulputate quam nibh, et faucibus enim gravida vel. Integer bibendum lectus et erat semper fermentum quis a risus. Fusce dignissim tempus metus non pretium. Nunc sagittis magna nec purus porttitor mollis. Pellentesque feugiat quam eget laoreet aliquet. Donec gravida congue massa, et sollicitudin turpis lacinia a. Fusce non tortor magna. Cras vel finibus tellus.",
20-
"Quisque facilisis dictum tellus vitae sagittis. Sed gravida nulla vel ultrices ultricies. Praesent vehicula ligula sit amet massa elementum, eget fringilla nunc ultricies. Fusce aliquet nunc ac lectus tempus sagittis. Phasellus molestie commodo leo, sit amet ultrices est. Integer vitae hendrerit neque, in pretium tellus. Nam egestas mauris id nunc sollicitudin ullamcorper. Integer eget accumsan nulla. Phasellus quis eros non leo condimentum fringilla quis sit amet tellus. Donec semper vulputate lacinia. In hac habitasse platea dictumst. Aliquam varius metus fringilla sapien cursus cursus.",
21-
"Curabitur tellus libero, feugiat vel mauris et, consequat auctor ipsum. Praesent sed pharetra dolor, at convallis lectus. Vivamus at ullamcorper sem. Sed euismod vel massa a dignissim. Proin auctor nibh at pretium facilisis. Ut aliquam erat lacus. Integer sit amet magna urna. Maecenas bibendum pretium mauris convallis semper. Nunc arcu tortor, pulvinar quis eros ut, mattis placerat tortor. Sed et lacus magna. Proin ultrices fermentum sem et placerat. Donec eget sapien mi. Maecenas maximus justo sed vulputate pulvinar. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum accumsan, sapien sit amet suscipit dignissim, velit velit maximus elit, a cursus mi odio eu magna. Nunc nec fermentum nisi, non imperdiet purus.",
22-
"Vestibulum convallis magna arcu, sagittis porta mi luctus sit amet. Nunc tellus magna, fermentum et mi vitae, consectetur vestibulum nulla. Fusce ornare, augue vitae tempor pellentesque, orci orci fringilla tortor, porta feugiat justo purus nec sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nulla pellentesque sed odio in aliquam. Fusce sed molestie velit. Curabitur id quam ac felis accumsan vehicula quis in ex.",
23-
"Duis ac ornare erat. Nulla in odio eget ante tristique dignissim a non erat. Sed non nisi vitae arcu dapibus porta vitae dignissim ante. Cras et fringilla turpis. Maecenas arcu nibh, tempus euismod pretium eget, hendrerit vitae arcu. Sed vel dolor quam. Etiam consequat sed dolor ut elementum. Quisque dictum tempor pretium. Sed eu sollicitudin mi, in commodo ante.",
24-
"",
25-
}
26-
27-
func TestWrapper_Wrap(t *testing.T) {
28-
// Test multiple line lengths.
29-
for _, l := range tests {
30-
31-
// Test each input line individually.
32-
for _, s := range loremIpsums {
33-
wrapped := w.Wrap(s, l)
34-
35-
// Assert that each output line is no longer than the limit.
36-
for _, v := range strings.Split(wrapped, w.Newline) {
37-
38-
// Only check lines which contain more than one word.
39-
if !strings.Contains(v, " ") {
40-
continue
41-
}
42-
43-
// If length < 1, the string remains unchaged.
44-
if l < 1 {
45-
assert.Equal(t, s, v)
46-
continue
47-
}
48-
49-
assert.True(t, len(v) <= l,
50-
fmt.Sprintf("Line length greater than %d: %s", l, v))
51-
}
52-
53-
}
54-
55-
}
56-
}
57-
58-
func benchmarkWrap(b *testing.B, limit int) {
59-
b.ReportAllocs()
60-
for i := 0; i < b.N; i++ {
61-
w.Wrap(loremIpsums[0], limit)
62-
}
63-
}
64-
65-
func BenchmarkWrap0(b *testing.B) { benchmarkWrap(b, 0) }
66-
func BenchmarkWrap5(b *testing.B) { benchmarkWrap(b, 5) }
67-
func BenchmarkWrap10(b *testing.B) { benchmarkWrap(b, 10) }
68-
func BenchmarkWrap25(b *testing.B) { benchmarkWrap(b, 25) }
69-
func BenchmarkWrap80(b *testing.B) { benchmarkWrap(b, 80) }
70-
func BenchmarkWrap120(b *testing.B) { benchmarkWrap(b, 120) }
71-
func BenchmarkWrap500(b *testing.B) { benchmarkWrap(b, 500) }
72-
73-
func ExampleWrapper_Wrap() {
9+
func ExampleWrap() {
7410
var loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vulputate quam nibh, et faucibus enim gravida vel. Integer bibendum lectus et erat semper fermentum quis a risus. Fusce dignissim tempus metus non pretium. Nunc sagittis magna nec purus porttitor mollis. Pellentesque feugiat quam eget laoreet aliquet. Donec gravida congue massa, et sollicitudin turpis lacinia a. Fusce non tortor magna. Cras vel finibus tellus."
7511

7612
// Wrap when lines exceed 80 chars.
77-
fmt.Println(w.Wrap(loremIpsum, 80))
13+
fmt.Println(wrap.Wrap(loremIpsum, 80))
7814
// Output:
7915
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vulputate quam
8016
// nibh, et faucibus enim gravida vel. Integer bibendum lectus et erat semper
@@ -83,171 +19,3 @@ func ExampleWrapper_Wrap() {
8319
// aliquet. Donec gravida congue massa, et sollicitudin turpis lacinia a. Fusce
8420
// non tortor magna. Cras vel finibus tellus.
8521
}
86-
87-
func ExampleWrapper_Wrap_paragraphs() {
88-
var loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pulvinar augue vel dui gravida, sed convallis ante aliquam. Morbi euismod felis in justo lobortis, eu egestas quam cursus. Ut ut tellus mattis, porttitor leo ut, porttitor ex. Nulla suscipit molestie ligula, quis porta nulla pellentesque ac. Cras ut vestibulum orci. Phasellus ante nisl, dignissim non nunc eget, dapibus convallis orci. Integer vel euismod mauris. Integer tortor elit, vestibulum eget augue vitae, vehicula commodo sapien. Integer iaculis maximus dui, vitae rutrum magna congue at. Praesent varius quam vitae rhoncus fringilla. Quisque ac ex sit amet enim aliquam rutrum in in tortor. Sed sit amet est finibus, congue purus et, ultrices quam. Aenean felis velit, ullamcorper at sagittis ut, aliquam eu mauris.
89-
90-
Phasellus vel lorem venenatis, condimentum risus quis, ultricies risus. Vivamus porttitor lorem sit amet bibendum congue. Mauris sem enim, rutrum in ipsum eget, porttitor placerat diam. Pellentesque ut pharetra augue. Maecenas in ante eget ex efficitur tincidunt. Cras ut ultrices nisl. Donec tristique tincidunt eros condimentum tempus. Morbi libero urna, pretium id turpis vel, cursus efficitur orci. Mauris ut elit felis. Duis ultrices nisl eget accumsan consectetur. Nullam blandit elit vel vulputate scelerisque. Nulla facilisi. Cras quis maximus odio. Nam orci est, tempor ac arcu eget, tincidunt consectetur risus. Donec quis faucibus velit.
91-
92-
Maecenas rhoncus semper nisi non luctus. Nam accumsan malesuada urna vel vehicula. Nullam quis dui in augue tristique sollicitudin. Praesent vulputate condimentum vestibulum. Morbi tincidunt consectetur velit non accumsan. Praesent sit amet vestibulum purus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nulla rhoncus urna ut aliquet congue. Sed ornare dignissim orci non imperdiet. Maecenas nec magna bibendum, cursus nisi ac, commodo arcu.
93-
94-
Sed auctor id leo at molestie. Donec sed cursus massa. Morbi semper lobortis dui. Sed mattis sem a molestie sodales. Cras consequat sapien semper, pretium nulla a, dignissim massa. Aliquam non ornare lacus. Cras gravida lorem tellus, et consectetur ante sodales ut.
95-
96-
Nunc mi enim, aliquam quis bibendum sed, commodo quis nulla. Aliquam vulputate arcu a volutpat semper. Donec nec mauris eros. Suspendisse velit ante, fermentum a odio non, porta dignissim nunc. Vestibulum condimentum at massa at malesuada. Etiam augue purus, interdum a est pretium, cursus interdum eros. Vestibulum et ligula dignissim, suscipit arcu et, congue sem. Integer posuere mauris id scelerisque sagittis. Proin cursus congue sem, nec pulvinar neque auctor eget. Suspendisse vitae mi ipsum. Nullam sed mauris posuere, accumsan ligula vitae, viverra tellus. Morbi quam turpis, sagittis vitae arcu vel, tempus sagittis neque. Vivamus dolor purus, blandit ac condimentum a, interdum in ipsum.`
97-
98-
fmt.Println(w.Wrap(loremIpsum, 80))
99-
// Output:
100-
// Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pulvinar augue vel
101-
// dui gravida, sed convallis ante aliquam. Morbi euismod felis in justo lobortis,
102-
// eu egestas quam cursus. Ut ut tellus mattis, porttitor leo ut, porttitor ex.
103-
// Nulla suscipit molestie ligula, quis porta nulla pellentesque ac. Cras ut
104-
// vestibulum orci. Phasellus ante nisl, dignissim non nunc eget, dapibus
105-
// convallis orci. Integer vel euismod mauris. Integer tortor elit, vestibulum
106-
// eget augue vitae, vehicula commodo sapien. Integer iaculis maximus dui, vitae
107-
// rutrum magna congue at. Praesent varius quam vitae rhoncus fringilla. Quisque
108-
// ac ex sit amet enim aliquam rutrum in in tortor. Sed sit amet est finibus,
109-
// congue purus et, ultrices quam. Aenean felis velit, ullamcorper at sagittis ut,
110-
// aliquam eu mauris.
111-
//
112-
// Phasellus vel lorem venenatis, condimentum risus quis, ultricies risus. Vivamus
113-
// porttitor lorem sit amet bibendum congue. Mauris sem enim, rutrum in ipsum
114-
// eget, porttitor placerat diam. Pellentesque ut pharetra augue. Maecenas in ante
115-
// eget ex efficitur tincidunt. Cras ut ultrices nisl. Donec tristique tincidunt
116-
// eros condimentum tempus. Morbi libero urna, pretium id turpis vel, cursus
117-
// efficitur orci. Mauris ut elit felis. Duis ultrices nisl eget accumsan
118-
// consectetur. Nullam blandit elit vel vulputate scelerisque. Nulla facilisi.
119-
// Cras quis maximus odio. Nam orci est, tempor ac arcu eget, tincidunt
120-
// consectetur risus. Donec quis faucibus velit.
121-
//
122-
// Maecenas rhoncus semper nisi non luctus. Nam accumsan malesuada urna vel
123-
// vehicula. Nullam quis dui in augue tristique sollicitudin. Praesent vulputate
124-
// condimentum vestibulum. Morbi tincidunt consectetur velit non accumsan.
125-
// Praesent sit amet vestibulum purus. Orci varius natoque penatibus et magnis dis
126-
// parturient montes, nascetur ridiculus mus. Nulla rhoncus urna ut aliquet
127-
// congue. Sed ornare dignissim orci non imperdiet. Maecenas nec magna bibendum,
128-
// cursus nisi ac, commodo arcu.
129-
//
130-
// Sed auctor id leo at molestie. Donec sed cursus massa. Morbi semper lobortis
131-
// dui. Sed mattis sem a molestie sodales. Cras consequat sapien semper, pretium
132-
// nulla a, dignissim massa. Aliquam non ornare lacus. Cras gravida lorem tellus,
133-
// et consectetur ante sodales ut.
134-
//
135-
// Nunc mi enim, aliquam quis bibendum sed, commodo quis nulla. Aliquam vulputate
136-
// arcu a volutpat semper. Donec nec mauris eros. Suspendisse velit ante,
137-
// fermentum a odio non, porta dignissim nunc. Vestibulum condimentum at massa at
138-
// malesuada. Etiam augue purus, interdum a est pretium, cursus interdum eros.
139-
// Vestibulum et ligula dignissim, suscipit arcu et, congue sem. Integer posuere
140-
// mauris id scelerisque sagittis. Proin cursus congue sem, nec pulvinar neque
141-
// auctor eget. Suspendisse vitae mi ipsum. Nullam sed mauris posuere, accumsan
142-
// ligula vitae, viverra tellus. Morbi quam turpis, sagittis vitae arcu vel,
143-
// tempus sagittis neque. Vivamus dolor purus, blandit ac condimentum a, interdum
144-
// in ipsum.
145-
}
146-
147-
func ExampleWrapper_Wrap_short() {
148-
var loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vulputate quam nibh, et faucibus enim gravida vel. Integer bibendum lectus et erat semper fermentum quis a risus. Fusce dignissim tempus metus non pretium. Nunc sagittis magna nec purus porttitor mollis. Pellentesque feugiat quam eget laoreet aliquet. Donec gravida congue massa, et sollicitudin turpis lacinia a. Fusce non tortor magna. Cras vel finibus tellus."
149-
150-
// Wrap on every word.
151-
fmt.Println(w.Wrap(loremIpsum, 1))
152-
// Output:
153-
// Lorem
154-
// ipsum
155-
// dolor
156-
// sit
157-
// amet,
158-
// consectetur
159-
// adipiscing
160-
// elit.
161-
// Sed
162-
// vulputate
163-
// quam
164-
// nibh,
165-
// et
166-
// faucibus
167-
// enim
168-
// gravida
169-
// vel.
170-
// Integer
171-
// bibendum
172-
// lectus
173-
// et
174-
// erat
175-
// semper
176-
// fermentum
177-
// quis
178-
// a
179-
// risus.
180-
// Fusce
181-
// dignissim
182-
// tempus
183-
// metus
184-
// non
185-
// pretium.
186-
// Nunc
187-
// sagittis
188-
// magna
189-
// nec
190-
// purus
191-
// porttitor
192-
// mollis.
193-
// Pellentesque
194-
// feugiat
195-
// quam
196-
// eget
197-
// laoreet
198-
// aliquet.
199-
// Donec
200-
// gravida
201-
// congue
202-
// massa,
203-
// et
204-
// sollicitudin
205-
// turpis
206-
// lacinia
207-
// a.
208-
// Fusce
209-
// non
210-
// tortor
211-
// magna.
212-
// Cras
213-
// vel
214-
// finibus
215-
// tellus.
216-
}
217-
218-
func ExampleWrapper_Wrap_hyphens() {
219-
var loremIpsum = `
220-
In this particular example, I will spam a lot of hyphenated words, which should wrap at some point, and test the multi-breakpoint feature of this package.
221-
222-
The girl was accident-prone, good-looking, quick-thinking, carbon-neutral, bad-tempered, sport-mad, fair-haired, camera-ready, and finally open-mouthed.
223-
`
224-
225-
fmt.Println(w.Wrap(loremIpsum, 80))
226-
// Output:
227-
// In this particular example, I will spam a lot of hyphenated words, which should
228-
// wrap at some point, and test the multi-breakpoint feature of this package.
229-
//
230-
// The girl was accident-prone, good-looking, quick-thinking, carbon-neutral, bad
231-
// tempered, sport-mad, fair-haired, camera-ready, and finally open-mouthed.
232-
}
233-
234-
func ExampleWrapper_Wrap_prefix() {
235-
var loremIpsum = "/* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vulputate quam nibh, et faucibus enim gravida vel. Integer bibendum lectus et erat semper fermentum quis a risus. Fusce dignissim tempus metus non pretium. Nunc sagittis magna nec purus porttitor mollis. Pellentesque feugiat quam eget laoreet aliquet. Donec gravida congue massa, et sollicitudin turpis lacinia a. Fusce non tortor magna. Cras vel finibus tellus. */"
236-
237-
// Trim the single-line block comment symbols from each input line.
238-
w.TrimInputPrefix = "/* "
239-
w.TrimInputSuffix = " */"
240-
241-
// Prefix each new line with a single-line comment symbol.
242-
w.OutputLinePrefix = "// "
243-
244-
// Wrap when lines exceed 80 chars.
245-
fmt.Println(w.Wrap(loremIpsum, 80))
246-
// Output:
247-
// // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vulputate quam
248-
// // nibh, et faucibus enim gravida vel. Integer bibendum lectus et erat semper
249-
// // fermentum quis a risus. Fusce dignissim tempus metus non pretium. Nunc
250-
// // sagittis magna nec purus porttitor mollis. Pellentesque feugiat quam eget
251-
// // laoreet aliquet. Donec gravida congue massa, et sollicitudin turpis lacinia
252-
// // a. Fusce non tortor magna. Cras vel finibus tellus.
253-
}

0 commit comments

Comments
 (0)