This repository has been archived on 2021-03-25. You can view files and clone it, but cannot push or open issues/pull-requests.
tui/stringutil.go

135 lines
2.0 KiB
Go

package tui
import (
"strings"
"unicode"
)
// Split text into words or newlines.
func splitText(s string) [][]rune {
s = strings.TrimSpace(s)
r := []rune(s)
out := [][]rune{}
nextWord := func() []rune {
for i := range r {
if unicode.IsSpace(r[i]) {
ret := r[:i]
r = r[i:]
return ret
}
}
ret := r
r = r[:0]
return ret
}
nextSpaces := func() []rune {
for i := range r {
if !unicode.IsSpace(r[i]) {
ret := r[:i]
r = r[i:]
return ret
}
}
// Code should never reach these lines.
ret := r
r = r[:0]
return ret
}
for len(r) > 0 {
word := nextWord()
if len(word) != 0 {
out = append(out, word)
}
if len(r) == 0 {
break
}
spaces := nextSpaces()
count := 0
for _, x := range spaces {
if x == '\n' {
count++
}
if count > 1 {
break
}
}
if count > 1 {
out = append(out, []rune{'\n'})
}
}
return out
}
func normalizeText(s string) string {
out := make([]rune, 0, len(s))
parts := splitText(s)
prevWasWord := false
for _, p := range parts {
if p[0] == '\n' {
out = append(out, '\n', '\n')
prevWasWord = false
} else {
if prevWasWord {
out = append(out, ' ')
}
out = append(out, p...)
prevWasWord = true
}
}
return string(out)
}
func wrapText(s string, w int) ([]string, int) {
maxLine := 0
parts := splitText(s)
nextLine := func() (string, int) {
if parts[0][0] == '\n' {
parts = parts[1:]
return "", 0
}
words := append([]string{}, string(parts[0]))
length := len(parts[0])
parts = parts[1:]
for len(parts) > 0 {
p := parts[0]
if p[0] == '\n' {
break
}
if length+len(p)+1 > w {
break
}
length += len(p) + 1
words = append(words, string(p))
parts = parts[1:]
}
return strings.Join(words, " "), length
}
lines := make([]string, 0, 2)
for len(parts) > 0 {
line, lineLen := nextLine()
if lineLen > maxLine {
maxLine = lineLen
}
lines = append(lines, line)
}
return lines, maxLine
}