Skip to content

Commit 64f681e

Browse files
committed
Merge branch 'release/1.0.1'
2 parents 3e0fc64 + c89bfcd commit 64f681e

File tree

5 files changed

+55
-80
lines changed

5 files changed

+55
-80
lines changed

Package.swift

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
11
// swift-tools-version:4.0
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

4-
54
import PackageDescription
65

76
let package = Package(
87
name: "StringCase",
98
products: [
10-
// Products define the executables and libraries produced by a package, and make them visible to other packages.
119
.library(
1210
name: "StringCase",
13-
targets: ["StringCase"]),
14-
],
15-
dependencies: [
16-
// Dependencies declare other packages that this package depends on.
11+
targets: ["StringCase"])
1712
],
1813
targets: [
19-
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
20-
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
2114
.target(
2215
name: "StringCase",
2316
dependencies: []),
2417
.testTarget(
2518
name: "StringCaseTests",
26-
dependencies: ["StringCase"]),
19+
dependencies: ["StringCase"])
2720
]
2821
)

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,12 @@ let package = Package(
2121
targets: ["XXX"]),
2222
],
2323
dependencies: [
24-
.package(url: "https://github.com/Digipolitan/string-case-swift.git", .branch("master"))
24+
.package(url: "https://github.com/Digipolitan/string-case-swift.git", from: "1.0.0")
2525
],
2626
targets: [
2727
.target(
2828
name: "XXX",
29-
dependencies: ["StringCase"]),
30-
.testTarget(
31-
name: "XXXTests",
32-
dependencies: ["CommandLineArgs"])
29+
dependencies: ["StringCase"])
3330
]
3431
)
3532
```

Sources/StringCase/StringCase.swift

Lines changed: 49 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,34 @@
77

88
import Foundation
99

10-
public extension String {
11-
12-
public enum CaseFormat {
10+
public enum StringCaseFormat {
1311

14-
public enum SnakeCase {
15-
case lower
16-
case upper
17-
case capitalized
18-
}
12+
public enum SnakeCase {
13+
case lower
14+
case upper
15+
case capitalized
16+
}
1917

20-
public enum CamelCase {
21-
case `default`
22-
case capitalized
23-
}
18+
public enum CamelCase {
19+
case `default`
20+
case capitalized
2421
}
22+
}
2523

26-
public func snakeCased(_ format: CaseFormat.SnakeCase = .lower) -> String {
24+
public extension String {
25+
26+
public func caseSplit() -> [String] {
27+
var res: [String] = []
28+
let trim = self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
2729
let alphanumerics = CharacterSet.alphanumerics
2830
let uppercaseLetters = CharacterSet.uppercaseLetters
2931
let lowercaseLetters = CharacterSet.lowercaseLetters
30-
var underscore = false
31-
var previousCase = 0 // 0 none, 1 upper, 2 lower, 3 other
32-
var currentCase = 0 // 0 none, 1 upper, 2 lower, 3 other
33-
var letterInWord = 0
34-
var res = ""
35-
for ch in self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) {
36-
for scalar in ch.unicodeScalars {
32+
trim.split(separator: " ").forEach { str in
33+
var previousCase = 0
34+
var currentCase = 0
35+
var caseChange = false
36+
var scalars = UnicodeScalarView()
37+
for scalar in str.unicodeScalars {
3738
if alphanumerics.contains(scalar) {
3839
if uppercaseLetters.contains(scalar) {
3940
currentCase = 1
@@ -42,8 +43,7 @@ public extension String {
4243
} else {
4344
currentCase = 0
4445
}
45-
var str = String(scalar)
46-
var caseChange = underscore
46+
let letterInWord = scalars.count
4747
if !caseChange && letterInWord > 0 {
4848
if currentCase != previousCase {
4949
if previousCase == 1 {
@@ -56,57 +56,42 @@ public extension String {
5656
}
5757
}
5858
if caseChange {
59-
res += "_"
60-
letterInWord = 0
61-
}
62-
letterInWord += 1
63-
if format == .capitalized {
64-
if currentCase != 1 {
65-
if caseChange || previousCase == 0 {
66-
str = str.uppercased()
67-
}
68-
} else if !caseChange {
69-
str = str.lowercased()
70-
}
71-
} else if format == .upper && currentCase != 1{
72-
str = str.uppercased()
73-
} else if format == .lower && currentCase != 2 {
74-
str = str.lowercased()
59+
res.append(String(scalars))
60+
scalars.removeAll()
7561
}
76-
res += str
77-
underscore = false;
78-
previousCase = currentCase;
62+
scalars.append(scalar)
63+
caseChange = false
64+
previousCase = currentCase
7965
} else {
80-
underscore = true
66+
caseChange = true
8167
}
8268
}
69+
if scalars.count > 0 {
70+
res.append(String(scalars))
71+
}
8372
}
8473
return res
8574
}
8675

87-
public func camelCased(_ format: CaseFormat.CamelCase = .default) -> String {
88-
var uppercase = format == .capitalized;
89-
var res = ""
90-
let alphanumerics = CharacterSet.alphanumerics
91-
let lowercaseLetters = CharacterSet.lowercaseLetters
92-
for ch in self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) {
93-
for scalar in ch.unicodeScalars {
94-
if alphanumerics.contains(scalar) {
95-
var str = String(scalar)
96-
if uppercase {
97-
if lowercaseLetters.contains(scalar) {
98-
str = str.uppercased()
99-
}
100-
uppercase = false
101-
} else if res.count == 0 {
102-
str = str.lowercased()
103-
}
104-
res += str
105-
} else {
106-
uppercase = true
107-
}
76+
public func snakeCased(_ format: StringCaseFormat.SnakeCase = .lower) -> String {
77+
let split = self.caseSplit()
78+
if format == .lower {
79+
return split.map { $0.lowercased() }.joined(separator: "_")
80+
} else if format == .upper {
81+
return split.map { $0.uppercased() }.joined(separator: "_")
82+
}
83+
return split.map { $0.capitalized }.joined(separator: "_")
84+
}
85+
86+
public func camelCased(_ format: StringCaseFormat.CamelCase = .default) -> String {
87+
var res: [String] = []
88+
for (i, str) in self.caseSplit().enumerated() {
89+
if i == 0 && format == .default {
90+
res.append(str.lowercased())
91+
continue
10892
}
93+
res.append(str.capitalized)
10994
}
110-
return res
95+
return res.joined()
11196
}
11297
}

Tests/LinuxMain.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import XCTest
22
@testable import StringCaseTests
33

44
XCTMain([
5-
testCase(StringCaseTests.allTests),
5+
testCase(StringCaseTests.allTests)
66
])

Tests/StringCaseTests/StringCamelCaseTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class StringCamelCaseTests: XCTestCase {
1515
}
1616

1717
func testCapitalizeCamelCase() {
18-
XCTAssertEqual("i love swift".camelCased(.capitalized), "ILoveSwift")
18+
XCTAssertEqual("i3 love swift".camelCased(.capitalized), "I3LoveSwift")
1919
}
2020

2121
func testCapitalizeCamelCaseTrim() {

0 commit comments

Comments
 (0)