Skip to content

Instantly share code, notes, and snippets.

@CanTheAlmighty
Last active October 31, 2024 08:05
Show Gist options
  • Save CanTheAlmighty/18b443a09ebe56c3cf78bc4785438cf8 to your computer and use it in GitHub Desktop.
Save CanTheAlmighty/18b443a09ebe56c3cf78bc4785438cf8 to your computer and use it in GitHub Desktop.
Automatic Snake Case and CamelCase for Swift
extension String {
private static let wordLikeRegex = /([A-Z]+[^A-Z\s_]+)|(?:[\s_]|^)+([^A-Z\s_]+)/
/// Creates a copy of the current string by turning into snake case
///
/// ## Example
/// ```swift
/// // Outputs: my_spaced_name24_long_string
/// "My SpacedName24_Long_____String".snakeCased()
/// ```
///
/// - Returns: A `snake_cased` version of the string
func snakeCased() -> String {
return matches(of: String.wordLikeRegex).map({ match in
let (_, worded, spaced) = match.output
return (worded ?? spaced ?? "").lowercased()
}).joined(separator: "_")
}
/// Creates a copy of the current string by turning into camel case
///
/// ## Example
/// ```swift
/// // Outputs: MySpacedName24LongString
/// "My SpacedName24_Long_____String".camelCased(upper: true)
/// ```
///
/// - Parameter upper: Wether or not the first character should be uppercased (`helloWorld` or `HelloWorld`)
///
/// - Returns: A `camelCased` version of the string (or `CamelCased` if `upper` is true)
func camelCased(upper: Bool = false) -> String {
return matches(of: String.wordLikeRegex).map({ (match) in
let (_, worded, spaced) = match.output
let word = worded ?? spaced ?? ""
if (upper == false && match.range.lowerBound == startIndex) {
return word.lowercased()
}
else {
return word.capitalized
}
}).joined(separator: "")
}
}
@CanTheAlmighty
Copy link
Author

CanTheAlmighty commented Sep 25, 2024

I spent a whole goddamn afternoon trying to come up with a Regex that could turn any arbitrary phrase-like text into a whatever casing I needed. The TL;DR of the regex:

It will try to match either:

  • An uppercase character followed by non-uppercase/space/underscores. The match includes the uppercase character
  • A space/underscore character followed by non-uppercase/space/underscores. The match does NOT include the spacings.

So both matches (1, 2) are optional due to having two regex groups with an optional, and thus I use worded ?? spaced ?? "", the last one so swift doesn't complaint, but it should never be the case.

Tests

Test Resultt
"lowercase" "lowercase"
"User Table with spaces" "user_table_with_spaces"
"User table" "user_table"
"UserGenerator_table" "user_generator_table"
"User_table" "user_table"
"SQLISGREAT1234 asdads" "sqlisgreat1234_asdads"
"My SpacedName24_Long_____String" "my_spaced_name24_long_string"
" spaces at the beginning?" "spaces_at_the_beginning?"
"___underscores!? woooo" "underscores!?_woooo"
"_ _ _ _ _ _ _ _ Im just trolling at this point _ _ _ __ _" "im_just_trolling_at_this_point"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment