├── .DS_Store
├── promo.png
├── SwiftGenUIMac
├── Assets.xcassets
│ ├── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── SwiftGenUIMac.entitlements
├── Model
│ ├── AppState.swift
│ ├── SwiftGen.swift
│ └── SwiftGen+Types.swift
├── Helper
│ └── Process+Extension.swift
├── View
│ ├── Forms
│ │ ├── ProgressView.swift
│ │ ├── FileSelectView.swift
│ │ ├── MacEditorTextView.swift
│ │ └── FormView.swift
│ └── ContentView.swift
├── Info.plist
├── AppDelegate.swift
└── Base.lproj
│ └── Main.storyboard
├── SwiftGenUIMac.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ ├── xcuserdata
│ │ └── alfianlosari.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── swiftpm
│ │ └── Package.resolved
├── xcuserdata
│ └── alfianlosari.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
└── project.pbxproj
├── README.md
└── LICENSE.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfianlosari/SwftGenSwiftUIMac/HEAD/.DS_Store
--------------------------------------------------------------------------------
/promo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfianlosari/SwftGenSwiftUIMac/HEAD/promo.png
--------------------------------------------------------------------------------
/SwiftGenUIMac/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SwiftGenUIMac/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/SwiftGenUIMac.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/xcuserdata/alfianlosari.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/project.xcworkspace/xcuserdata/alfianlosari.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alfianlosari/SwftGenSwiftUIMac/HEAD/SwiftGenUIMac.xcodeproj/project.xcworkspace/xcuserdata/alfianlosari.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "Splash",
6 | "repositoryURL": "https://github.com/JohnSundell/Splash.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "2d55b33529e1a3a354d5ef9a5437d4abd842a5a3",
10 | "version": "0.11.1"
11 | }
12 | }
13 | ]
14 | },
15 | "version": 1
16 | }
17 |
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/xcuserdata/alfianlosari.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | SwiftGenUIMac.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftGen UI macOS App built with SwiftUI
2 | A macOS app that uses SwiftGen CLI to generate Swift code from various resources such as assets, fonts, strings, json, yaml, colors for type safety runtime. For more information about, visit [SwiftGen Official Github](https://github.com/SwiftGen/SwiftGen)
3 |
4 | 
5 |
6 | ## Requirements
7 | - Install swiftgen cli using `brew install swiftgen`
8 | - macOS Catalina 10.15.3
9 | - Xcode 11.3.1
10 |
11 | ## Running
12 | - Clone or download
13 | - Build and run the project
14 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/Model/AppState.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppappState.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 20/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import Combine
10 |
11 | class AppState: ObservableObject {
12 |
13 | @Published var selectedType: SwiftGenType? = SwiftGenType.allCases[0] {
14 | didSet {
15 | self.isProcessing = false
16 | self.command = nil
17 | }
18 | }
19 |
20 | @Published var isProcessing: Bool = false
21 | @Published var command: SwiftGenCommand? = nil
22 | }
23 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/Helper/Process+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Process+Extension.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 20/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension Process {
12 |
13 | @objc static func execute(_ command: String, arguments: [String]) -> Data? {
14 | let task = Process()
15 | task.launchPath = command
16 | task.arguments = arguments
17 |
18 | let pipe = Pipe()
19 | task.standardOutput = pipe
20 |
21 | do {
22 | try task.run()
23 | let data = pipe.fileHandleForReading.readDataToEndOfFile()
24 | return data
25 | } catch {
26 | print(error.localizedDescription)
27 | return nil
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/View/Forms/ProgressView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressView.swift
3 | // SwiftGenUIMac
4 | //
5 | // Created by Alfian Losari on 21/02/20.
6 | // Copyright © 2020 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ProgressView: NSViewRepresentable {
12 |
13 | func updateNSView(_ nsView: NSProgressIndicator, context: NSViewRepresentableContext) {
14 | nsView.style = .spinning
15 | nsView.startAnimation(self)
16 | }
17 |
18 |
19 | func makeNSView(context: NSViewRepresentableContext) -> NSProgressIndicator {
20 | let indicator = NSProgressIndicator()
21 | return indicator
22 |
23 | }
24 |
25 | }
26 |
27 | struct ProgressView_Previews: PreviewProvider {
28 | static var previews: some View {
29 | ProgressView()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Alfian Losari
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "size" : "16x16",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "size" : "16x16",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "size" : "32x32",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "size" : "32x32",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "size" : "128x128",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "size" : "128x128",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "size" : "256x256",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "size" : "256x256",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "size" : "512x512",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "size" : "512x512",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/SwiftGenUIMac/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | Copyright © 2020 Alfian Losari. All rights reserved.
27 | NSMainStoryboardFile
28 | Main
29 | NSPrincipalClass
30 | NSApplication
31 | NSSupportsAutomaticTermination
32 |
33 | NSSupportsSuddenTermination
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftGenUIMac
4 | //
5 | // Created by Alfian Losari on 21/02/20.
6 | // Copyright © 2020 Alfian Losari. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import SwiftUI
11 |
12 | @NSApplicationMain
13 | class AppDelegate: NSObject, NSApplicationDelegate {
14 |
15 | var window: NSWindow!
16 |
17 | func applicationDidFinishLaunching(_ aNotification: Notification) {
18 | // Create the SwiftUI view that provides the window contents.
19 |
20 | let appState = AppState()
21 | let contentView = ContentView()
22 | .environmentObject(appState)
23 |
24 | window = NSWindow(
25 | contentRect: NSRect(x: 0, y: 0, width: 1200, height: 768),
26 | styleMask: [.titled, .closable, .miniaturizable, .fullSizeContentView],
27 | backing: .buffered, defer: false)
28 | window.titlebarAppearsTransparent = true
29 | window.isRestorable = true
30 | window.center()
31 | window.setFrameAutosaveName("Main Window")
32 | window.contentView = NSHostingView(rootView: contentView)
33 | window.makeKeyAndOrderFront(nil)
34 |
35 | }
36 |
37 | func applicationWillTerminate(_ aNotification: Notification) {
38 |
39 | }
40 |
41 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
42 | true
43 | }
44 |
45 | }
46 |
47 |
48 |
49 | struct AppDelegate_Previews: PreviewProvider {
50 | static var previews: some View {
51 | /*@START_MENU_TOKEN@*/Text("Hello, World!")/*@END_MENU_TOKEN@*/
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/View/Forms/FileSelectView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FileSelectView.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 20/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import Cocoa
11 |
12 | struct FileSelectView: View {
13 |
14 | var documentType = DocumentType.file
15 | var allowedFileTypes: [String]
16 | var selectedURL: (URL) -> ()
17 |
18 | var body: some View {
19 | VStack(alignment: .leading, spacing: 8) {
20 | Text("Input Resource \(documentType.rawValue)")
21 | .font(.headline)
22 | Button(action: {
23 | self.open()
24 | }) {
25 | Text("Select \(documentType.rawValue)")
26 | }
27 |
28 | Text("Supported extension: \(allowedFileTypes.joined(separator: ", "))")
29 | .font(.caption)
30 | }
31 | }
32 |
33 | func open() {
34 | let panel = NSOpenPanel()
35 | panel.allowsMultipleSelection = false
36 | panel.canChooseFiles = self.documentType == .file
37 | panel.canChooseDirectories = self.documentType == .directory
38 | panel.allowedFileTypes = allowedFileTypes
39 | panel.canChooseFiles = true
40 | panel.begin { (result) in
41 | switch result {
42 | case .OK:
43 | guard let url = panel.urls.first else { return }
44 | self.selectedURL(url)
45 |
46 | default:
47 | print("failed to get file location")
48 | }
49 | }
50 | }
51 | }
52 |
53 | enum DocumentType: String {
54 | case file
55 | case directory
56 | }
57 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/View/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 18/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ContentView: View {
12 | var body: some View {
13 |
14 | HStack(alignment: .top, spacing: 0) {
15 | SidebarView()
16 | .frame(width: 200)
17 | Divider()
18 | .edgesIgnoringSafeArea(.top)
19 | MainView()
20 | }
21 | .frame(minWidth: 1200, maxHeight: 768)
22 | }
23 | }
24 |
25 | struct SidebarView: View {
26 |
27 | @EnvironmentObject var appState: AppState
28 | var types = SwiftGenType.allCases.map { $0 }
29 |
30 | var body: some View {
31 | List(selection: self.$appState.selectedType) {
32 | padding(.top, 16)
33 |
34 | ForEach(self.types) { type in
35 | HStack {
36 | Text(type.rawValue)
37 | .font(.headline)
38 | }
39 | .padding(.vertical, 8)
40 | }
41 | }
42 | .listStyle(SidebarListStyle())
43 | }
44 | }
45 |
46 | struct MainView: View {
47 |
48 | @EnvironmentObject var appState: AppState
49 |
50 | var body: some View {
51 | NavigationView {
52 | if appState.selectedType != nil {
53 | appState.selectedType!.contentView
54 | }
55 |
56 | ResultsView()
57 | .frame(minWidth: 700, maxHeight: 768)
58 |
59 | } .navigationViewStyle(DoubleColumnNavigationViewStyle())
60 | }
61 | }
62 |
63 | struct ResultsView: View {
64 |
65 | @EnvironmentObject var appState: AppState
66 |
67 | var body: some View {
68 | Group {
69 | if self.appState.isProcessing {
70 | ProgressView()
71 | } else if self.appState.command != nil {
72 | VStack(alignment: .trailing) {
73 | MacEditorTextView(text: self.appState.command!.generateSwiftCode()!.attributedCode)
74 |
75 | HStack {
76 | Button(action: {
77 | self.appState.command!.generateSwiftCodeAndCopyToClipboard()
78 | }) {
79 | Text("Copy to clipboard")
80 | }
81 |
82 | Button(action: {
83 | self.openSavePanel(command: self.appState.command!)
84 | }) {
85 | Text("Save to file")
86 | }
87 | }
88 | .padding(.bottom, 8)
89 | .padding(.trailing, 16)
90 | }
91 |
92 | } else {
93 | Text("Select the options from the left panel to convert to generate your assets into Swift code")
94 | }
95 | }
96 | }
97 |
98 | func openSavePanel(command: SwiftGenCommand) {
99 | let savePanel = NSSavePanel()
100 | savePanel.canCreateDirectories = true
101 | savePanel.showsTagField = false
102 | savePanel.nameFieldStringValue = "Generated-\(command.type.rawValue).swift"
103 | savePanel.level = NSWindow.Level(rawValue: Int(CGWindowLevelForKey(.modalPanelWindow)))
104 | savePanel.begin { (result) in
105 | if result == .OK {
106 | guard let url = savePanel.url else { return }
107 | DispatchQueue.global(qos: .userInitiated).async {
108 | self.appState.command!.generateSwiftCodeAndSaveToFile(url: url)
109 | }
110 | }
111 | }
112 | }
113 |
114 | }
115 |
116 | struct ContentView_Previews: PreviewProvider {
117 | static var previews: some View {
118 | ContentView()
119 | }
120 | }
121 |
122 | struct SwiftGenResult {
123 | var code: String
124 | var attributedCode: NSAttributedString
125 | }
126 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/Model/SwiftGen.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftGen.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 20/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SwiftUI
11 |
12 | enum SwiftGenType: String, Identifiable, CaseIterable {
13 |
14 | var id: SwiftGenType { self }
15 |
16 | case assets = "Assets"
17 | case strings = "Strings"
18 | case colors = "Colors"
19 | case fonts = "Fonts"
20 | case ib = "Interface Builder"
21 | case json = "JSON"
22 | case yaml = "YAML"
23 |
24 | var supportedDocumentType: DocumentType {
25 | switch self {
26 | case .assets:
27 | return .directory
28 | case .strings:
29 | return .file
30 | case .colors:
31 | return .file
32 | case .fonts:
33 | return .directory
34 | case .ib:
35 | return .file
36 | case .json:
37 | return .file
38 | case .yaml:
39 | return .file
40 | }
41 | }
42 |
43 | var allowedFileTypes: [String] {
44 | switch self {
45 | case .assets:
46 | return ["xcassets"]
47 | case .strings:
48 | return ["strings"]
49 | case .colors:
50 | return ["txt", "json", "xml", "clr"]
51 | case .fonts:
52 | return ["ttf", "otf"]
53 | case .ib:
54 | return ["storyboard"]
55 | case .json:
56 | return ["json"]
57 | case .yaml:
58 | return ["yml"]
59 | }
60 | }
61 |
62 | var assetName: String {
63 | switch self {
64 | case .assets:
65 | return "photo"
66 | case .strings:
67 | return "photo"
68 | case .colors:
69 | return "photo"
70 | case .fonts:
71 | return "photo"
72 | default:
73 | return "photo"
74 | }
75 | }
76 |
77 | var defaultEnumName: String {
78 | switch self {
79 | case .assets:
80 | return XCAssetsTemplate.defaultEnumName
81 | case .strings:
82 | return StringsTemplate.defaultEnumName
83 | case .colors:
84 | return ColorsTemplate.defaultEnumName
85 | case .fonts:
86 | return FontsTemplate.defaultEnumName
87 | case .ib:
88 | return InterfaceBuildersTemplate.defaultEnumName
89 | case .json:
90 | return JSONTemplate.defaultEnumName
91 | case .yaml:
92 | return YAMLTemplate.defaultEnumName
93 |
94 | }
95 | }
96 |
97 | var typeValue: String {
98 | switch self {
99 | case .assets:
100 | return "xcassets"
101 | case .strings:
102 | return "strings"
103 | case .colors:
104 | return "colors"
105 | case .fonts:
106 | return "fonts"
107 | case .ib:
108 | return "ib"
109 | case .json:
110 | return "json"
111 | case .yaml:
112 | return "yaml"
113 | }
114 | }
115 | }
116 |
117 | extension SwiftGenType {
118 |
119 | var contentView: some View {
120 | switch self {
121 | case .assets:
122 | return AnyView(FormView(selectedTemplate: .swift4))
123 | case .strings:
124 | return AnyView(FormView(selectedTemplate: .structuredSwift4))
125 | case .colors:
126 | return AnyView(FormView(selectedTemplate: .literalsSwift4))
127 | case .fonts:
128 | return AnyView(FormView(selectedTemplate: .swift4))
129 | case .ib:
130 | return AnyView(FormView(selectedTemplate: .scenesSwift4))
131 | case .json:
132 | return AnyView(FormView(selectedTemplate: .runTimeSwift4))
133 | case .yaml:
134 | return AnyView(FormView(selectedTemplate: .inlineSwift4))
135 |
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/View/Forms/MacEditorTextView.swift:
--------------------------------------------------------------------------------
1 | /**
2 | * MacEditorTextView
3 | * Copyright (c) Thiago Holanda 2020
4 | * https://twitter.com/tholanda
5 | *
6 | * MIT license
7 | */
8 |
9 | import Combine
10 | import SwiftUI
11 |
12 | struct MacEditorTextView: NSViewRepresentable {
13 | var text: NSAttributedString
14 |
15 |
16 | func makeNSView(context: Context) -> CustomTextView {
17 | let textView = CustomTextView(text: self.text)
18 |
19 | return textView
20 | }
21 |
22 | func updateNSView(_ view: CustomTextView, context: Context) {
23 | view.text = text
24 | }
25 | }
26 |
27 |
28 | final class CustomTextView: NSView {
29 | private var isEditable: Bool = false
30 | private var font: NSFont
31 |
32 | weak var delegate: NSTextViewDelegate?
33 |
34 | var text: NSAttributedString {
35 | didSet {
36 | textView.string = ""
37 | textView.insertText(text, replacementRange: NSMakeRange(0, text.length))
38 | }
39 | }
40 |
41 | var selectedRanges: [NSValue] = [] {
42 | didSet {
43 | guard selectedRanges.count > 0 else {
44 | return
45 | }
46 |
47 | textView.selectedRanges = selectedRanges
48 | }
49 | }
50 |
51 | private lazy var scrollView: NSScrollView = {
52 | let scrollView = NSScrollView()
53 | scrollView.drawsBackground = true
54 | scrollView.borderType = .noBorder
55 | scrollView.hasVerticalScroller = true
56 | scrollView.hasHorizontalRuler = false
57 | scrollView.autoresizingMask = [.width, .height]
58 | scrollView.translatesAutoresizingMaskIntoConstraints = false
59 |
60 | return scrollView
61 | }()
62 |
63 | private lazy var textView: NSTextView = {
64 | let contentSize = scrollView.contentSize
65 | let textStorage = NSTextStorage()
66 |
67 |
68 | let layoutManager = NSLayoutManager()
69 | textStorage.addLayoutManager(layoutManager)
70 |
71 |
72 | let textContainer = NSTextContainer(containerSize: scrollView.frame.size)
73 | textContainer.widthTracksTextView = true
74 | textContainer.containerSize = NSSize(
75 | width: contentSize.width,
76 | height: CGFloat.greatestFiniteMagnitude
77 | )
78 |
79 | layoutManager.addTextContainer(textContainer)
80 |
81 |
82 | let textView = NSTextView(frame: .zero, textContainer: textContainer)
83 | textView.autoresizingMask = .width
84 | textView.backgroundColor = NSColor.textBackgroundColor
85 | textView.delegate = self.delegate
86 | textView.drawsBackground = true
87 | textView.font = self.font
88 | textView.isEditable = self.isEditable
89 | textView.isHorizontallyResizable = false
90 | textView.isVerticallyResizable = true
91 | textView.maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
92 | textView.minSize = NSSize(width: 0, height: contentSize.height)
93 | textView.textColor = NSColor.labelColor
94 |
95 | return textView
96 | }()
97 |
98 | // MARK: - Init
99 | init(text: NSAttributedString, isEditable: Bool = true, font: NSFont = NSFont.monospacedSystemFont(ofSize: 17, weight: NSFont.Weight.medium)) {
100 | self.font = font
101 | self.isEditable = isEditable
102 | self.text = text
103 |
104 | super.init(frame: .zero)
105 | }
106 |
107 | required init?(coder: NSCoder) {
108 | fatalError("init(coder:) has not been implemented")
109 | }
110 |
111 | // MARK: - Life cycle
112 |
113 | override func viewWillDraw() {
114 | super.viewWillDraw()
115 |
116 | setupScrollViewConstraints()
117 | setupTextView()
118 | }
119 |
120 | func setupScrollViewConstraints() {
121 | scrollView.translatesAutoresizingMaskIntoConstraints = false
122 |
123 | addSubview(scrollView)
124 |
125 | NSLayoutConstraint.activate([
126 | scrollView.topAnchor.constraint(equalTo: topAnchor),
127 | scrollView.trailingAnchor.constraint(equalTo: trailingAnchor),
128 | scrollView.bottomAnchor.constraint(equalTo: bottomAnchor),
129 | scrollView.leadingAnchor.constraint(equalTo: leadingAnchor)
130 | ])
131 | }
132 |
133 | func setupTextView() {
134 | scrollView.documentView = textView
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/View/Forms/FormView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FormView.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 20/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 | import Splash
11 |
12 | struct FormView: View {
13 |
14 | @EnvironmentObject var appState: AppState
15 |
16 | var templates: [S] { S.allCases }
17 |
18 | @State var selectedTemplate: S
19 | @State var selectedURL: URL?
20 | @State var enumClassName: String = S.defaultEnumName
21 | @State var colorAliasName: String = TemplateParameterType.colorAliasName.defaultValue ?? ""
22 | @State var imageTypeName: String = TemplateParameterType.imageTypeName.defaultValue ?? ""
23 | @State var imageAliasName: String = TemplateParameterType.imageAliasName.defaultValue ?? ""
24 | @State var colorTypeName: String = TemplateParameterType.colorTypeName.defaultValue ?? ""
25 | @State var sceneEnumName: String = TemplateParameterType.sceneEnumName.defaultValue ?? ""
26 | @State var segueEnumName: String = TemplateParameterType.segueEnumName.defaultValue ?? ""
27 |
28 | @State var preservePath: Bool = false
29 | @State var publicAccess: Bool = false
30 | @State var noAllValues: Bool = false
31 | @State var module: Bool = false
32 | @State var ignoreTargetModule: Bool = false
33 | @State var noComments: Bool = false
34 |
35 |
36 | var body: some View {
37 | VStack(alignment: .leading, spacing: 16) {
38 | FileSelectView(
39 | documentType: S.type.supportedDocumentType,
40 | allowedFileTypes: S.type.allowedFileTypes
41 | ) { url in
42 | self.selectedURL = url
43 | }
44 |
45 | Divider()
46 |
47 | if self.selectedURL != nil {
48 | VStack(alignment: .leading, spacing: 8) {
49 | Text("Selected directory")
50 | .font(.headline)
51 | Text(self.selectedURL!.path)
52 | .lineLimit(5)
53 | .font(.caption)
54 | }
55 |
56 | Divider()
57 | }
58 |
59 | VStack(alignment: .leading, spacing: 16) {
60 | Text("Template & Parameters")
61 | .font(.headline)
62 |
63 | Picker(selection: self.$selectedTemplate, label: Text("Template")) {
64 | ForEach(self.templates, id: \.self) { template in
65 | Text(template.rawValue).tag(template)
66 | }
67 | }
68 |
69 | TemplateTextFieldFormView(
70 | defaultEnumName: S.defaultEnumName,
71 | selectedTemplateParameters: self.selectedTemplate.parameters,
72 | enumClassName: self.$enumClassName,
73 | colorAliasName: self.$colorAliasName,
74 | imageTypeName: self.$imageTypeName,
75 | imageAliasName: self.$imageAliasName,
76 | colorTypeName: self.$colorTypeName,
77 | sceneEnumName: self.$sceneEnumName,
78 | segueEnumName: self.$segueEnumName
79 | )
80 |
81 | TemplateToggleFormView(
82 | selectedTemplateParameters: self.selectedTemplate.parameters, preservePath: self.$preservePath, publicAccess: self.$publicAccess, noAllValues: self.$noAllValues, module: self.$module, ignoreTargetModule: self.$ignoreTargetModule, noComments: self.$noComments
83 | )
84 | }
85 |
86 | Divider()
87 |
88 | if appState.isProcessing {
89 | HStack {
90 | Spacer()
91 | ProgressView()
92 | Spacer()
93 | }
94 |
95 | } else {
96 | Button(action: {
97 | self.generateSwiftGen()
98 | }) {
99 | Text("Generate Swift Code")
100 | }.disabled(self.selectedURL == nil)
101 | .frame(maxWidth: .infinity)
102 | }
103 | Spacer()
104 | }
105 | .padding(.horizontal, 16)
106 | .frame(width: 300, height: 768)
107 |
108 | }
109 |
110 | func generateSwiftGen() {
111 | guard let inputURL = self.selectedURL
112 | else {
113 | return
114 | }
115 |
116 | let templateParams = TemplateParams(
117 | enumName: self.enumClassName,
118 | colorAliasName: self.colorAliasName,
119 | colorTypeName: self.colorTypeName,
120 | imageTypeName: self.imageTypeName,
121 | imageAliasName: self.imageAliasName,
122 | sceneEnumName: self.sceneEnumName,
123 | segueEnumName: self.segueEnumName,
124 | module: self.module,
125 | noAllValues: self.noAllValues,
126 | preservePath: self.preservePath,
127 | ignoreTargetModule: self.ignoreTargetModule,
128 | publicAccess: self.publicAccess,
129 | noComments: self.noComments
130 | )
131 |
132 | let swiftGenCommand = SwiftGenConcreteCommand(
133 | type: S.type,
134 | inputURL: inputURL,
135 | templateName: self.selectedTemplate.rawValue,
136 | templateParams: templateParams)
137 |
138 | self.appState.isProcessing = true
139 | DispatchQueue.global(qos: .userInitiated).async {
140 | _ = swiftGenCommand.generateSwiftCode()
141 | DispatchQueue.main.async {
142 | self.appState.isProcessing = false
143 | self.appState.command = swiftGenCommand
144 | }
145 | }
146 | }
147 |
148 | }
149 |
150 | struct TemplateToggleFormView: View {
151 |
152 | var selectedTemplateParameters: [TemplateParameterType]
153 |
154 | @Binding var preservePath: Bool
155 | @Binding var publicAccess: Bool
156 | @Binding var noAllValues: Bool
157 | @Binding var module: Bool
158 | @Binding var ignoreTargetModule: Bool
159 | @Binding var noComments: Bool
160 |
161 | func binding(for parameter: TemplateParameterType) -> Binding {
162 | switch parameter {
163 | case .preservePath:
164 | return self.$preservePath
165 | case .module:
166 | return self.$module
167 | case .ignoreTargetModule:
168 | return self.$ignoreTargetModule
169 | case .publicAccess:
170 | return self.$publicAccess
171 | case .noAllValues:
172 | return self.$noAllValues
173 | case .noComments:
174 | return self.$noComments
175 | default:
176 | fatalError()
177 | }
178 | }
179 |
180 | var body: some View {
181 | ForEach(TemplateParameterType.boolFieldCases) { parameter in
182 | if self.selectedTemplateParameters.firstIndex(of: parameter) != nil {
183 | parameter.toggleFormView(binding: self.binding(for: parameter))
184 | }
185 | }
186 | }
187 | }
188 |
189 |
190 | struct TemplateTextFieldFormView: View {
191 |
192 | var defaultEnumName: String
193 | var selectedTemplateParameters: [TemplateParameterType]
194 |
195 | @Binding var enumClassName: String
196 | @Binding var colorAliasName: String
197 | @Binding var imageTypeName: String
198 | @Binding var imageAliasName: String
199 | @Binding var colorTypeName: String
200 | @Binding var sceneEnumName: String
201 | @Binding var segueEnumName: String
202 |
203 | func binding(for parameter: TemplateParameterType) -> Binding {
204 | switch parameter {
205 | case .enumName:
206 | return self.$enumClassName
207 | case .colorAliasName:
208 | return self.$colorAliasName
209 | case .imageAliasName:
210 | return self.$imageAliasName
211 | case .colorTypeName:
212 | return self.$colorTypeName
213 | case .imageTypeName:
214 | return self.$imageTypeName
215 | case .sceneEnumName:
216 | return self.$sceneEnumName
217 | case .segueEnumName:
218 | return self.$segueEnumName
219 | default:
220 | fatalError()
221 | }
222 | }
223 |
224 | var body: some View {
225 | ForEach(TemplateParameterType.stringFieldCases) { parameter in
226 | if self.selectedTemplateParameters.firstIndex(of: parameter) != nil {
227 | parameter.textFieldFormView(binding: self.binding(for: parameter))
228 | }
229 | }
230 | }
231 |
232 | }
233 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/Model/SwiftGen+Types.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftGen+Types.swift
3 | // macCMDTest
4 | //
5 | // Created by Alfian Losari on 20/02/20.
6 | // Copyright © 2020 alfianlosari. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SwiftUI
11 | import Splash
12 |
13 | protocol SwiftGenCommand: class {
14 |
15 | var cachedResult: SwiftGenResult? { get set }
16 |
17 | var type: SwiftGenType { get }
18 | var inputURL: URL { get }
19 | var templateName: String { get }
20 | var templateParams: TemplateParams? { get }
21 | var parameters: [String]? { get }
22 |
23 | func generateSwiftCode() -> SwiftGenResult?
24 | func generateSwiftCodeAndSaveToFile(url: URL)
25 | func generateSwiftCodeAndCopyToClipboard()
26 |
27 | }
28 |
29 | extension SwiftGenCommand {
30 |
31 | var parameters: [String]? {
32 | guard let templateParams = templateParams else {
33 | return nil
34 | }
35 | var params = [String]()
36 |
37 | if let enumName = templateParams.enumName {
38 | let name = enumName.isEmpty ? type.defaultEnumName : enumName
39 |
40 | params += ["--param", "\(TemplateParameterType.enumName.rawValue)=\(name)"]
41 | }
42 |
43 | if let colorAliasName = templateParams.colorAliasName, !colorAliasName.isEmpty {
44 | params += ["--param", "\(TemplateParameterType.colorAliasName.rawValue)=\(colorAliasName)"]
45 | }
46 |
47 | if let colorTypeName = templateParams.colorTypeName, !colorTypeName.isEmpty {
48 | params += ["--param", "\(TemplateParameterType.colorTypeName.rawValue)=\(colorTypeName)"]
49 | }
50 |
51 | if let imageTypeName = templateParams.imageTypeName, !imageTypeName.isEmpty {
52 | params += ["--param", "\(TemplateParameterType.imageTypeName.rawValue)=\(imageTypeName)"]
53 | }
54 |
55 | if let imageAliasName = templateParams.imageAliasName, !imageAliasName.isEmpty {
56 | params += ["--param", "\(TemplateParameterType.imageAliasName.rawValue)=\(imageAliasName)"]
57 | }
58 |
59 | if let sceneEnumName = templateParams.sceneEnumName, !sceneEnumName.isEmpty {
60 | params += ["--param", "\(TemplateParameterType.sceneEnumName.rawValue)=\(sceneEnumName)"]
61 | }
62 |
63 | if let segueEnumName = templateParams.segueEnumName, !segueEnumName.isEmpty {
64 | params += ["--param", "\(TemplateParameterType.segueEnumName.rawValue)=\(segueEnumName)"]
65 | }
66 |
67 | if let noAllValues = templateParams.noAllValues, noAllValues {
68 | params += ["--param", TemplateParameterType.noAllValues.rawValue]
69 | }
70 |
71 | if let preservePath = templateParams.preservePath, preservePath {
72 | params += ["--param", TemplateParameterType.preservePath.rawValue]
73 | }
74 |
75 | if let module = templateParams.module, module {
76 | params += ["--param", TemplateParameterType.module.rawValue]
77 | }
78 |
79 | if let ignoreTargetModule = templateParams.ignoreTargetModule, ignoreTargetModule {
80 | params += ["--param", TemplateParameterType.ignoreTargetModule.rawValue]
81 | }
82 |
83 | if let publicAccess = templateParams.publicAccess, publicAccess {
84 | params += ["--param", TemplateParameterType.publicAccess.rawValue]
85 | }
86 |
87 | if let noComments = templateParams.noComments, noComments {
88 | params += ["--param", TemplateParameterType.noComments.rawValue]
89 | }
90 |
91 | return params
92 | }
93 |
94 |
95 | private func executeCommand(parameters: [String]) -> String? {
96 | let swiftGenPath = "/usr/local/bin/swiftgen"
97 |
98 | var arguments: [String] = [self.type.typeValue, inputURL.path, "--templateName", templateName]
99 | arguments += parameters
100 |
101 | if let data = Process.execute(swiftGenPath, arguments: arguments) {
102 | let string = String(data: data, encoding: .utf8)
103 | return string
104 | } else {
105 | return nil
106 | }
107 | }
108 |
109 | func generateSwiftCode() -> SwiftGenResult? {
110 | if let cachedResult = self.cachedResult {
111 | return cachedResult
112 | }
113 |
114 | guard let result = executeCommand(parameters: self.parameters ?? []) else {
115 | return SwiftGenResult(code: "", attributedCode: NSAttributedString(string: ""))
116 | }
117 |
118 | let highlighter = SyntaxHighlighter(format: AttributedStringOutputFormat(theme: Theme.midnight(withFont: Splash.Font.init(size: 20))))
119 | let attrString = highlighter.highlight(result)
120 | let swiftGenResult = SwiftGenResult(code: result, attributedCode: attrString)
121 | cachedResult = swiftGenResult
122 | return swiftGenResult
123 |
124 | }
125 |
126 | func generateSwiftCodeAndSaveToFile(url: URL) {
127 | var parameters = self.parameters ?? []
128 | parameters += ["--output", url.path]
129 |
130 | _ = executeCommand(parameters: parameters)
131 | }
132 |
133 | func generateSwiftCodeAndCopyToClipboard() {
134 | let text: String
135 | if let cachedText = cachedResult?.code {
136 | text = cachedText
137 | } else if let _text = executeCommand(parameters: parameters ?? []) {
138 | text = _text
139 | } else {
140 | return
141 | }
142 |
143 | let pasteBoard = NSPasteboard.general
144 | pasteBoard.clearContents()
145 | pasteBoard.writeObjects([text as NSString])
146 | }
147 |
148 | }
149 |
150 | class SwiftGenConcreteCommand: SwiftGenCommand {
151 |
152 |
153 | var type: SwiftGenType
154 | var inputURL: URL {
155 | didSet { cachedResult = nil }
156 | }
157 | var templateName: String
158 | var templateParams: TemplateParams?
159 |
160 | var cachedResult: SwiftGenResult? = nil
161 |
162 | init(type: SwiftGenType, inputURL: URL, templateName: String, templateParams: TemplateParams?, cachedResult: SwiftGenResult? = nil) {
163 | self.type = type
164 | self.inputURL = inputURL
165 | self.templateName = templateName
166 | self.templateParams = templateParams
167 | self.cachedResult = cachedResult
168 | }
169 |
170 | }
171 |
172 |
173 | enum AccessModifier: String, CaseIterable {
174 | case `public`
175 | case `internal`
176 | }
177 |
178 | struct TemplateParams {
179 | var enumName: String?
180 | var colorAliasName: String?
181 | var colorTypeName: String?
182 | var imageTypeName: String?
183 | var imageAliasName: String?
184 | var sceneEnumName: String?
185 | var segueEnumName: String?
186 | var module: Bool?
187 | var noAllValues: Bool?
188 | var preservePath: Bool?
189 | var ignoreTargetModule: Bool?
190 | var publicAccess: Bool?
191 | var noComments: Bool?
192 | }
193 |
194 | protocol SelectedAssetTemplate: Hashable {
195 |
196 | var rawValue: String { get }
197 | var parameters: [TemplateParameterType] { get }
198 | static var allCases: [Self] { get }
199 |
200 | static var type: SwiftGenType { get }
201 | static var defaultEnumName: String { get }
202 |
203 | }
204 |
205 |
206 | enum XCAssetsTemplate: String, CaseIterable, SelectedAssetTemplate {
207 | case swift2
208 | case swift3
209 | case swift4
210 |
211 | static var defaultEnumName: String { "Asset" }
212 | static var type: SwiftGenType { SwiftGenType.assets }
213 |
214 | var parameters: [(TemplateParameterType)] {
215 | switch self {
216 | case .swift2:
217 | return [.enumName, .imageAliasName, .colorTypeName, .imageTypeName, .noAllValues, .publicAccess]
218 | case .swift3, .swift4:
219 | return [.enumName, .colorAliasName, .imageAliasName, .colorTypeName, .imageTypeName, .noAllValues, .publicAccess]
220 | }
221 | }
222 | }
223 |
224 |
225 | enum ColorsTemplate: String, CaseIterable, SelectedAssetTemplate {
226 | case literalsSwift3 = "literals-swift3"
227 | case literalsSwift4 = "literals-swift4"
228 | case swift2
229 | case swift3
230 | case swift4
231 |
232 | static var defaultEnumName: String { "ColorName" }
233 | static var type: SwiftGenType { SwiftGenType.colors }
234 |
235 |
236 | var parameters: [(TemplateParameterType)] {
237 | switch self {
238 | case .literalsSwift3, .literalsSwift4:
239 | return [
240 | .enumName, .publicAccess
241 | ]
242 |
243 | case .swift2, .swift3, .swift4:
244 | return [
245 | .enumName, .colorAliasName, .publicAccess
246 | ]
247 | }
248 | }
249 | }
250 |
251 | enum FontsTemplate: String, CaseIterable, SelectedAssetTemplate {
252 |
253 | static var defaultEnumName: String { "FontFamily"}
254 | static var type: SwiftGenType { SwiftGenType.fonts }
255 |
256 | case swift2
257 | case swift3
258 | case swift4
259 |
260 | var parameters: [(TemplateParameterType)] {
261 | [.enumName, .preservePath, .publicAccess]
262 | }
263 | }
264 |
265 | enum InterfaceBuildersTemplate: String, CaseIterable, SelectedAssetTemplate {
266 |
267 | static var defaultEnumName: String { "" }
268 | static var type: SwiftGenType { SwiftGenType.ib }
269 |
270 | case scenesSwift4 = "scenes-swift4"
271 | case seguesSwift4 = "segues-swift4"
272 | case scenesSwift3 = "scenes-swift3"
273 | case seguesSwift3 = "segues-swift3"
274 |
275 |
276 | var parameters: [(TemplateParameterType)] {
277 | [
278 | .sceneEnumName, .segueEnumName, .module, .ignoreTargetModule, .publicAccess
279 | ]
280 | }
281 | }
282 |
283 | enum StringsTemplate: String, CaseIterable, SelectedAssetTemplate {
284 |
285 | static var defaultEnumName: String { "L10n" }
286 | static var type: SwiftGenType { SwiftGenType.strings }
287 |
288 | case flatSwift2 = "flat-swift2"
289 | case flatSwift3 = "flat-swift3"
290 | case flatSwift4 = "flat-swift4"
291 | case structuredSwift2 = "structured-swift2"
292 | case structuredSwift3 = "structured-swift3"
293 | case structuredSwift4 = "structured-swift4"
294 |
295 | var parameters: [(TemplateParameterType)] {
296 | [
297 | .enumName, .noComments, .publicAccess
298 | ]
299 | }
300 |
301 | }
302 |
303 | enum JSONTemplate: String, CaseIterable, SelectedAssetTemplate {
304 |
305 | static var defaultEnumName: String { "JSONFiles" }
306 | static var type: SwiftGenType { SwiftGenType.json }
307 |
308 | case runTimeSwift4 = "runtime-swift4"
309 | case inlineSwift4 = "inline-swift4"
310 | case inlineSwift3 = "inline-swift3"
311 | case runTimeSwift3 = "runtime-swift3"
312 |
313 | var parameters: [(TemplateParameterType)] {
314 | [
315 | .enumName, .publicAccess
316 | ]
317 | }
318 |
319 | }
320 |
321 | enum YAMLTemplate: String, CaseIterable, SelectedAssetTemplate {
322 |
323 | static var defaultEnumName: String { "YAMLFiles" }
324 | static var type: SwiftGenType { SwiftGenType.yaml }
325 |
326 | case inlineSwift4 = "inline-swift4"
327 | case inlineSwift3 = "inline-swift3"
328 |
329 | var parameters: [(TemplateParameterType)] {
330 | [
331 | .enumName, .publicAccess
332 | ]
333 | }
334 |
335 | }
336 |
337 |
338 | enum TemplateParameterType: String, Identifiable, CaseIterable {
339 |
340 | var id: TemplateParameterType { self }
341 | case enumName
342 | case colorAliasName
343 | case imageAliasName
344 | case colorTypeName
345 | case imageTypeName
346 | case sceneEnumName
347 | case segueEnumName
348 | case noAllValues
349 | case preservePath
350 | case module
351 | case ignoreTargetModule
352 | case publicAccess
353 | case noComments
354 |
355 | var defaultValue: String? {
356 | switch self {
357 | case .colorAliasName:
358 | return "Color"
359 | case .imageAliasName:
360 | return "Image"
361 | case .colorTypeName:
362 | return "ColorAsset"
363 | case .imageTypeName:
364 | return "ImageAsset"
365 | case .sceneEnumName:
366 | return "StoryboardScene"
367 | case .segueEnumName:
368 | return "StoryboardSegue"
369 | case .enumName,
370 | .preservePath,
371 | .module,
372 | .ignoreTargetModule,
373 | .publicAccess,
374 | .noAllValues,
375 | .noComments:
376 | return nil
377 | }
378 | }
379 |
380 | var label: String {
381 | switch self {
382 | case .colorAliasName:
383 | return "Color alias name"
384 | case .imageAliasName:
385 | return "Image alias name"
386 | case .colorTypeName:
387 | return "Color type name"
388 | case .imageTypeName:
389 | return "Image type name"
390 | case .sceneEnumName:
391 | return "Scene enum name"
392 | case .segueEnumName:
393 | return "Segue enum name"
394 | case .enumName:
395 | return "Enum class name"
396 | case .preservePath:
397 | return "Preserve path"
398 | case .module:
399 | return "Module"
400 | case .ignoreTargetModule:
401 | return "Ignore target module"
402 | case .publicAccess:
403 | return "Public access"
404 | case .noAllValues:
405 | return "No all values"
406 | case .noComments:
407 | return "No comments"
408 |
409 | }
410 | }
411 |
412 |
413 | static var stringFieldCases: [TemplateParameterType] {
414 | [
415 | .enumName,
416 | .colorAliasName,
417 | .imageAliasName,
418 | .colorTypeName,
419 | .imageTypeName,
420 | .sceneEnumName,
421 | .segueEnumName
422 | ]
423 | }
424 |
425 | static var boolFieldCases: [TemplateParameterType] {
426 | [
427 | .preservePath,
428 | .module,
429 | .ignoreTargetModule,
430 | .publicAccess,
431 | .noAllValues,
432 | .noComments
433 | ]
434 | }
435 |
436 |
437 | }
438 |
439 | extension TemplateParameterType {
440 | func textFieldFormView(binding: Binding) -> some View {
441 | VStack(alignment: .leading, spacing: 8) {
442 | Text(self.label)
443 | TextField("", text: binding)
444 | }
445 |
446 | }
447 |
448 | func toggleFormView(binding: Binding) -> some View {
449 | Toggle(self.label, isOn: binding)
450 |
451 | }
452 | }
453 |
--------------------------------------------------------------------------------
/SwiftGenUIMac.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8B8DC3BF23FFEFE100C7903A /* ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B8DC3BE23FFEFE100C7903A /* ProgressView.swift */; };
11 | 8BB3ABD623FF830B00E12395 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABD523FF830B00E12395 /* AppDelegate.swift */; };
12 | 8BB3ABDA23FF830D00E12395 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8BB3ABD923FF830D00E12395 /* Assets.xcassets */; };
13 | 8BB3ABDD23FF830D00E12395 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8BB3ABDC23FF830D00E12395 /* Preview Assets.xcassets */; };
14 | 8BB3ABE023FF830D00E12395 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8BB3ABDE23FF830D00E12395 /* Main.storyboard */; };
15 | 8BB3ABEA23FF837C00E12395 /* Splash in Frameworks */ = {isa = PBXBuildFile; productRef = 8BB3ABE923FF837C00E12395 /* Splash */; };
16 | 8BB3ABF723FF83BA00E12395 /* SwiftGen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABEC23FF83BA00E12395 /* SwiftGen.swift */; };
17 | 8BB3ABF823FF83BA00E12395 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABED23FF83BA00E12395 /* AppState.swift */; };
18 | 8BB3ABF923FF83BA00E12395 /* SwiftGen+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABEE23FF83BA00E12395 /* SwiftGen+Types.swift */; };
19 | 8BB3ABFA23FF83BA00E12395 /* FileSelectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABF123FF83BA00E12395 /* FileSelectView.swift */; };
20 | 8BB3ABFB23FF83BA00E12395 /* MacEditorTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABF223FF83BA00E12395 /* MacEditorTextView.swift */; };
21 | 8BB3ABFC23FF83BA00E12395 /* FormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABF323FF83BA00E12395 /* FormView.swift */; };
22 | 8BB3ABFD23FF83BA00E12395 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABF423FF83BA00E12395 /* ContentView.swift */; };
23 | 8BB3ABFE23FF83BA00E12395 /* Process+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BB3ABF623FF83BA00E12395 /* Process+Extension.swift */; };
24 | /* End PBXBuildFile section */
25 |
26 | /* Begin PBXFileReference section */
27 | 8B8DC3BE23FFEFE100C7903A /* ProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressView.swift; sourceTree = ""; };
28 | 8BB3ABD223FF830B00E12395 /* SwiftGenUIMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftGenUIMac.app; sourceTree = BUILT_PRODUCTS_DIR; };
29 | 8BB3ABD523FF830B00E12395 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
30 | 8BB3ABD923FF830D00E12395 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
31 | 8BB3ABDC23FF830D00E12395 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
32 | 8BB3ABDF23FF830D00E12395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
33 | 8BB3ABE123FF830D00E12395 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
34 | 8BB3ABE223FF830D00E12395 /* SwiftGenUIMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SwiftGenUIMac.entitlements; sourceTree = ""; };
35 | 8BB3ABEC23FF83BA00E12395 /* SwiftGen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftGen.swift; sourceTree = ""; };
36 | 8BB3ABED23FF83BA00E12395 /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; };
37 | 8BB3ABEE23FF83BA00E12395 /* SwiftGen+Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Types.swift"; sourceTree = ""; };
38 | 8BB3ABF123FF83BA00E12395 /* FileSelectView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileSelectView.swift; sourceTree = ""; };
39 | 8BB3ABF223FF83BA00E12395 /* MacEditorTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacEditorTextView.swift; sourceTree = ""; };
40 | 8BB3ABF323FF83BA00E12395 /* FormView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormView.swift; sourceTree = ""; };
41 | 8BB3ABF423FF83BA00E12395 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
42 | 8BB3ABF623FF83BA00E12395 /* Process+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Process+Extension.swift"; sourceTree = ""; };
43 | /* End PBXFileReference section */
44 |
45 | /* Begin PBXFrameworksBuildPhase section */
46 | 8BB3ABCF23FF830B00E12395 /* Frameworks */ = {
47 | isa = PBXFrameworksBuildPhase;
48 | buildActionMask = 2147483647;
49 | files = (
50 | 8BB3ABEA23FF837C00E12395 /* Splash in Frameworks */,
51 | );
52 | runOnlyForDeploymentPostprocessing = 0;
53 | };
54 | /* End PBXFrameworksBuildPhase section */
55 |
56 | /* Begin PBXGroup section */
57 | 8BB3ABC923FF830B00E12395 = {
58 | isa = PBXGroup;
59 | children = (
60 | 8BB3ABD423FF830B00E12395 /* SwiftGenUIMac */,
61 | 8BB3ABD323FF830B00E12395 /* Products */,
62 | );
63 | sourceTree = "";
64 | };
65 | 8BB3ABD323FF830B00E12395 /* Products */ = {
66 | isa = PBXGroup;
67 | children = (
68 | 8BB3ABD223FF830B00E12395 /* SwiftGenUIMac.app */,
69 | );
70 | name = Products;
71 | sourceTree = "";
72 | };
73 | 8BB3ABD423FF830B00E12395 /* SwiftGenUIMac */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 8BB3ABD523FF830B00E12395 /* AppDelegate.swift */,
77 | 8BB3ABD923FF830D00E12395 /* Assets.xcassets */,
78 | 8BB3ABDE23FF830D00E12395 /* Main.storyboard */,
79 | 8BB3ABF523FF83BA00E12395 /* Helper */,
80 | 8BB3ABEB23FF83BA00E12395 /* Model */,
81 | 8BB3ABEF23FF83BA00E12395 /* View */,
82 | 8BB3ABE123FF830D00E12395 /* Info.plist */,
83 | 8BB3ABE223FF830D00E12395 /* SwiftGenUIMac.entitlements */,
84 | 8BB3ABDB23FF830D00E12395 /* Preview Content */,
85 | );
86 | path = SwiftGenUIMac;
87 | sourceTree = "";
88 | };
89 | 8BB3ABDB23FF830D00E12395 /* Preview Content */ = {
90 | isa = PBXGroup;
91 | children = (
92 | 8BB3ABDC23FF830D00E12395 /* Preview Assets.xcassets */,
93 | );
94 | path = "Preview Content";
95 | sourceTree = "";
96 | };
97 | 8BB3ABEB23FF83BA00E12395 /* Model */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 8BB3ABEC23FF83BA00E12395 /* SwiftGen.swift */,
101 | 8BB3ABED23FF83BA00E12395 /* AppState.swift */,
102 | 8BB3ABEE23FF83BA00E12395 /* SwiftGen+Types.swift */,
103 | );
104 | path = Model;
105 | sourceTree = "";
106 | };
107 | 8BB3ABEF23FF83BA00E12395 /* View */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 8BB3ABF023FF83BA00E12395 /* Forms */,
111 | 8BB3ABF423FF83BA00E12395 /* ContentView.swift */,
112 | );
113 | path = View;
114 | sourceTree = "";
115 | };
116 | 8BB3ABF023FF83BA00E12395 /* Forms */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 8BB3ABF123FF83BA00E12395 /* FileSelectView.swift */,
120 | 8BB3ABF223FF83BA00E12395 /* MacEditorTextView.swift */,
121 | 8BB3ABF323FF83BA00E12395 /* FormView.swift */,
122 | 8B8DC3BE23FFEFE100C7903A /* ProgressView.swift */,
123 | );
124 | path = Forms;
125 | sourceTree = "";
126 | };
127 | 8BB3ABF523FF83BA00E12395 /* Helper */ = {
128 | isa = PBXGroup;
129 | children = (
130 | 8BB3ABF623FF83BA00E12395 /* Process+Extension.swift */,
131 | );
132 | path = Helper;
133 | sourceTree = "";
134 | };
135 | /* End PBXGroup section */
136 |
137 | /* Begin PBXNativeTarget section */
138 | 8BB3ABD123FF830B00E12395 /* SwiftGenUIMac */ = {
139 | isa = PBXNativeTarget;
140 | buildConfigurationList = 8BB3ABE523FF830D00E12395 /* Build configuration list for PBXNativeTarget "SwiftGenUIMac" */;
141 | buildPhases = (
142 | 8BB3ABCE23FF830B00E12395 /* Sources */,
143 | 8BB3ABCF23FF830B00E12395 /* Frameworks */,
144 | 8BB3ABD023FF830B00E12395 /* Resources */,
145 | );
146 | buildRules = (
147 | );
148 | dependencies = (
149 | );
150 | name = SwiftGenUIMac;
151 | packageProductDependencies = (
152 | 8BB3ABE923FF837C00E12395 /* Splash */,
153 | );
154 | productName = SwiftGenUIMac;
155 | productReference = 8BB3ABD223FF830B00E12395 /* SwiftGenUIMac.app */;
156 | productType = "com.apple.product-type.application";
157 | };
158 | /* End PBXNativeTarget section */
159 |
160 | /* Begin PBXProject section */
161 | 8BB3ABCA23FF830B00E12395 /* Project object */ = {
162 | isa = PBXProject;
163 | attributes = {
164 | LastSwiftUpdateCheck = 1130;
165 | LastUpgradeCheck = 1130;
166 | ORGANIZATIONNAME = "Alfian Losari";
167 | TargetAttributes = {
168 | 8BB3ABD123FF830B00E12395 = {
169 | CreatedOnToolsVersion = 11.3.1;
170 | };
171 | };
172 | };
173 | buildConfigurationList = 8BB3ABCD23FF830B00E12395 /* Build configuration list for PBXProject "SwiftGenUIMac" */;
174 | compatibilityVersion = "Xcode 9.3";
175 | developmentRegion = en;
176 | hasScannedForEncodings = 0;
177 | knownRegions = (
178 | en,
179 | Base,
180 | );
181 | mainGroup = 8BB3ABC923FF830B00E12395;
182 | packageReferences = (
183 | 8BB3ABE823FF837C00E12395 /* XCRemoteSwiftPackageReference "Splash" */,
184 | );
185 | productRefGroup = 8BB3ABD323FF830B00E12395 /* Products */;
186 | projectDirPath = "";
187 | projectRoot = "";
188 | targets = (
189 | 8BB3ABD123FF830B00E12395 /* SwiftGenUIMac */,
190 | );
191 | };
192 | /* End PBXProject section */
193 |
194 | /* Begin PBXResourcesBuildPhase section */
195 | 8BB3ABD023FF830B00E12395 /* Resources */ = {
196 | isa = PBXResourcesBuildPhase;
197 | buildActionMask = 2147483647;
198 | files = (
199 | 8BB3ABE023FF830D00E12395 /* Main.storyboard in Resources */,
200 | 8BB3ABDD23FF830D00E12395 /* Preview Assets.xcassets in Resources */,
201 | 8BB3ABDA23FF830D00E12395 /* Assets.xcassets in Resources */,
202 | );
203 | runOnlyForDeploymentPostprocessing = 0;
204 | };
205 | /* End PBXResourcesBuildPhase section */
206 |
207 | /* Begin PBXSourcesBuildPhase section */
208 | 8BB3ABCE23FF830B00E12395 /* Sources */ = {
209 | isa = PBXSourcesBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | 8BB3ABFB23FF83BA00E12395 /* MacEditorTextView.swift in Sources */,
213 | 8BB3ABF823FF83BA00E12395 /* AppState.swift in Sources */,
214 | 8BB3ABFD23FF83BA00E12395 /* ContentView.swift in Sources */,
215 | 8BB3ABFC23FF83BA00E12395 /* FormView.swift in Sources */,
216 | 8BB3ABF723FF83BA00E12395 /* SwiftGen.swift in Sources */,
217 | 8BB3ABFE23FF83BA00E12395 /* Process+Extension.swift in Sources */,
218 | 8BB3ABFA23FF83BA00E12395 /* FileSelectView.swift in Sources */,
219 | 8B8DC3BF23FFEFE100C7903A /* ProgressView.swift in Sources */,
220 | 8BB3ABF923FF83BA00E12395 /* SwiftGen+Types.swift in Sources */,
221 | 8BB3ABD623FF830B00E12395 /* AppDelegate.swift in Sources */,
222 | );
223 | runOnlyForDeploymentPostprocessing = 0;
224 | };
225 | /* End PBXSourcesBuildPhase section */
226 |
227 | /* Begin PBXVariantGroup section */
228 | 8BB3ABDE23FF830D00E12395 /* Main.storyboard */ = {
229 | isa = PBXVariantGroup;
230 | children = (
231 | 8BB3ABDF23FF830D00E12395 /* Base */,
232 | );
233 | name = Main.storyboard;
234 | sourceTree = "";
235 | };
236 | /* End PBXVariantGroup section */
237 |
238 | /* Begin XCBuildConfiguration section */
239 | 8BB3ABE323FF830D00E12395 /* Debug */ = {
240 | isa = XCBuildConfiguration;
241 | buildSettings = {
242 | ALWAYS_SEARCH_USER_PATHS = NO;
243 | CLANG_ANALYZER_NONNULL = YES;
244 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
246 | CLANG_CXX_LIBRARY = "libc++";
247 | CLANG_ENABLE_MODULES = YES;
248 | CLANG_ENABLE_OBJC_ARC = YES;
249 | CLANG_ENABLE_OBJC_WEAK = YES;
250 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
251 | CLANG_WARN_BOOL_CONVERSION = YES;
252 | CLANG_WARN_COMMA = YES;
253 | CLANG_WARN_CONSTANT_CONVERSION = YES;
254 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
255 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
256 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
257 | CLANG_WARN_EMPTY_BODY = YES;
258 | CLANG_WARN_ENUM_CONVERSION = YES;
259 | CLANG_WARN_INFINITE_RECURSION = YES;
260 | CLANG_WARN_INT_CONVERSION = YES;
261 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
262 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
263 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
264 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
265 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
266 | CLANG_WARN_STRICT_PROTOTYPES = YES;
267 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
268 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
269 | CLANG_WARN_UNREACHABLE_CODE = YES;
270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
271 | COPY_PHASE_STRIP = NO;
272 | DEBUG_INFORMATION_FORMAT = dwarf;
273 | ENABLE_STRICT_OBJC_MSGSEND = YES;
274 | ENABLE_TESTABILITY = YES;
275 | GCC_C_LANGUAGE_STANDARD = gnu11;
276 | GCC_DYNAMIC_NO_PIC = NO;
277 | GCC_NO_COMMON_BLOCKS = YES;
278 | GCC_OPTIMIZATION_LEVEL = 0;
279 | GCC_PREPROCESSOR_DEFINITIONS = (
280 | "DEBUG=1",
281 | "$(inherited)",
282 | );
283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
284 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
285 | GCC_WARN_UNDECLARED_SELECTOR = YES;
286 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
287 | GCC_WARN_UNUSED_FUNCTION = YES;
288 | GCC_WARN_UNUSED_VARIABLE = YES;
289 | MACOSX_DEPLOYMENT_TARGET = 10.15;
290 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
291 | MTL_FAST_MATH = YES;
292 | ONLY_ACTIVE_ARCH = YES;
293 | SDKROOT = macosx;
294 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
295 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
296 | };
297 | name = Debug;
298 | };
299 | 8BB3ABE423FF830D00E12395 /* Release */ = {
300 | isa = XCBuildConfiguration;
301 | buildSettings = {
302 | ALWAYS_SEARCH_USER_PATHS = NO;
303 | CLANG_ANALYZER_NONNULL = YES;
304 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
305 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
306 | CLANG_CXX_LIBRARY = "libc++";
307 | CLANG_ENABLE_MODULES = YES;
308 | CLANG_ENABLE_OBJC_ARC = YES;
309 | CLANG_ENABLE_OBJC_WEAK = YES;
310 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
311 | CLANG_WARN_BOOL_CONVERSION = YES;
312 | CLANG_WARN_COMMA = YES;
313 | CLANG_WARN_CONSTANT_CONVERSION = YES;
314 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
316 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
317 | CLANG_WARN_EMPTY_BODY = YES;
318 | CLANG_WARN_ENUM_CONVERSION = YES;
319 | CLANG_WARN_INFINITE_RECURSION = YES;
320 | CLANG_WARN_INT_CONVERSION = YES;
321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
326 | CLANG_WARN_STRICT_PROTOTYPES = YES;
327 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
328 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
329 | CLANG_WARN_UNREACHABLE_CODE = YES;
330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
331 | COPY_PHASE_STRIP = NO;
332 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
333 | ENABLE_NS_ASSERTIONS = NO;
334 | ENABLE_STRICT_OBJC_MSGSEND = YES;
335 | GCC_C_LANGUAGE_STANDARD = gnu11;
336 | GCC_NO_COMMON_BLOCKS = YES;
337 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
338 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
339 | GCC_WARN_UNDECLARED_SELECTOR = YES;
340 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
341 | GCC_WARN_UNUSED_FUNCTION = YES;
342 | GCC_WARN_UNUSED_VARIABLE = YES;
343 | MACOSX_DEPLOYMENT_TARGET = 10.15;
344 | MTL_ENABLE_DEBUG_INFO = NO;
345 | MTL_FAST_MATH = YES;
346 | SDKROOT = macosx;
347 | SWIFT_COMPILATION_MODE = wholemodule;
348 | SWIFT_OPTIMIZATION_LEVEL = "-O";
349 | };
350 | name = Release;
351 | };
352 | 8BB3ABE623FF830D00E12395 /* Debug */ = {
353 | isa = XCBuildConfiguration;
354 | buildSettings = {
355 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
356 | CODE_SIGN_ENTITLEMENTS = SwiftGenUIMac/SwiftGenUIMac.entitlements;
357 | CODE_SIGN_IDENTITY = "-";
358 | CODE_SIGN_STYLE = Automatic;
359 | COMBINE_HIDPI_IMAGES = YES;
360 | DEVELOPMENT_ASSET_PATHS = "\"SwiftGenUIMac/Preview Content\"";
361 | DEVELOPMENT_TEAM = 5C2XD9H2JS;
362 | ENABLE_HARDENED_RUNTIME = YES;
363 | ENABLE_PREVIEWS = YES;
364 | INFOPLIST_FILE = SwiftGenUIMac/Info.plist;
365 | LD_RUNPATH_SEARCH_PATHS = (
366 | "$(inherited)",
367 | "@executable_path/../Frameworks",
368 | );
369 | MACOSX_DEPLOYMENT_TARGET = 10.15;
370 | PRODUCT_BUNDLE_IDENTIFIER = com.alfianlosari.SwiftGenUIMac;
371 | PRODUCT_NAME = "$(TARGET_NAME)";
372 | SWIFT_VERSION = 5.0;
373 | };
374 | name = Debug;
375 | };
376 | 8BB3ABE723FF830D00E12395 /* Release */ = {
377 | isa = XCBuildConfiguration;
378 | buildSettings = {
379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
380 | CODE_SIGN_ENTITLEMENTS = SwiftGenUIMac/SwiftGenUIMac.entitlements;
381 | CODE_SIGN_IDENTITY = "-";
382 | CODE_SIGN_STYLE = Automatic;
383 | COMBINE_HIDPI_IMAGES = YES;
384 | DEVELOPMENT_ASSET_PATHS = "\"SwiftGenUIMac/Preview Content\"";
385 | DEVELOPMENT_TEAM = 5C2XD9H2JS;
386 | ENABLE_HARDENED_RUNTIME = YES;
387 | ENABLE_PREVIEWS = YES;
388 | INFOPLIST_FILE = SwiftGenUIMac/Info.plist;
389 | LD_RUNPATH_SEARCH_PATHS = (
390 | "$(inherited)",
391 | "@executable_path/../Frameworks",
392 | );
393 | MACOSX_DEPLOYMENT_TARGET = 10.15;
394 | PRODUCT_BUNDLE_IDENTIFIER = com.alfianlosari.SwiftGenUIMac;
395 | PRODUCT_NAME = "$(TARGET_NAME)";
396 | SWIFT_VERSION = 5.0;
397 | };
398 | name = Release;
399 | };
400 | /* End XCBuildConfiguration section */
401 |
402 | /* Begin XCConfigurationList section */
403 | 8BB3ABCD23FF830B00E12395 /* Build configuration list for PBXProject "SwiftGenUIMac" */ = {
404 | isa = XCConfigurationList;
405 | buildConfigurations = (
406 | 8BB3ABE323FF830D00E12395 /* Debug */,
407 | 8BB3ABE423FF830D00E12395 /* Release */,
408 | );
409 | defaultConfigurationIsVisible = 0;
410 | defaultConfigurationName = Release;
411 | };
412 | 8BB3ABE523FF830D00E12395 /* Build configuration list for PBXNativeTarget "SwiftGenUIMac" */ = {
413 | isa = XCConfigurationList;
414 | buildConfigurations = (
415 | 8BB3ABE623FF830D00E12395 /* Debug */,
416 | 8BB3ABE723FF830D00E12395 /* Release */,
417 | );
418 | defaultConfigurationIsVisible = 0;
419 | defaultConfigurationName = Release;
420 | };
421 | /* End XCConfigurationList section */
422 |
423 | /* Begin XCRemoteSwiftPackageReference section */
424 | 8BB3ABE823FF837C00E12395 /* XCRemoteSwiftPackageReference "Splash" */ = {
425 | isa = XCRemoteSwiftPackageReference;
426 | repositoryURL = "https://github.com/JohnSundell/Splash.git";
427 | requirement = {
428 | kind = upToNextMajorVersion;
429 | minimumVersion = 0.11.1;
430 | };
431 | };
432 | /* End XCRemoteSwiftPackageReference section */
433 |
434 | /* Begin XCSwiftPackageProductDependency section */
435 | 8BB3ABE923FF837C00E12395 /* Splash */ = {
436 | isa = XCSwiftPackageProductDependency;
437 | package = 8BB3ABE823FF837C00E12395 /* XCRemoteSwiftPackageReference "Splash" */;
438 | productName = Splash;
439 | };
440 | /* End XCSwiftPackageProductDependency section */
441 | };
442 | rootObject = 8BB3ABCA23FF830B00E12395 /* Project object */;
443 | }
444 |
--------------------------------------------------------------------------------
/SwiftGenUIMac/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
--------------------------------------------------------------------------------