snakeToCamelCase function

String snakeToCamelCase(
  1. String input
)

Converts a snake_case string to lowerCamelCase.

Preserves existing camelCase/PascalCase identifiers unchanged (no underscores means no transformation). Leading and trailing underscores are preserved. Consecutive underscores produce empty segments which are skipped.

Examples:

  • obs_scenes_listobsScenesList
  • getUsergetUser (unchanged)
  • _internal_internal (unchanged — single segment)
  • foo___barfooBar (consecutive underscores collapsed)

Implementation

String snakeToCamelCase(String input) {
  if (input.isEmpty) return input;

  // Preserve leading underscore(s) — common for private Dart members.
  var leadingUnderscores = 0;
  while (leadingUnderscores < input.length &&
      input[leadingUnderscores] == '_') {
    leadingUnderscores++;
  }

  final rest = input.substring(leadingUnderscores);
  if (!rest.contains('_')) {
    // No underscores in the body — already camelCase or PascalCase.
    return input;
  }

  final parts = rest.split('_').where((p) => p.isNotEmpty).toList();
  if (parts.isEmpty) return input; // Only underscores

  final buffer = StringBuffer();
  // Preserve leading underscores
  for (var i = 0; i < leadingUnderscores; i++) {
    buffer.write('_');
  }
  // First segment stays lowercase
  buffer.write(parts.first.toLowerCase());
  // Subsequent segments get capitalized
  for (var i = 1; i < parts.length; i++) {
    final part = parts[i];
    buffer.write(part[0].toUpperCase());
    if (part.length > 1) {
      buffer.write(part.substring(1).toLowerCase());
    }
  }
  return buffer.toString();
}