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  }