github.com/fragmenta/query@v1.5.3/textual.go (about) 1 package query 2 3 import ( 4 "bytes" 5 "strings" 6 ) 7 8 // Truncate the given string to length using … as ellipsis. 9 func Truncate(s string, length int) string { 10 return TruncateWithEllipsis(s, length, "…") 11 } 12 13 // TruncateWithEllipsis truncates the given string to length using provided ellipsis. 14 func TruncateWithEllipsis(s string, length int, ellipsis string) string { 15 16 l := len(s) 17 el := len(ellipsis) 18 if l+el > length { 19 s = string(s[0:length-el]) + ellipsis 20 } 21 return s 22 } 23 24 // ToPlural returns the plural version of an English word 25 // using some simple rules and a table of exceptions. 26 func ToPlural(text string) (plural string) { 27 28 // We only deal with lowercase 29 word := strings.ToLower(text) 30 31 // Check translations first, and return a direct translation if there is one 32 if translations[word] != "" { 33 return translations[word] 34 } 35 36 // If we have no translation, just follow some basic rules - avoid new rules if possible 37 if strings.HasSuffix(word, "s") || strings.HasSuffix(word, "z") || strings.HasSuffix(word, "h") { 38 plural = word + "es" 39 } else if strings.HasSuffix(word, "y") { 40 plural = strings.TrimRight(word, "y") + "ies" 41 } else if strings.HasSuffix(word, "um") { 42 plural = strings.TrimRight(word, "um") + "a" 43 } else { 44 plural = word + "s" 45 } 46 47 return plural 48 } 49 50 // common transformations from singular to plural 51 // Which irregulars are important or correct depends on your usage of English 52 // Some of those below are now considered old-fashioned and many more could be added 53 // As this is used for database models, it only needs a limited subset of all irregulars 54 // NB you should not attempt to reverse and singularize, but just use the singular provided 55 var translations = map[string]string{ 56 "hero": "heroes", 57 "supernova": "supernovae", 58 "day": "days", 59 "monkey": "monkeys", 60 "money": "monies", 61 "chassis": "chassis", 62 "sheep": "sheep", 63 "aircraft": "aircraft", 64 "fish": "fish", 65 "nucleus": "nuclei", 66 "mouse": "mice", 67 "buffalo": "buffalo", 68 "species": "species", 69 "information": "information", 70 "wife": "wives", 71 "shelf": "shelves", 72 "index": "indices", 73 "matrix": "matrices", 74 "formula": "formulae", 75 "millennium": "millennia", 76 "ganglion": "ganglia", 77 "octopus": "octopodes", 78 "man": "men", 79 "woman": "women", 80 "person": "people", 81 "axis": "axes", 82 "die": "dice", 83 // ..etc 84 } 85 86 // ToSingular converts a word to singular. 87 // NB reversal from plurals may fail 88 func ToSingular(word string) (singular string) { 89 90 if strings.HasSuffix(word, "ses") || strings.HasSuffix(word, "zes") || strings.HasSuffix(word, "hes") { 91 singular = strings.TrimRight(word, "es") 92 } else if strings.HasSuffix(word, "ies") { 93 singular = strings.TrimRight(word, "ies") + "y" 94 } else if strings.HasSuffix(word, "a") { 95 singular = strings.TrimRight(word, "a") + "um" 96 } else { 97 singular = strings.TrimRight(word, "s") 98 } 99 100 return singular 101 } 102 103 // ToSnake converts a string from struct field names to corresponding database column names (e.g. FieldName to field_name). 104 func ToSnake(text string) string { 105 b := bytes.NewBufferString("") 106 for i, c := range text { 107 if i > 0 && c >= 'A' && c <= 'Z' { 108 b.WriteRune('_') 109 } 110 b.WriteRune(c) 111 } 112 return strings.ToLower(b.String()) 113 } 114 115 // ToCamel converts a string from database column names to corresponding struct field names (e.g. field_name to FieldName). 116 func ToCamel(text string, private ...bool) string { 117 lowerCamel := false 118 if private != nil { 119 lowerCamel = private[0] 120 } 121 b := bytes.NewBufferString("") 122 s := strings.Split(text, "_") 123 for i, v := range s { 124 if len(v) > 0 { 125 s := v[:1] 126 if i > 0 || lowerCamel == false { 127 s = strings.ToUpper(s) 128 } 129 b.WriteString(s) 130 b.WriteString(v[1:]) 131 } 132 } 133 return b.String() 134 }