github.com/richardwilkes/toolbox@v1.121.0/txt/case.go (about)

     1  // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, version 2.0. If a copy of the MPL was not distributed with
     5  // this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  //
     7  // This Source Code Form is "Incompatible With Secondary Licenses", as
     8  // defined by the Mozilla Public License, version 2.0.
     9  
    10  package txt
    11  
    12  import (
    13  	"unicode"
    14  	"unicode/utf8"
    15  )
    16  
    17  // ToCamelCase converts a string to CamelCase.
    18  func ToCamelCase(in string) string {
    19  	runes := []rune(in)
    20  	out := make([]rune, 0, len(runes))
    21  	up := true
    22  	for i := 0; i < len(runes); i++ {
    23  		r := runes[i]
    24  		if r == '_' {
    25  			up = true
    26  		} else {
    27  			if up {
    28  				r = unicode.ToUpper(r)
    29  				up = false
    30  			}
    31  			out = append(out, r)
    32  		}
    33  	}
    34  	return string(out)
    35  }
    36  
    37  // ToCamelCaseWithExceptions converts a string to CamelCase, but forces certain words to all caps.
    38  func ToCamelCaseWithExceptions(in string, exceptions *AllCaps) string {
    39  	out := ToCamelCase(in)
    40  	pos := 0
    41  	runes := []rune(out)
    42  	rr := RuneReader{}
    43  	for {
    44  		rr.Src = runes[pos:]
    45  		rr.Pos = 0
    46  		matches := exceptions.regex.FindReaderIndex(&rr)
    47  		if len(matches) == 0 {
    48  			break
    49  		}
    50  		for i := matches[0] + 1; i < matches[1]; i++ {
    51  			runes[pos+i] = unicode.ToUpper(runes[pos+i])
    52  		}
    53  		pos += matches[0] + 1
    54  	}
    55  	return string(runes)
    56  }
    57  
    58  // ToSnakeCase converts a string to snake_case.
    59  func ToSnakeCase(in string) string {
    60  	runes := []rune(in)
    61  	out := make([]rune, 0, 1+len(runes))
    62  	for i := 0; i < len(runes); i++ {
    63  		if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < len(runes) && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
    64  			out = append(out, '_')
    65  		}
    66  		out = append(out, unicode.ToLower(runes[i]))
    67  	}
    68  	return string(out)
    69  }
    70  
    71  // FirstToUpper converts the first character to upper case.
    72  func FirstToUpper(in string) string {
    73  	if in == "" {
    74  		return in
    75  	}
    76  	r, size := utf8.DecodeRuneInString(in)
    77  	if r == utf8.RuneError {
    78  		return in
    79  	}
    80  	return string(unicode.ToUpper(r)) + in[size:]
    81  }
    82  
    83  // FirstToLower converts the first character to lower case.
    84  func FirstToLower(in string) string {
    85  	if in == "" {
    86  		return in
    87  	}
    88  	r, size := utf8.DecodeRuneInString(in)
    89  	if r == utf8.RuneError {
    90  		return in
    91  	}
    92  	return string(unicode.ToLower(r)) + in[size:]
    93  }