Last active
November 17, 2017 17:51
-
-
Save crmitchelmore/793f4eae09309aa12c31c929d8efaabc to your computer and use it in GitHub Desktop.
Split model structs, enum, classes, extensions from 1 file to 1 per type. Types should be codable or regex will need changing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import PlaygroundSupport | |
let documentsDir = PlaygroundSupport.playgroundSharedDataDirectory | |
let fileManager = FileManager() | |
extension String { | |
subscript (bounds: CountableClosedRange<Int>) -> String { | |
let start = index(startIndex, offsetBy: bounds.lowerBound) | |
let end = index(startIndex, offsetBy: bounds.upperBound) | |
return String(self[start...end]) | |
} | |
subscript (bounds: CountableRange<Int>) -> String { | |
let start = index(startIndex, offsetBy: bounds.lowerBound) | |
let end = index(startIndex, offsetBy: bounds.upperBound) | |
return String(self[start..<end]) | |
} | |
} | |
enum BlockType { | |
static let regex = try! NSRegularExpression(pattern: "(.+?)(?=\n\\})", options: .dotMatchesLineSeparators) | |
case anExtension(String) | |
case aStruct(String) | |
case anEnum(String) | |
case aClass(String) | |
static var regexPairs: [(BlockType, NSRegularExpression)] { | |
return [ | |
(BlockType.aStruct(""), try! NSRegularExpression(pattern: "struct (.+):", options: [])), | |
(BlockType.aClass(""), try! NSRegularExpression(pattern: "class (.+):", options: [])), | |
(BlockType.anExtension(""), try! NSRegularExpression(pattern: "extension (.+?)[: ]", options: [])), | |
(BlockType.anEnum(""), try! NSRegularExpression(pattern: "enum (.+?)[: ]", options: [])) | |
] | |
} | |
var name: String { | |
switch self { | |
case .anExtension(let name): | |
return name | |
case .aStruct(let name): | |
return name | |
case .anEnum(let name): | |
return name | |
case .aClass(let name): | |
return name | |
} | |
} | |
var shouldHaveNewFile: Bool { | |
switch self { | |
case .anExtension(_): | |
return false | |
default: | |
return true | |
} | |
} | |
private func changeName(to name: String) -> BlockType { | |
switch self { | |
case .anExtension(_): | |
return .anExtension(name) | |
case .aStruct(_): | |
return .aStruct(name) | |
case .anEnum(_): | |
return .anEnum(name) | |
case .aClass(_): | |
return .aClass(name) | |
} | |
} | |
init?(block: String) { | |
var selfType: BlockType? | |
for (blockType, regex) in BlockType.regexPairs { | |
if let match = regex.matches(in: block, options: [], range: NSRange(location: 0, length: block.count)).first { | |
let range = match.range(at: 1) | |
selfType = blockType.changeName(to: (block[range.lowerBound..<range.upperBound])) | |
break | |
} | |
} | |
guard let type = selfType else { return nil } | |
self = type | |
} | |
} | |
func processBlock(_ block: String, folder: URL) { | |
if let blockType = BlockType(block: block) { | |
addText(text: makeEverythingPublicIn(block: block), toFileName: "\(blockType.name).swift", createFile: blockType.shouldHaveNewFile, folder: folder) | |
} | |
} | |
func makeEverythingPublicIn(block: String) -> String { | |
let lines = block.components(separatedBy: "\n") | |
let publicTypes = ["struct ", "class ", "enum ", "let ", "var ", "func "] | |
let ignoreKeywords = ["public ", "private ", "if ", "guard ", " try"] | |
let outputLines: [String] = lines.map { line in | |
for type in publicTypes where line.contains(type) { | |
if ignoreKeywords.filter({ keyword in line.contains(keyword)}).count == 0 { | |
return line.replacingOccurrences(of: type, with: "public \(type)") | |
} | |
} | |
return line | |
} | |
return outputLines.joined(separator: "\n") | |
} | |
func addText(text: String, toFileName: String, createFile: Bool, folder: URL) { | |
var data: Data? | |
let fileUrl = folder.appendingPathComponent(toFileName) | |
if let existingText = try? String(contentsOf: fileUrl, encoding: .utf8), !createFile { | |
data = Data((existingText + "\n" + text).utf8) | |
} else { | |
data = Data(("import Foundation" + text).utf8) | |
} | |
try? data?.write(to: fileUrl) | |
} | |
do { | |
let fileName = "LoyaltyCheckoutOffer.swift" | |
let fileUrl = documentsDir.appendingPathComponent(fileName) | |
let folder = documentsDir.appendingPathComponent(fileName.replacingOccurrences(of: ".swift", with: "")).appendingPathComponent("Models") | |
try fileManager.createDirectory(at: folder, withIntermediateDirectories: true, attributes: nil) | |
let text = try String(contentsOf: fileUrl, encoding: .utf8) | |
let matches = BlockType.regex.matches(in: text, options: [], range: NSRange(location: 0, length: text.count)) | |
for match in matches { | |
let range = match.range(at: 0) | |
processBlock(text[(range.lowerBound + 2)..<range.upperBound] + "\n}", folder: folder) | |
} | |
} catch { | |
print(error) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment