...
1 package flect
2
3 import (
4 "encoding"
5 "strings"
6 "unicode"
7 "unicode/utf8"
8 )
9
10
11 type Ident struct {
12 Original string
13 Parts []string
14 }
15
16
17 func (i Ident) String() string {
18 return i.Original
19 }
20
21
22 func New(s string) Ident {
23 i := Ident{
24 Original: s,
25 Parts: toParts(s),
26 }
27
28 return i
29 }
30
31 func toParts(s string) []string {
32 parts := []string{}
33 s = strings.TrimSpace(s)
34 if len(s) == 0 {
35 return parts
36 }
37 if _, ok := baseAcronyms[strings.ToUpper(s)]; ok {
38 return []string{strings.ToUpper(s)}
39 }
40 var prev rune
41 var x strings.Builder
42 x.Grow(len(s))
43 for _, c := range s {
44
45
46
47
48
49
50
51
52
53
54
55
56 if !utf8.ValidRune(c) {
57 continue
58 }
59
60 if isSpace(c) {
61 parts = xappend(parts, x.String())
62 x.Reset()
63 x.WriteRune(c)
64 prev = c
65 continue
66 }
67
68 if unicode.IsUpper(c) && !unicode.IsUpper(prev) {
69 parts = xappend(parts, x.String())
70 x.Reset()
71 x.WriteRune(c)
72 prev = c
73 continue
74 }
75 if unicode.IsUpper(c) && baseAcronyms[strings.ToUpper(x.String())] {
76 parts = xappend(parts, x.String())
77 x.Reset()
78 x.WriteRune(c)
79 prev = c
80 continue
81 }
82 if unicode.IsLetter(c) || unicode.IsDigit(c) || unicode.IsPunct(c) || c == '`' {
83 prev = c
84 x.WriteRune(c)
85 continue
86 }
87
88 parts = xappend(parts, x.String())
89 x.Reset()
90 prev = c
91 }
92 parts = xappend(parts, x.String())
93
94 return parts
95 }
96
97 var _ encoding.TextUnmarshaler = &Ident{}
98 var _ encoding.TextMarshaler = &Ident{}
99
100
101 func (i *Ident) LastPart() string {
102 if len(i.Parts) == 0 {
103 return ""
104 }
105 return i.Parts[len(i.Parts)-1]
106 }
107
108
109 func (i Ident) ReplaceSuffix(orig, new string) Ident {
110 return New(strings.TrimSuffix(i.Original, orig) + new)
111 }
112
113
114 func (i *Ident) UnmarshalText(data []byte) error {
115 (*i) = New(string(data))
116 return nil
117 }
118
119
120 func (i Ident) MarshalText() ([]byte, error) {
121 return []byte(i.Original), nil
122 }
123
View as plain text