podman
1package text2
3import (4"bytes"5"math"6)
7
8var (9nl = []byte{'\n'}10sp = []byte{' '}11)
12
13const defaultPenalty = 1e514
15// Wrap wraps s into a paragraph of lines of length lim, with minimal
16// raggedness.
17func Wrap(s string, lim int) string {18return string(WrapBytes([]byte(s), lim))19}
20
21// WrapBytes wraps b into a paragraph of lines of length lim, with minimal
22// raggedness.
23func WrapBytes(b []byte, lim int) []byte {24words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp)25var lines [][]byte26for _, line := range WrapWords(words, 1, lim, defaultPenalty) {27lines = append(lines, bytes.Join(line, sp))28}29return bytes.Join(lines, nl)30}
31
32// WrapWords is the low-level line-breaking algorithm, useful if you need more
33// control over the details of the text wrapping process. For most uses, either
34// Wrap or WrapBytes will be sufficient and more convenient.
35//
36// WrapWords splits a list of words into lines with minimal "raggedness",
37// treating each byte as one unit, accounting for spc units between adjacent
38// words on each line, and attempting to limit lines to lim units. Raggedness
39// is the total error over all lines, where error is the square of the
40// difference of the length of the line and lim. Too-long lines (which only
41// happen when a single word is longer than lim units) have pen penalty units
42// added to the error.
43func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte {44n := len(words)45
46length := make([][]int, n)47for i := 0; i < n; i++ {48length[i] = make([]int, n)49length[i][i] = len(words[i])50for j := i + 1; j < n; j++ {51length[i][j] = length[i][j-1] + spc + len(words[j])52}53}54
55nbrk := make([]int, n)56cost := make([]int, n)57for i := range cost {58cost[i] = math.MaxInt3259}60for i := n - 1; i >= 0; i-- {61if length[i][n-1] <= lim || i == n-1 {62cost[i] = 063nbrk[i] = n64} else {65for j := i + 1; j < n; j++ {66d := lim - length[i][j-1]67c := d*d + cost[j]68if length[i][j-1] > lim {69c += pen // too-long lines get a worse penalty70}71if c < cost[i] {72cost[i] = c73nbrk[i] = j74}75}76}77}78
79var lines [][][]byte80i := 081for i < n {82lines = append(lines, words[i:nbrk[i]])83i = nbrk[i]84}85return lines86}
87