#!/usr/bin/env swift /// Usage: $0 FOLDER /// Description: /// Merge all Swift files contained in FOLDER into swift code that can be used by the FolderSynchronizer. /// Example: $0 Sources/SourceryRuntime > file.swift /// Options: /// FOLDERS: the paths where the Swift files to merge are, separated with comma "," /// isForDarwinPlatform: if true, the generated code will be compilable on Darwin platforms /// -h: Display this help message import Foundation func printUsage() { guard let scriptPath = CommandLine.arguments.first else { fatalError("Could not find script path in arguments (\(CommandLine.arguments))") } guard let lines = (try? String(contentsOfFile: scriptPath, encoding: .utf8))? .components(separatedBy: .newlines) else { fatalError("Could not read the script at path \(scriptPath)") } let documentationPrefix = "/// " lines .filter { $0.hasPrefix(documentationPrefix) } .map { $0.dropFirst(documentationPrefix.count) } .map { $0.replacingOccurrences(of: "$0", with: scriptPath) } .forEach { print("\($0)") } } extension String { func escapedSwiftTokens() -> String { // return self let replacements = [ "\\(": "\\\\(", "\\\"": "\\\\\"", "\\n": "\\\\n", ] var escapedString = self replacements.forEach { escapedString = escapedString.replacingOccurrences(of: $0, with: $1) } return escapedString } } func package(folders folderPaths: [String], isForDarwinPlatform: Bool) throws { if !isForDarwinPlatform { print("#if !canImport(ObjectiveC)") } else { print("#if canImport(ObjectiveC)") } print("let sourceryRuntimeFiles: [FolderSynchronizer.File] = [") for folderPath in folderPaths { let folderURL = URL(fileURLWithPath: folderPath) guard let enumerator = FileManager.default.enumerator(at: folderURL, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else { print("Unable to retrieve file enumerator") exit(1) } var files = [URL]() for case let fileURL as URL in enumerator { do { let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey]) if fileAttributes.isRegularFile! { files.append(fileURL) } } catch { print(error, fileURL) } } try files .sorted(by: { $0.lastPathComponent < $1.lastPathComponent }) .forEach { sourceFileURL in print(" .init(name: \"\(sourceFileURL.lastPathComponent)\", content:") print("\"\"\"") let content = try String(contentsOf: sourceFileURL, encoding: .utf8) .escapedSwiftTokens() print(content) print("\"\"\"),") } } print("]") print("#endif") } func main() { if CommandLine.arguments.contains("-h") { printUsage() exit(0) } guard CommandLine.arguments.count > 1 else { print("Missing folderPath argument") exit(1) } guard CommandLine.arguments.count > 2 else { print("Missing isForDarwinPlatform argument") exit(1) } let foldersPaths = CommandLine.arguments[1] let isForDarwinPlatform = Bool(CommandLine.arguments[2]) ?? false let folders = foldersPaths.split(separator: ",").map(String.init) do { try package(folders: folders, isForDarwinPlatform: isForDarwinPlatform) } catch { print("Failed with error: \(error)") exit(1) } } main()