-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwrap.go
99 lines (85 loc) · 2.08 KB
/
wrap.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package str
import (
"math"
"strings"
)
type WrapBehavior uint
const (
WrapBeforeWord WrapBehavior = iota
WrapAfterWord
WrapLiteral
)
// The user options for the wrap
type WrapOptions struct {
Width uint
LineBreak string
Behavior WrapBehavior
}
var defaultWrapOptions *WrapOptions
func init() {
defaultWrapOptions = &WrapOptions{
Width: 76,
LineBreak: "\n",
Behavior: WrapBeforeWord,
}
}
// SetWrapOptions - set the global wordwrap options
func SetWrapOptions(options *WrapOptions) {
defaultWrapOptions = options
}
// Wrap - Perform word wrap on a string
func Wrap(in string) string {
return WrapWithOptions(in, defaultWrapOptions)
}
// WrapWithOptions - Perform word wrap with user options
func WrapWithOptions(in string, options *WrapOptions) string {
fields := strings.Fields(in)
if options.Behavior == WrapLiteral {
return wrapLiteral(strings.Join(fields, ` `), options.Width, options.LineBreak)
} else if options.Behavior == WrapAfterWord {
return wrapAfterWord(fields, options.Width, options.LineBreak)
}
return wrapBeforeWord(fields, options.Width, options.LineBreak)
}
func wrapLiteral(in string, width uint, lineBreak string) string {
lines := uint(math.Ceil(float64(len(in)) / float64(width)))
var out string
var i uint
for i = 0; i < lines; i++ {
start := i * width
remain := in[start:]
if len(remain) <= int(width) {
out += remain
continue
}
out += in[start:start+width] + lineBreak
}
return out
}
func wrapBeforeWord(words []string, width uint, lineBreak string) string {
var out, line string
for _, word := range words {
_line := line + word
if len(_line) > int(width) {
out += strings.TrimSpace(line) + lineBreak
line = word + " "
continue
}
line += word + " "
}
out += strings.TrimSpace(line)
return out
}
func wrapAfterWord(words []string, width uint, lineBreak string) string {
var out, line string
for _, word := range words {
if len(line)+1 > int(width) {
out += strings.TrimSpace(line) + lineBreak
line = word + " "
continue
}
line += word + " "
}
out += strings.TrimSpace(line)
return out
}