@@ -236,6 +236,20 @@ var (
236
236
titleCaseCache = map [string ]string {}
237
237
)
238
238
239
+ // TrimLeftDigits is for sanitizing the final output of an golang identifier:
240
+ // trimming digits at the start.
241
+ //
242
+ // This func should be applied after everything else to create the final output,
243
+ // or for the leftmost building block of an identifier.
244
+ func TrimLeftDigits (n string ) string {
245
+ for i , r := range n {
246
+ if ! unicode .IsDigit (r ) {
247
+ return n [i :]
248
+ }
249
+ }
250
+ return ""
251
+ }
252
+
239
253
// sanitizeForIdentifier expects a string to be used to generate an identifier.
240
254
// Accordingly, this func replaces any characters that would create an invalid identifier with '_'.
241
255
func sanitizeForIdentifier (n string ) string {
@@ -249,17 +263,31 @@ func sanitizeForIdentifier(n string) string {
249
263
}
250
264
cleanN += char
251
265
}
252
- return cleanN
266
+ return strings .TrimLeft (cleanN , "_" ) // Discard all leading '_'.
267
+ }
268
+
269
+ // TitleCaseFull is like TitleCase, but trims digits on the leftmost of the string.
270
+ //
271
+ // This func should only be used on full identifier names, not identifier name building blocks.
272
+ func TitleCaseFull (n string ) string {
273
+ return titleCase (n , true )
253
274
}
254
275
255
276
// TitleCase changes a snake-case variable name
256
277
// into a go styled object variable name of "ColumnName".
257
278
// titleCase also fully uppercases "ID" components of names, for example
258
279
// "column_name_id" to "ColumnNameID".
259
280
//
281
+ // Use this func for e.g. building blocks of an identifier name.
282
+ // If you are working with a complete name, use TitleCaseFull() instead.
283
+ //
260
284
// Note: This method is ugly because it has been highly optimized,
261
285
// we found that it was a fairly large bottleneck when we were using regexp.
262
286
func TitleCase (n string ) string {
287
+ return titleCase (n , false )
288
+ }
289
+
290
+ func titleCase (n string , trimLeftDigits bool ) string {
263
291
// Attempt to fetch from cache
264
292
mut .RLock ()
265
293
val , ok := titleCaseCache [n ]
@@ -269,6 +297,9 @@ func TitleCase(n string) string {
269
297
}
270
298
271
299
cleanN := sanitizeForIdentifier (n )
300
+ if trimLeftDigits {
301
+ cleanN = TrimLeftDigits (cleanN )
302
+ }
272
303
273
304
// If the string is made up of only uppercase letters and underscores,
274
305
// then return as is and do not strip the underscores
@@ -305,6 +336,12 @@ func TitleCase(n string) string {
305
336
}
306
337
307
338
word := name [start :end ]
339
+
340
+ if trimLeftDigits {
341
+ word = []byte (TrimLeftDigits (string (word )))
342
+ trimLeftDigits = false
343
+ }
344
+
308
345
wordLen := len (word )
309
346
var vowels bool
310
347
@@ -365,17 +402,34 @@ func Ignore(table, column string, ignoreList map[string]struct{}) bool {
365
402
return false
366
403
}
367
404
405
+ // CamelCaseFull is like CamelCase, but trims digits on the leftmost of the string.
406
+ //
407
+ // This func should only be used on full identifier names, not identifier name building blocks.
408
+ func CamelCaseFull (name string ) string {
409
+ return camelCase (name , true )
410
+ }
411
+
368
412
// CamelCase takes a variable name in the format of "var_name" and converts
369
413
// it into a go styled variable name of "varName".
370
414
// camelCase also fully uppercases "ID" components of names, for example
371
415
// "var_name_id" to "varNameID". It will also lowercase the first letter
372
416
// of the name in the case where it's fed something that starts with uppercase.
417
+ //
418
+ // Use this func for e.g. building blocks of an identifier name.
419
+ // If you are working with a complete name, use CamelCaseFull() instead.
373
420
func CamelCase (name string ) string {
421
+ return camelCase (name , false )
422
+ }
423
+
424
+ func camelCase (name string , trimLeftDigits bool ) string {
374
425
buf := GetBuffer ()
375
426
defer PutBuffer (buf )
376
427
377
428
name = sanitizeForIdentifier (name )
378
- name = strings .TrimLeft (name , "_" ) // Discard all leading '_'.
429
+ if trimLeftDigits {
430
+ name = TrimLeftDigits (name )
431
+ name = strings .TrimLeft (name , "_" ) // Discard all leading '_' (again).
432
+ }
379
433
if name == "" {
380
434
return ""
381
435
}
0 commit comments