164 lines
3.7 KiB
Go
164 lines
3.7 KiB
Go
/*
|
|
Copyright © Brian Buller <brian@bullercodeworks.com>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
package helpers
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
type Align int
|
|
|
|
const (
|
|
AlignLeft = iota
|
|
AlignCenter
|
|
AlignRight
|
|
)
|
|
|
|
func Center(txt string, width int) string {
|
|
if len(txt) >= width {
|
|
// Trim from beg & end until width
|
|
for len(txt) > width {
|
|
txt = txt[:len(txt)-1]
|
|
if len(txt) > width {
|
|
txt = txt[1:]
|
|
}
|
|
}
|
|
return txt
|
|
}
|
|
for len(txt) < width {
|
|
txt = fmt.Sprintf(" %s", txt)
|
|
if len(txt) < width {
|
|
txt = fmt.Sprintf("%s ", txt)
|
|
}
|
|
}
|
|
return txt
|
|
}
|
|
|
|
func CenterBetween(txt, left, right string, width int) string {
|
|
if len(txt) >= width {
|
|
return Center(txt, width)
|
|
}
|
|
for len(txt) < width {
|
|
txt = fmt.Sprintf("%s%s", left, txt)
|
|
if len(txt) < width {
|
|
txt = fmt.Sprintf("%s%s", txt, right)
|
|
}
|
|
}
|
|
return txt
|
|
}
|
|
|
|
func PadR(txt string, width int) string {
|
|
if len(txt) < width {
|
|
txt = fmt.Sprintf("%s%s", txt, strings.Repeat(" ", width-len(txt)))
|
|
}
|
|
return txt
|
|
}
|
|
|
|
func PadL(txt string, width int) string {
|
|
if len(txt) < width {
|
|
txt = fmt.Sprintf("%s%s", strings.Repeat(" ", width-len(txt)), txt)
|
|
}
|
|
return txt
|
|
}
|
|
|
|
// WrapText inserts new lines to make the text
|
|
// wrap at width 'w'
|
|
func WrapText(txt string, w int) string {
|
|
init := make([]byte, 0, len(txt))
|
|
buf := bytes.NewBuffer(init)
|
|
var current uint
|
|
var wordBuf, spaceBuf bytes.Buffer
|
|
var wordBufLen, spaceBufLen uint
|
|
writeBufs := func() {
|
|
current += spaceBufLen + wordBufLen
|
|
spaceBuf.WriteTo(buf)
|
|
spaceBuf.Reset()
|
|
spaceBufLen = 0
|
|
wordBuf.WriteTo(buf)
|
|
wordBuf.Reset()
|
|
wordBufLen = 0
|
|
}
|
|
for _, char := range txt {
|
|
if char == '\n' {
|
|
// _Must_ wrap at newline
|
|
if wordBuf.Len() == 0 {
|
|
if int(current+spaceBufLen) > w {
|
|
current = 0
|
|
} else {
|
|
current += spaceBufLen
|
|
spaceBuf.WriteTo(buf)
|
|
}
|
|
spaceBuf.Reset()
|
|
spaceBufLen = 0
|
|
} else {
|
|
writeBufs()
|
|
}
|
|
buf.WriteRune(char)
|
|
current = 0
|
|
} else if unicode.IsSpace(char) && char != 0xA0 {
|
|
// Can wrap at whitespace
|
|
if spaceBuf.Len() == 0 || wordBuf.Len() > 0 {
|
|
writeBufs()
|
|
}
|
|
spaceBuf.WriteRune(char)
|
|
spaceBufLen++
|
|
} else {
|
|
wordBuf.WriteRune(char)
|
|
wordBufLen++
|
|
if int(current+wordBufLen+spaceBufLen) > w && int(wordBufLen) < w {
|
|
buf.WriteRune('\n')
|
|
current = 0
|
|
spaceBuf.Reset()
|
|
spaceBufLen = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
if wordBuf.Len() == 0 {
|
|
if int(current+spaceBufLen) <= w {
|
|
spaceBuf.WriteTo(buf)
|
|
}
|
|
} else {
|
|
spaceBuf.WriteTo(buf)
|
|
wordBuf.WriteTo(buf)
|
|
}
|
|
return buf.String()
|
|
}
|
|
|
|
func Longest(of []string) int {
|
|
var ret int
|
|
for i := range of {
|
|
tst := len(of[i])
|
|
if tst > ret {
|
|
ret = tst
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func WrapStringToSlice(s string, width int) []string {
|
|
return strings.Split(WrapText(s, width), "\n")
|
|
}
|