ergo/irc/utils/text.go

68 lines
1.8 KiB
Go

// Copyright (c) 2017 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license
package utils
import "bytes"
// WordWrap wraps the given text into a series of lines that don't exceed lineWidth characters.
func WordWrap(text string, lineWidth int) []string {
var lines []string
var cacheLine, cacheWord bytes.Buffer
for _, char := range text {
if char == '\r' {
continue
} else if char == '\n' {
cacheLine.Write(cacheWord.Bytes())
lines = append(lines, cacheLine.String())
cacheWord.Reset()
cacheLine.Reset()
} else if (char == ' ' || char == '-') && cacheLine.Len()+cacheWord.Len()+1 < lineWidth {
// natural word boundary
cacheLine.Write(cacheWord.Bytes())
cacheLine.WriteRune(char)
cacheWord.Reset()
} else if lineWidth <= cacheLine.Len()+cacheWord.Len()+1 {
// time to wrap to next line
if cacheLine.Len() < (lineWidth / 2) {
// this word takes up more than half a line... just split in the middle of the word
cacheLine.Write(cacheWord.Bytes())
cacheLine.WriteRune(char)
cacheWord.Reset()
} else {
cacheWord.WriteRune(char)
}
lines = append(lines, cacheLine.String())
cacheLine.Reset()
} else {
// normal character
cacheWord.WriteRune(char)
}
}
if 0 < cacheWord.Len() {
cacheLine.Write(cacheWord.Bytes())
}
if 0 < cacheLine.Len() {
lines = append(lines, cacheLine.String())
}
return lines
}
// SplitMessage represents a message that's been split for sending.
type SplitMessage struct {
Original string
Wrapped []string // if this is nil, Original didn't need wrapping and can be sent to anyone
}
func MakeSplitMessage(original string, origIs512 bool) (result SplitMessage) {
result.Original = original
if !origIs512 {
result.Wrapped = WordWrap(original, 400)
}
return
}