github.com/sandwich-go/boost@v1.3.29/xstrings/wrap.go (about) 1 package xstrings 2 3 import ( 4 "bytes" 5 "unicode" 6 ) 7 8 const nbsp = 0xA0 9 10 // Wrap 换行给定字符串 11 func Wrap(s string, lim uint) string { 12 // Initialize a buffer with a slightly larger size to account for breaks 13 init := make([]byte, 0, len(s)) 14 buf := bytes.NewBuffer(init) 15 16 var current uint 17 var wordBuf, spaceBuf bytes.Buffer 18 var wordBufLen, spaceBufLen uint 19 20 for _, char := range s { 21 if char == '\n' { 22 if wordBuf.Len() == 0 { 23 if current+spaceBufLen > lim { 24 current = 0 25 } else { 26 current += spaceBufLen 27 _, _ = spaceBuf.WriteTo(buf) 28 } 29 spaceBuf.Reset() 30 spaceBufLen = 0 31 } else { 32 current += spaceBufLen + wordBufLen 33 _, _ = spaceBuf.WriteTo(buf) 34 spaceBuf.Reset() 35 spaceBufLen = 0 36 _, _ = wordBuf.WriteTo(buf) 37 wordBuf.Reset() 38 wordBufLen = 0 39 } 40 buf.WriteRune(char) 41 current = 0 42 } else if unicode.IsSpace(char) && char != nbsp { 43 if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { 44 current += spaceBufLen + wordBufLen 45 _, _ = spaceBuf.WriteTo(buf) 46 spaceBuf.Reset() 47 spaceBufLen = 0 48 _, _ = wordBuf.WriteTo(buf) 49 wordBuf.Reset() 50 wordBufLen = 0 51 } 52 53 spaceBuf.WriteRune(char) 54 spaceBufLen++ 55 } else { 56 wordBuf.WriteRune(char) 57 wordBufLen++ 58 59 if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim { 60 buf.WriteRune('\n') 61 current = 0 62 spaceBuf.Reset() 63 spaceBufLen = 0 64 } 65 } 66 } 67 68 if wordBuf.Len() == 0 { 69 if current+spaceBufLen <= lim { 70 _, _ = spaceBuf.WriteTo(buf) 71 } 72 } else { 73 _, _ = spaceBuf.WriteTo(buf) 74 _, _ = wordBuf.WriteTo(buf) 75 } 76 77 return buf.String() 78 }