diff --git a/text/gstr/gstr_convert.go b/text/gstr/gstr_convert.go index 7c4a6add3..c358dd14e 100644 --- a/text/gstr/gstr_convert.go +++ b/text/gstr/gstr_convert.go @@ -9,12 +9,18 @@ package gstr import ( "bytes" "fmt" - "github.com/gogf/gf/v2/util/grand" "math" "regexp" "strconv" "strings" "unicode" + + "github.com/gogf/gf/v2/util/grand" +) + +var ( + // octReg is the regular expression object for checks octal string. + octReg = regexp.MustCompile(`\\[0-7]{3}`) ) // Chr return the ascii string of a number(0-255). @@ -27,11 +33,6 @@ func Ord(char string) int { return int(char[0]) } -var ( - // octReg is the regular expression object for checks octal string. - octReg = regexp.MustCompile(`\\[0-7]{3}`) -) - // OctStr converts string container octal string to its original string, // for example, to Chinese string. // Eg: `\346\200\241` -> 怡 @@ -175,7 +176,8 @@ func Nl2Br(str string, isXhtml ...bool) string { } // WordWrap wraps a string to a given number of characters. -// TODO: Enable cut parameter, see http://php.net/manual/en/function.wordwrap.php. +// This function supports cut parameters of both english and chinese punctuations. +// TODO: Enable custom cut parameter, see http://php.net/manual/en/function.wordwrap.php. func WordWrap(str string, width int, br string) string { if br == "" { br = "\n" @@ -185,9 +187,11 @@ func WordWrap(str string, width int, br string) string { wordBuf, spaceBuf bytes.Buffer init = make([]byte, 0, len(str)) buf = bytes.NewBuffer(init) + strRunes = []rune(str) ) - for _, char := range []rune(str) { - if char == '\n' { + for _, char := range strRunes { + switch { + case char == '\n': if wordBuf.Len() == 0 { if current+spaceBuf.Len() > width { current = 0 @@ -205,7 +209,8 @@ func WordWrap(str string, width int, br string) string { } buf.WriteRune(char) current = 0 - } else if unicode.IsSpace(char) { + + case unicode.IsSpace(char): if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { current += spaceBuf.Len() + wordBuf.Len() spaceBuf.WriteTo(buf) @@ -214,7 +219,18 @@ func WordWrap(str string, width int, br string) string { wordBuf.Reset() } spaceBuf.WriteRune(char) - } else { + + case isPunctuation(char): + wordBuf.WriteRune(char) + if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { + current += spaceBuf.Len() + wordBuf.Len() + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + wordBuf.WriteTo(buf) + wordBuf.Reset() + } + + default: wordBuf.WriteRune(char) if current+spaceBuf.Len()+wordBuf.Len() > width && wordBuf.Len() < width { buf.WriteString(br) @@ -234,3 +250,16 @@ func WordWrap(str string, width int, br string) string { } return buf.String() } + +func isPunctuation(char int32) bool { + switch char { + // English Punctuations. + case ';', '.', ',', ':', '~': + return true + // Chinese Punctuations. + case ';', ',', '。', ':', '?', '!', '…', '、': + return true + default: + return false + } +} diff --git a/text/gstr/gstr_z_unit_convert_test.go b/text/gstr/gstr_z_unit_convert_test.go index 370689b90..4d0a7a813 100644 --- a/text/gstr/gstr_z_unit_convert_test.go +++ b/text/gstr/gstr_z_unit_convert_test.go @@ -4,8 +4,6 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -// go test *.go -bench=".*" - package gstr_test import ( @@ -20,3 +18,25 @@ func Test_OctStr(t *testing.T) { t.Assert(gstr.OctStr(`\346\200\241`), "怡") }) } + +func Test_WordWrap(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + t.Assert(gstr.WordWrap("12 34", 2, "
"), "12
34") + t.Assert(gstr.WordWrap("12 34", 2, "\n"), "12\n34") + t.Assert(gstr.WordWrap("我爱 GF", 2, "\n"), "我爱\nGF") + t.Assert(gstr.WordWrap("A very long woooooooooooooooooord. and something", 7, "
"), + "A very
long
woooooooooooooooooord.
and
something") + }) + // Chinese Punctuations. + gtest.C(t, func(t *gtest.T) { + var ( + br = " " + content = " DelRouteKeyIPv6 删除VPC内的服务的Route信息;和DelRouteIPv6接口相比,这个接口可以删除满足条件的多条RS\n" + length = 120 + ) + wrappedContent := gstr.WordWrap(content, length, "\n"+br) + t.Assert(wrappedContent, ` DelRouteKeyIPv6 删除VPC内的服务的Route信息;和DelRouteIPv6接口相比, + 这个接口可以删除满足条件的多条RS +`) + }) +} diff --git a/text/gstr/gstr_z_unit_test.go b/text/gstr/gstr_z_unit_test.go index 71e020ea9..1afc3a546 100644 --- a/text/gstr/gstr_z_unit_test.go +++ b/text/gstr/gstr_z_unit_test.go @@ -213,16 +213,6 @@ func Test_CountChars(t *testing.T) { }) } -func Test_WordWrap(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - t.Assert(gstr.WordWrap("12 34", 2, "
"), "12
34") - t.Assert(gstr.WordWrap("12 34", 2, "\n"), "12\n34") - t.Assert(gstr.WordWrap("我爱 GF", 2, "\n"), "我爱\nGF") - t.Assert(gstr.WordWrap("A very long woooooooooooooooooord. and something", 7, "
"), - "A very
long
woooooooooooooooooord.
and
something") - }) -} - func Test_LenRune(t *testing.T) { gtest.C(t, func(t *gtest.T) { t.Assert(gstr.LenRune("1234"), 4)