...

Source file src/github.com/drone/envsubst/v2/funcs.go

Documentation: github.com/drone/envsubst/v2

     1  package envsubst
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  	"unicode"
     7  	"unicode/utf8"
     8  
     9  	"github.com/drone/envsubst/v2/path"
    10  )
    11  
    12  // defines a parameter substitution function.
    13  type substituteFunc func(string, ...string) string
    14  
    15  // toLen returns the length of string s.
    16  func toLen(s string, args ...string) string {
    17  	return strconv.Itoa(len(s))
    18  }
    19  
    20  // toLower returns a copy of the string s with all characters
    21  // mapped to their lower case.
    22  func toLower(s string, args ...string) string {
    23  	return strings.ToLower(s)
    24  }
    25  
    26  // toUpper returns a copy of the string s with all characters
    27  // mapped to their upper case.
    28  func toUpper(s string, args ...string) string {
    29  	return strings.ToUpper(s)
    30  }
    31  
    32  // toLowerFirst returns a copy of the string s with the first
    33  // character mapped to its lower case.
    34  func toLowerFirst(s string, args ...string) string {
    35  	if s == "" {
    36  		return s
    37  	}
    38  	r, n := utf8.DecodeRuneInString(s)
    39  	return string(unicode.ToLower(r)) + s[n:]
    40  }
    41  
    42  // toUpperFirst returns a copy of the string s with the first
    43  // character mapped to its upper case.
    44  func toUpperFirst(s string, args ...string) string {
    45  	if s == "" {
    46  		return s
    47  	}
    48  	r, n := utf8.DecodeRuneInString(s)
    49  	return string(unicode.ToUpper(r)) + s[n:]
    50  }
    51  
    52  // toDefault returns a copy of the string s if not empty, else
    53  // returns a concatenation of the args without a separator.
    54  func toDefault(s string, args ...string) string {
    55  	if len(s) == 0 && len(args) > 0 {
    56  		// don't use any separator
    57  		s = strings.Join(args, "")
    58  	}
    59  	return s
    60  }
    61  
    62  // toSubstr returns a slice of the string s at the specified
    63  // length and position.
    64  func toSubstr(s string, args ...string) string {
    65  	if len(args) == 0 {
    66  		return s // should never happen
    67  	}
    68  
    69  	pos, err := strconv.Atoi(args[0])
    70  	if err != nil {
    71  		// bash returns the string if the position
    72  		// cannot be parsed.
    73  		return s
    74  	}
    75  
    76  	if pos < 0 {
    77  		// if pos is negative (counts from the end) add it
    78  		// to length to get first character offset
    79  		pos = len(s) + pos
    80  
    81  		// if negative offset exceeds the length of the string
    82  		// start from 0
    83  		if pos < 0 {
    84  			pos = 0
    85  		}
    86  	}
    87  
    88  	if len(args) == 1 {
    89  		if pos < len(s) {
    90  			return s[pos:]
    91  		}
    92  		// if the position exceeds the length of the
    93  		// string an empty string is returned
    94  		return ""
    95  	}
    96  
    97  	length, err := strconv.Atoi(args[1])
    98  	if err != nil {
    99  		// bash returns the string if the length
   100  		// cannot be parsed.
   101  		return s
   102  	}
   103  
   104  	if pos+length >= len(s) {
   105  		if pos < len(s) {
   106  			// if the position exceeds the length of the
   107  			// string just return the rest of it like bash
   108  			return s[pos:]
   109  		}
   110  		// if the position exceeds the length of the
   111  		// string an empty string is returned
   112  		return ""
   113  	}
   114  
   115  	return s[pos : pos+length]
   116  }
   117  
   118  // replaceAll returns a copy of the string s with all instances
   119  // of the substring replaced with the replacement string.
   120  func replaceAll(s string, args ...string) string {
   121  	switch len(args) {
   122  	case 0:
   123  		return s
   124  	case 1:
   125  		return strings.Replace(s, args[0], "", -1)
   126  	default:
   127  		return strings.Replace(s, args[0], args[1], -1)
   128  	}
   129  }
   130  
   131  // replaceFirst returns a copy of the string s with the first
   132  // instance of the substring replaced with the replacement string.
   133  func replaceFirst(s string, args ...string) string {
   134  	switch len(args) {
   135  	case 0:
   136  		return s
   137  	case 1:
   138  		return strings.Replace(s, args[0], "", 1)
   139  	default:
   140  		return strings.Replace(s, args[0], args[1], 1)
   141  	}
   142  }
   143  
   144  // replacePrefix returns a copy of the string s with the matching
   145  // prefix replaced with the replacement string.
   146  func replacePrefix(s string, args ...string) string {
   147  	if len(args) != 2 {
   148  		return s
   149  	}
   150  	if strings.HasPrefix(s, args[0]) {
   151  		return strings.Replace(s, args[0], args[1], 1)
   152  	}
   153  	return s
   154  }
   155  
   156  // replaceSuffix returns a copy of the string s with the matching
   157  // suffix replaced with the replacement string.
   158  func replaceSuffix(s string, args ...string) string {
   159  	if len(args) != 2 {
   160  		return s
   161  	}
   162  	if strings.HasSuffix(s, args[0]) {
   163  		s = strings.TrimSuffix(s, args[0])
   164  		s = s + args[1]
   165  	}
   166  	return s
   167  }
   168  
   169  // TODO
   170  
   171  func trimShortestPrefix(s string, args ...string) string {
   172  	if len(args) != 0 {
   173  		s = trimShortest(s, args[0])
   174  	}
   175  	return s
   176  }
   177  
   178  func trimShortestSuffix(s string, args ...string) string {
   179  	if len(args) != 0 {
   180  		r := reverse(s)
   181  		rarg := reverse(args[0])
   182  		s = reverse(trimShortest(r, rarg))
   183  	}
   184  	return s
   185  }
   186  
   187  func trimLongestPrefix(s string, args ...string) string {
   188  	if len(args) != 0 {
   189  		s = trimLongest(s, args[0])
   190  	}
   191  	return s
   192  }
   193  
   194  func trimLongestSuffix(s string, args ...string) string {
   195  	if len(args) != 0 {
   196  		r := reverse(s)
   197  		rarg := reverse(args[0])
   198  		s = reverse(trimLongest(r, rarg))
   199  	}
   200  	return s
   201  }
   202  
   203  func trimShortest(s, arg string) string {
   204  	var shortestMatch string
   205  	for i := 0; i < len(s); i++ {
   206  		match, err := path.Match(arg, s[0:len(s)-i])
   207  
   208  		if err != nil {
   209  			return s
   210  		}
   211  
   212  		if match {
   213  			shortestMatch = s[0 : len(s)-i]
   214  		}
   215  	}
   216  
   217  	if shortestMatch != "" {
   218  		return strings.TrimPrefix(s, shortestMatch)
   219  	}
   220  
   221  	return s
   222  }
   223  
   224  func trimLongest(s, arg string) string {
   225  	for i := 0; i < len(s); i++ {
   226  		match, err := path.Match(arg, s[0:len(s)-i])
   227  
   228  		if err != nil {
   229  			return s
   230  		}
   231  
   232  		if match {
   233  			return strings.TrimPrefix(s, s[0:len(s)-i])
   234  		}
   235  	}
   236  
   237  	return s
   238  }
   239  
   240  func reverse(s string) string {
   241  	r := []rune(s)
   242  	for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
   243  		r[i], r[j] = r[j], r[i]
   244  	}
   245  	return string(r)
   246  }
   247  

View as plain text