github.com/viant/toolbox@v0.34.5/format/case.go (about)

     1  package format
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"unicode"
     7  )
     8  
     9  type Case int
    10  
    11  const (
    12  	//CaseUpper represents case format
    13  	CaseUpper = Case(iota)
    14  	CaseLower
    15  	CaseUpperCamel
    16  	CaseLowerCamel
    17  	CaseUpperUnderscore
    18  	CaseLowerUnderscore
    19  )
    20  
    21  //NewCase create a new case for supplied name or error, supported in case insensitive form "upperCase", "upper", "u"
    22  func NewCase(name string) (Case, error) {
    23  	switch strings.ToLower(name) {
    24  	case "upper", "u":
    25  		return CaseUpper, nil
    26  	case "lower", "l":
    27  		return CaseLower, nil
    28  	case "lowercamel", "lc":
    29  		return CaseLowerCamel, nil
    30  	case "uppercamel", "uc":
    31  		return CaseUpperCamel, nil
    32  	case "lowerunderscore", "lu":
    33  		return CaseLowerUnderscore, nil
    34  	case "upperunderscore", "uu":
    35  		return CaseUpperUnderscore, nil
    36  	}
    37  	return -1, fmt.Errorf("unsupported case format: %s", name)
    38  }
    39  
    40  //String return case format name
    41  func (from Case) String() string {
    42  	switch from {
    43  	case CaseUpper:
    44  		return "Upper"
    45  	case CaseLower:
    46  		return "Lower"
    47  	case CaseUpperCamel:
    48  		return "UpperCamel"
    49  	case CaseLowerCamel:
    50  		return "UpperCamel"
    51  	case CaseUpperUnderscore:
    52  		return "UpperUnderscore"
    53  	case CaseLowerUnderscore:
    54  		return "LowerUnderscore"
    55  	}
    56  	return "UnsupportedCase"
    57  }
    58  
    59  
    60  //Format converts supplied text from Case to
    61  func (from Case) Format(text string, to Case) string {
    62  	toUpper := false
    63  	toLower := false
    64  	toCamel := false
    65  	toUnserscore := false
    66  	fromCamel := false
    67  	fromUnserscore := false
    68  
    69  	switch to {
    70  	case CaseUpper, CaseUpperUnderscore:
    71  		toUpper = true
    72  	case CaseLower, CaseLowerUnderscore:
    73  		toLower = true
    74  	case CaseUpperCamel, CaseLowerCamel:
    75  		toCamel = true
    76  	}
    77  	switch to {
    78  	case CaseUpperUnderscore, CaseLowerUnderscore:
    79  		toUnserscore = true
    80  	}
    81  	switch from {
    82  	case CaseUpperCamel, CaseLowerCamel:
    83  		fromCamel = true
    84  	case CaseUpperUnderscore, CaseLowerUnderscore:
    85  		fromUnserscore = true
    86  	}
    87  	underscore := rune('_')
    88  	var result = make([]rune, 0)
    89  	makeLower := false
    90  	makeUpper := false
    91  	hasUnderscore := false
    92  	for i, r := range text {
    93  		first := i == 0
    94  		if toUpper {
    95  			makeUpper = true
    96  		} else if toLower {
    97  			makeLower = true
    98  		}
    99  		if first {
   100  			if to == CaseLowerCamel {
   101  				r = unicode.ToLower(r)
   102  			} else if to == CaseUpperCamel {
   103  				r = unicode.ToUpper(r)
   104  			}
   105  		} else {
   106  			if fromUnserscore {
   107  				if toCamel {
   108  					if r == underscore {
   109  						hasUnderscore = true
   110  						continue
   111  					}
   112  					if hasUnderscore {
   113  						makeUpper = true
   114  						hasUnderscore = false
   115  					} else {
   116  						makeLower = true
   117  					}
   118  				}
   119  			}
   120  			if unicode.IsUpper(r) && fromCamel {
   121  				if toUnserscore {
   122  					result = append(result, underscore)
   123  				}
   124  			}
   125  		}
   126  
   127  		if makeLower {
   128  			r = unicode.ToLower(r)
   129  		} else if makeUpper {
   130  			r = unicode.ToUpper(r)
   131  		}
   132  		result = append(result, r)
   133  		makeUpper = false
   134  		makeLower = false
   135  	}
   136  
   137  	return string(result)
   138  }