github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/codegen/identifier.go (about)

     1  package codegen
     2  
     3  import (
     4  	"strings"
     5  	"unicode"
     6  	"unicode/utf8"
     7  )
     8  
     9  // https://github.com/golang/lint/blob/master/lint.go#L720
    10  var commonInitialisms = map[string]bool{
    11  	"ACL":   true,
    12  	"API":   true,
    13  	"ASCII": true,
    14  	"CPU":   true,
    15  	"CSS":   true,
    16  	"DNS":   true,
    17  	"EOF":   true,
    18  	"GUID":  true,
    19  	"HTML":  true,
    20  	"HTTP":  true,
    21  	"HTTPS": true,
    22  	"ID":    true,
    23  	"IP":    true,
    24  	"JSON":  true,
    25  	"LHS":   true,
    26  	"QPS":   true,
    27  	"RAM":   true,
    28  	"RHS":   true,
    29  	"RPC":   true,
    30  	"SLA":   true,
    31  	"SMTP":  true,
    32  	"SQL":   true,
    33  	"SSH":   true,
    34  	"TCP":   true,
    35  	"TLS":   true,
    36  	"TTL":   true,
    37  	"UDP":   true,
    38  	"UI":    true,
    39  	"UID":   true,
    40  	"UUID":  true,
    41  	"URI":   true,
    42  	"URL":   true,
    43  	"UTF8":  true,
    44  	"VM":    true,
    45  	"XML":   true,
    46  	"XMPP":  true,
    47  	"XSRF":  true,
    48  	"XSS":   true,
    49  }
    50  
    51  func SplitToWords(s string) (entries []string) {
    52  	if !utf8.ValidString(s) {
    53  		return []string{s}
    54  	}
    55  	entries = []string{}
    56  	var runes [][]rune
    57  	lastClass := 0
    58  	class := 0
    59  
    60  	// split into fields based on class of unicode character
    61  	for _, r := range s {
    62  		switch true {
    63  		case unicode.IsSpace(r):
    64  			class = 1
    65  		case unicode.IsLower(r):
    66  			class = 2
    67  		case unicode.IsUpper(r):
    68  			class = 3
    69  		case unicode.IsDigit(r):
    70  			class = 4
    71  		default:
    72  			class = 5
    73  		}
    74  		if class == lastClass {
    75  			runes[len(runes)-1] = append(runes[len(runes)-1], r)
    76  		} else {
    77  			runes = append(runes, []rune{r})
    78  		}
    79  		lastClass = class
    80  	}
    81  
    82  	// handle upper case -> lower case sequences, e.g.
    83  	// "PDFL", "oader" -> "PDF", "Loader"
    84  	for i := 0; i < len(runes)-1; i++ {
    85  		if unicode.IsUpper(runes[i][0]) && unicode.IsLower(runes[i+1][0]) {
    86  			runes[i+1] = append([]rune{runes[i][len(runes[i])-1]}, runes[i+1]...)
    87  			runes[i] = runes[i][:len(runes[i])-1]
    88  		}
    89  	}
    90  
    91  	// construct []string from results
    92  	//
    93  	for _, s := range runes {
    94  		if len(s) > 0 && (unicode.IsDigit(s[0]) || unicode.IsLetter(s[0])) {
    95  			entries = append(entries, string(s))
    96  		}
    97  	}
    98  
    99  	return
   100  }
   101  
   102  type RewordsReducer func(result string, word string, index int) string
   103  
   104  func Rewords(s string, reducer RewordsReducer) string {
   105  	words := SplitToWords(s)
   106  
   107  	var result = ""
   108  
   109  	for idx, word := range words {
   110  		result = reducer(result, word, idx)
   111  	}
   112  
   113  	return result
   114  }
   115  
   116  func ToUpperFirst(s string) string {
   117  	runes := []rune(s)
   118  	runes[0] = unicode.ToUpper(runes[0])
   119  	return string(runes)
   120  }
   121  
   122  func ToCamelCase(s string) string {
   123  	upperString := strings.ToUpper(s)
   124  	if commonInitialisms[upperString] {
   125  		return upperString
   126  	}
   127  	return ToUpperFirst(strings.ToLower(upperString))
   128  }
   129  
   130  func ToUpperCamelCase(s string) string {
   131  	return Rewords(s, func(result string, word string, idx int) string {
   132  		return result + ToCamelCase(word)
   133  	})
   134  }
   135  
   136  func ToLowerCamelCase(s string) string {
   137  	return Rewords(s, func(result string, word string, idx int) string {
   138  		if idx == 0 {
   139  			return result + strings.ToLower(word)
   140  		}
   141  		return result + ToCamelCase(word)
   142  	})
   143  }
   144  
   145  func ToUpperSnakeCase(s string) string {
   146  	return Rewords(s, func(result string, word string, idx int) string {
   147  		newWord := strings.ToUpper(word)
   148  		if idx == 0 || (len(newWord) == 1 && unicode.IsDigit(rune(newWord[0]))) {
   149  			return result + newWord
   150  		}
   151  		return result + "_" + newWord
   152  	})
   153  }
   154  
   155  func ToLowerSnakeCase(s string) string {
   156  	return strings.ToLower(ToUpperSnakeCase(s))
   157  }
   158  
   159  func ToLowerLinkCase(s string) string {
   160  	return strings.Replace(ToLowerSnakeCase(s), "_", "-", -1)
   161  }