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  }