mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
parent
a0d1c9263e
commit
de228c0e0c
2 changed files with 68 additions and 0 deletions
|
|
@ -332,6 +332,52 @@ func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) }
|
||||||
// ToTitle returns a copy of the byte array s with all Unicode letters mapped to their title case.
|
// ToTitle returns a copy of the byte array s with all Unicode letters mapped to their title case.
|
||||||
func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
|
func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
|
||||||
|
|
||||||
|
// isSeparator reports whether the rune could mark a word boundary.
|
||||||
|
// TODO: update when package unicode captures more of the properties.
|
||||||
|
func isSeparator(rune int) bool {
|
||||||
|
// ASCII alphanumerics and underscore are not separators
|
||||||
|
if rune <= 0x7F {
|
||||||
|
switch {
|
||||||
|
case '0' <= rune && rune <= '9':
|
||||||
|
return false
|
||||||
|
case 'a' <= rune && rune <= 'z':
|
||||||
|
return false
|
||||||
|
case 'A' <= rune && rune <= 'Z':
|
||||||
|
return false
|
||||||
|
case rune == '_':
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Letters and digits are not separators
|
||||||
|
if unicode.IsLetter(rune) || unicode.IsDigit(rune) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Otherwise, all we can do for now is treat spaces as separators.
|
||||||
|
return unicode.IsSpace(rune)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUG(r): The rule Title uses for word boundaries does not handle Unicode punctuation properly.
|
||||||
|
|
||||||
|
// Title returns a copy of s with all Unicode letters that begin words
|
||||||
|
// mapped to their title case.
|
||||||
|
func Title(s []byte) []byte {
|
||||||
|
// Use a closure here to remember state.
|
||||||
|
// Hackish but effective. Depends on Map scanning in order and calling
|
||||||
|
// the closure once per rune.
|
||||||
|
prev := ' '
|
||||||
|
return Map(
|
||||||
|
func(r int) int {
|
||||||
|
if isSeparator(prev) {
|
||||||
|
prev = r
|
||||||
|
return unicode.ToTitle(r)
|
||||||
|
}
|
||||||
|
prev = r
|
||||||
|
return r
|
||||||
|
},
|
||||||
|
s)
|
||||||
|
}
|
||||||
|
|
||||||
// TrimLeftFunc returns a subslice of s by slicing off all leading UTF-8 encoded
|
// TrimLeftFunc returns a subslice of s by slicing off all leading UTF-8 encoded
|
||||||
// Unicode code points c that satisfy f(c).
|
// Unicode code points c that satisfy f(c).
|
||||||
func TrimLeftFunc(s []byte, f func(r int) bool) []byte {
|
func TrimLeftFunc(s []byte, f func(r int) bool) []byte {
|
||||||
|
|
|
||||||
|
|
@ -685,3 +685,25 @@ func TestReplace(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TitleTest struct {
|
||||||
|
in, out string
|
||||||
|
}
|
||||||
|
|
||||||
|
var TitleTests = []TitleTest{
|
||||||
|
TitleTest{"", ""},
|
||||||
|
TitleTest{"a", "A"},
|
||||||
|
TitleTest{" aaa aaa aaa ", " Aaa Aaa Aaa "},
|
||||||
|
TitleTest{" Aaa Aaa Aaa ", " Aaa Aaa Aaa "},
|
||||||
|
TitleTest{"123a456", "123a456"},
|
||||||
|
TitleTest{"double-blind", "Double-Blind"},
|
||||||
|
TitleTest{"ÿøû", "Ÿøû"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTitle(t *testing.T) {
|
||||||
|
for _, tt := range TitleTests {
|
||||||
|
if s := string(Title([]byte(tt.in))); s != tt.out {
|
||||||
|
t.Errorf("Title(%q) = %q, want %q", tt.in, s, tt.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue