// Copyright (c) 2017 Daniel Oaks // 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 }