├── .github
└── workflows
│ └── swift.yml
├── .gitignore
├── Codable
├── Codable.entitlements
├── Command.swift
├── Info.plist
├── OptionalExtension.swift
├── Regex.swift
├── SourceEditorCommand.swift
├── SourceEditorExtension.swift
└── StringExtension.swift
├── LICENSE
├── README.md
├── TrickerX.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcshareddata
│ └── xcschemes
│ │ └── TrickerX.xcscheme
└── xcuserdata
│ └── ray.xcuserdatad
│ └── xcschemes
│ └── Codable.xcscheme
├── TrickerX
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ └── Main.storyboard
├── Info.plist
├── TrickerX.entitlements
└── ViewController.swift
├── TrickerXTests
├── CodableRegexTests.swift
├── Info.plist
└── TrickerXTests.swift
├── app
└── TrickerX.dmg
├── codable.gif
└── fastlane
├── Appfile
├── Fastfile
├── README.md
└── make_dmg
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Swift project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift
3 |
4 | name: Swift
5 |
6 | on:
7 | push:
8 | branches: [ "master" ]
9 | pull_request:
10 | branches: [ "master" ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: macos-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: Build
20 | run: swift build -v
21 | - name: Run tests
22 | run: swift test -v
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 | xcuserdata
20 | *.DS_Store
21 | *.xcworkspace
22 |
23 | ## Other
24 | *.moved-aside
25 | *.xccheckout
26 | *.xcscmblueprint
27 |
28 | ## Obj-C/Swift specific
29 | *.hmap
30 | *.ipa
31 | *.dSYM.zip
32 | *.dSYM
33 |
34 | ## Playgrounds
35 | timeline.xctimeline
36 | playground.xcworkspace
37 |
38 | # Swift Package Manager
39 | #
40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
41 | # Packages/
42 | # Package.pins
43 | # Package.resolved
44 | .build/
45 |
46 | # CocoaPods
47 | #
48 | # We recommend against adding the Pods directory to your .gitignore. However
49 | # you should judge for yourself, the pros and cons are mentioned at:
50 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
51 | #
52 | # Pods/
53 |
54 | # Carthage
55 | #
56 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
57 | # Carthage/Checkouts
58 |
59 | Carthage/Build
60 |
61 | # fastlane
62 | #
63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
64 | # screenshots whenever they are needed.
65 | # For more information about the recommended setup visit:
66 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
67 |
68 | fastlane/report.xml
69 | fastlane/Preview.html
70 | fastlane/screenshots
71 | fastlane/test_output
72 |
--------------------------------------------------------------------------------
/Codable/Codable.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Codable/Command.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Command.swift
3 | // Codable
4 | //
5 | // Created by Lei Wang on 2017/12/6.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | enum Command: RawRepresentable {
13 |
14 | var rawValue: String {
15 | switch self {
16 | case .makeCodingKeys(let isSorting):
17 | if isSorting {
18 | return "makeCodingKeysWithSorting"
19 | }else {
20 | return "makeCodingKeys"
21 | }
22 | case .readme:
23 | return "readme"
24 | }
25 | }
26 |
27 | init?(rawValue: String) {
28 | switch rawValue {
29 | case "makeCodingKeys":
30 | self = .makeCodingKeys(sorting: false)
31 | case "makeCodingKeysWithSorting":
32 | self = .makeCodingKeys(sorting: true)
33 | case "readme":
34 | self = .readme
35 | default:
36 | return nil
37 | }
38 | }
39 | case makeCodingKeys(sorting: Bool)
40 | case readme
41 |
42 | var displayName: String {
43 | switch self {
44 | case .makeCodingKeys(let isSorting):
45 | if isSorting {
46 | return "Make Coding Key With Sorting"
47 | }else {
48 | return "Make Coding Key"
49 | }
50 | case .readme:
51 | return "README"
52 | }
53 | }
54 | }
55 |
56 |
57 |
--------------------------------------------------------------------------------
/Codable/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Codable
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSExtension
26 |
27 | NSExtensionAttributes
28 |
29 | XCSourceEditorExtensionPrincipalClass
30 | $(PRODUCT_MODULE_NAME).SourceEditorExtension
31 |
32 | NSExtensionPointIdentifier
33 | com.apple.dt.Xcode.extension.source-editor
34 |
35 | NSHumanReadableCopyright
36 | Copyright © 2017年 Lei Wang. All rights reserved.
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Codable/OptionalExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OptionalExtension.swift
3 | // Codable
4 | //
5 | // Created by Lei Wang on 2017/12/6.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | extension Optional where Wrapped == String {
13 | var unwrappedOrEmpty: String {
14 | switch self {
15 | case let .some(wrapped):
16 | return wrapped
17 | default:
18 | return ""
19 | }
20 | }
21 | }
22 | extension Optional where Wrapped: Collection {
23 | var isNilOrEmpty: Bool {
24 | switch self {
25 | case let .some(wrapped):
26 | return wrapped.isEmpty
27 | default:
28 | return true
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Codable/Regex.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Regex.swift
3 | // TrickerX
4 | //
5 | // Created by Lei Wang on 2017/12/7.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum Regex: String {
12 | case codableModelStartLine = ".+\\s*:\\s*.*(Codable|Decodable|Encodable).*\\{"
13 | case openBracket = "\\{"
14 | case closeBracket = "\\}"
15 | case closureOrTuple = "\\(.*\\)"
16 | case spaceOrTabIndent = "^(\\s|\\t)*"
17 | case toggleComments = "^\\s*\\/\\/"
18 |
19 | case codablePropertyLine = ".*(let|var)\\s+\\w+\\s*(:|=).+"
20 | case codablePropertyName = "\\w+(?=\\s*:)"
21 | case customKey = "\\/\\/\\s*\\w+"
22 | }
23 |
--------------------------------------------------------------------------------
/Codable/SourceEditorCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceEditorCommand.swift
3 | // Codable
4 | //
5 | // Created by Lei Wang on 2017/11/24.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XcodeKit
11 | import AppKit
12 |
13 | class SourceEditorCommand: NSObject, XCSourceEditorCommand {
14 |
15 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
16 | let command = Command.init(rawValue: invocation.commandIdentifier)
17 | command?.perform(with: invocation, completionHandler: completionHandler)
18 |
19 | }
20 |
21 | }
22 |
23 |
24 | private let Github = "https://github.com/wleii/TrickerX"
25 |
26 | enum TrickerXError: CustomDebugStringConvertible, CustomStringConvertible {
27 | case noSelectionFound
28 | case notFoundCodableModel
29 | case codablePropertyEmpty
30 |
31 | var localizedDescription: String {
32 | return description
33 | }
34 |
35 | var description: String {
36 | switch self {
37 | case .noSelectionFound:
38 | return "Not found selection line where to make CodingKeys"
39 | case .notFoundCodableModel:
40 | return "Not found codable model. Please add codable protocol where your model want to inherit"
41 | case .codablePropertyEmpty:
42 | return "Not found available codable properties. If you have a doubt about this, please check the documents: \(Github)"
43 | } }
44 | var debugDescription: String {
45 | return description
46 | }
47 |
48 | private var errorCode: Int {
49 | return 404
50 | }
51 |
52 | var asNSError: NSError {
53 | let domain = "com.rayternet.codable.error"
54 | let userInfo = [NSLocalizedDescriptionKey: description]
55 | return NSError(domain: domain, code: errorCode, userInfo: userInfo)
56 | }
57 | }
58 |
59 |
60 | private extension Command {
61 |
62 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
63 | switch self {
64 | case .makeCodingKeys(let isSortingKey):
65 | guard let textRange = invocation.buffer.selections.firstObject as? XCSourceTextRange else {
66 | completionHandler(TrickerXError.noSelectionFound.asNSError)
67 | return
68 | }
69 | var startLine = textRange.start.line
70 |
71 | var bracketCount: Int = 0
72 | var isMatchCodableModelStartLine: Bool = false
73 | var enumCase: [(key: String, value: String)] = []
74 |
75 | while startLine >= 0 {
76 | guard let lineText = invocation.buffer.lines[startLine] as? String else { startLine -= 1; continue }
77 |
78 |
79 | // toggle comments
80 | if !lineText.match(regex: .toggleComments).isNilOrEmpty {
81 | startLine -= 1
82 | continue
83 | }
84 |
85 | // find { or }
86 | let closeBracket: [String] = lineText.match(regex: Regex.closeBracket.rawValue)
87 | let openBracket: [String] = lineText.match(regex: Regex.openBracket.rawValue)
88 |
89 | bracketCount += closeBracket.count
90 |
91 | if bracketCount > 0 {
92 | // not full {} continue ⬆️ parse
93 | bracketCount -= openBracket.count
94 | startLine -= 1
95 | continue
96 | }
97 | if !lineText.match(regex: .codableModelStartLine).isNilOrEmpty {
98 | // the end, then break
99 | isMatchCodableModelStartLine = true
100 | break
101 | }
102 |
103 | //
104 | if !lineText.match(regex: .closureOrTuple).isNilOrEmpty {
105 | startLine -= 1
106 | continue
107 | }
108 |
109 | //
110 | let codablePropertyLine = lineText.match(regex: .codablePropertyLine).unwrappedOrEmpty
111 | if codablePropertyLine.isEmpty {
112 | startLine -= 1
113 | continue
114 | }
115 |
116 | // parse property name
117 | let propertyName = codablePropertyLine.match(regex: .codablePropertyName).unwrappedOrEmpty
118 |
119 | let rawValue: String
120 | // check: is exist custom key?
121 | if let customRawValue = codablePropertyLine.match(regex: .customKey)?.match(regex: "\\w+"), !customRawValue.isEmpty {
122 | rawValue = customRawValue
123 | let splitStrings = codablePropertyLine.split(separator: "/")
124 | invocation.buffer.lines[startLine] = splitStrings.first!
125 | }else {
126 | let propertyRawValue = propertyName.snakeCased().unwrappedOrEmpty
127 | rawValue = propertyRawValue
128 | }
129 | enumCase.append((key: propertyName, value: rawValue))
130 |
131 | // coontinue
132 | startLine -= 1
133 |
134 | }
135 |
136 | guard isMatchCodableModelStartLine else {
137 | // not match codable model start line
138 | completionHandler(TrickerXError.notFoundCodableModel.asNSError)
139 | return
140 | }
141 |
142 | guard !enumCase.isEmpty else {
143 | // codable keys empty
144 | completionHandler(TrickerXError.codablePropertyEmpty.asNSError)
145 | return
146 | }
147 |
148 |
149 | let startSelection = textRange.start.line
150 | let updateSelectionIndexs: [Int] = Array(startLine...startLine+(enumCase.count + 2))
151 |
152 | let indentSpaces = (invocation.buffer.lines[textRange.start.line] as! String).match(regex: .spaceOrTabIndent).unwrappedOrEmpty.replacingOccurrences(of: "\n", with: "")
153 | let caseIndentSpaces = repeatElement(" ", count: invocation.buffer.indentationWidth).joined()
154 | if isSortingKey {
155 | enumCase = enumCase.sorted(by: {$0.0 < $1.1})
156 | }else {
157 | enumCase = enumCase.reversed()
158 | }
159 | var lines = enumCase.reduce("\(indentSpaces)enum CodingKeys: String, CodingKey {\n") { (result, dict) -> String in
160 | if dict.key != dict.value {
161 | return result.appending("\(indentSpaces)\(caseIndentSpaces)case \(dict.key) = \"\(dict.value)\"\n")
162 | }else {
163 | return result.appending("\(indentSpaces)\(caseIndentSpaces)case \(dict.key)\n")
164 | }
165 | }
166 | lines += "\(indentSpaces)}"
167 | invocation.buffer.lines.insert(lines, at: startSelection)
168 |
169 | let textRanges = updateSelectionIndexs.map { (index) -> XCSourceTextRange in
170 | let sourceTextRange = XCSourceTextRange()
171 | sourceTextRange.start = XCSourceTextPosition(line: index, column: 0)
172 | sourceTextRange.end = XCSourceTextPosition(line: index, column: 0)
173 | return sourceTextRange
174 | }
175 | invocation.buffer.selections.setArray(textRanges)
176 |
177 | completionHandler(nil)
178 | case .readme:
179 | NSWorkspace.shared.open(URL.init(string: Github)!)
180 | completionHandler(nil)
181 | }
182 | }
183 | }
184 |
185 |
186 |
--------------------------------------------------------------------------------
/Codable/SourceEditorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceEditorExtension.swift
3 | // Codable
4 | //
5 | // Created by Lei Wang on 2017/11/24.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XcodeKit
11 |
12 | class SourceEditorExtension: NSObject, XCSourceEditorExtension {
13 |
14 | /*
15 | func extensionDidFinishLaunching() {
16 | // If your extension needs to do any work at launch, implement this optional method.
17 | }
18 | */
19 |
20 | var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
21 | // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter.
22 | let className = SourceEditorCommand.className()
23 | let commaneds: [Command] = [.makeCodingKeys(sorting: false),
24 | .makeCodingKeys(sorting: true),
25 | .readme]
26 |
27 | return commaneds.map({ (command) -> [XCSourceEditorCommandDefinitionKey: Any] in
28 | return [
29 | .nameKey: command.displayName,
30 | .classNameKey: className,
31 | .identifierKey: command.rawValue,
32 | ]
33 | })
34 | }
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Codable/StringExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StringExtension.swift
3 | // Codable
4 | //
5 | // Created by Lei Wang on 2017/12/6.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 |
13 | func match(regex: Regex) -> String? {
14 | return self.match(regex: regex.rawValue)
15 | }
16 |
17 | func match(regex: String) -> String? {
18 | let matchList: [String] = match(regex: regex)
19 | return matchList.first
20 | }
21 |
22 | func match(regex: String) -> [String] {
23 | if isEmpty {
24 | return []
25 | }
26 | do {
27 | let regex = try NSRegularExpression(pattern: regex, options: [])
28 | let results = regex.matches(in: self, options: [], range: NSRange.init(startIndex..., in: self))
29 | return results.map({ (result) -> String in
30 | let range = Range.init(result.range, in: self)
31 | return String(self[range!])
32 | })
33 | }
34 | catch {
35 | return []
36 | }
37 | }
38 |
39 | func snakeCased() -> String? {
40 | let pattern = "([a-z0-9])([A-Z])"
41 |
42 | let regex = try? NSRegularExpression(pattern: pattern, options: [])
43 | let range = NSRange(location: 0, length: count)
44 | return regex?.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: "$1_$2").lowercased()
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Lei Wang
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TrickerX
2 | An Xcode9+ Extension which make [CodingKeys](https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types) automatically.
3 |
4 | 
5 |
6 | ## How to use
7 | 1. Download the installation [package](https://github.com/wleii/TrickerX/tree/master/app) I provide, or you can download project and build it yourself.
8 | 2. Open the App you have installed
9 | 3. Launch Xcode -> Open `Make CodingKey` File -> Editor -> Codable -> Make CodingKeys (PS: If you need, you can bind the shortcut key for this :]
10 |
11 | ## More specific methods of use
12 | TrickerX also support the following way to define keys, e.g.
13 | ```swift
14 | struct CustomKey: Codable {
15 | // TrickerX will parsing the syntax //my_custom_key
16 | private let key: String //my_custom_key
17 | }
18 | ```
19 | result
20 | ```swift
21 | struct CustomKey: Codable {
22 | // TrickerX will parsing the syntax //my_custom_key
23 | private let key: String
24 |
25 | enum CodingKeys: String, Codable {
26 | case key = "my_custom_key"
27 | }
28 | }
29 | ```
30 | ## Contributes
31 |
32 | Welcome :]
33 |
34 | ## License
35 | MIT
36 |
--------------------------------------------------------------------------------
/TrickerX.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 719DB98D1FD817920080CD22 /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719DB98C1FD817920080CD22 /* Command.swift */; };
11 | 719DB98F1FD818730080CD22 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719DB98E1FD818730080CD22 /* StringExtension.swift */; };
12 | 719DB9911FD8187D0080CD22 /* OptionalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719DB9901FD8187D0080CD22 /* OptionalExtension.swift */; };
13 | 71B852911FC834F80084F597 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B852901FC834F80084F597 /* AppDelegate.swift */; };
14 | 71B852931FC834F80084F597 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B852921FC834F80084F597 /* ViewController.swift */; };
15 | 71B852951FC834F80084F597 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 71B852941FC834F80084F597 /* Assets.xcassets */; };
16 | 71B852981FC834F80084F597 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71B852961FC834F80084F597 /* Main.storyboard */; };
17 | 71B852CE1FC83A970084F597 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 71B852A61FC835610084F597 /* Cocoa.framework */; };
18 | 71B852D11FC83A970084F597 /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B852D01FC83A970084F597 /* SourceEditorExtension.swift */; };
19 | 71B852D31FC83A970084F597 /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71B852D21FC83A970084F597 /* SourceEditorCommand.swift */; };
20 | 71B852D81FC83A970084F597 /* Codable.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 71B852CD1FC83A970084F597 /* Codable.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
21 | 71C885841FD8F2800045737E /* TrickerXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71C885831FD8F2800045737E /* TrickerXTests.swift */; };
22 | 71C885901FD8F2F70045737E /* CodableRegexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71C8858E1FD8F2F70045737E /* CodableRegexTests.swift */; };
23 | 71C885911FD8F33B0045737E /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719DB98E1FD818730080CD22 /* StringExtension.swift */; };
24 | 71C885931FD8F34D0045737E /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71C885921FD8F34D0045737E /* Regex.swift */; };
25 | 71C885941FD8F34D0045737E /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71C885921FD8F34D0045737E /* Regex.swift */; };
26 | 71C885951FD912C40045737E /* OptionalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719DB9901FD8187D0080CD22 /* OptionalExtension.swift */; };
27 | /* End PBXBuildFile section */
28 |
29 | /* Begin PBXContainerItemProxy section */
30 | 71B852D61FC83A970084F597 /* PBXContainerItemProxy */ = {
31 | isa = PBXContainerItemProxy;
32 | containerPortal = 71B852851FC834F80084F597 /* Project object */;
33 | proxyType = 1;
34 | remoteGlobalIDString = 71B852CC1FC83A970084F597;
35 | remoteInfo = Codable;
36 | };
37 | 71C885861FD8F2800045737E /* PBXContainerItemProxy */ = {
38 | isa = PBXContainerItemProxy;
39 | containerPortal = 71B852851FC834F80084F597 /* Project object */;
40 | proxyType = 1;
41 | remoteGlobalIDString = 71B8528C1FC834F80084F597;
42 | remoteInfo = TrickerX;
43 | };
44 | /* End PBXContainerItemProxy section */
45 |
46 | /* Begin PBXCopyFilesBuildPhase section */
47 | 71B852B51FC835610084F597 /* Embed App Extensions */ = {
48 | isa = PBXCopyFilesBuildPhase;
49 | buildActionMask = 2147483647;
50 | dstPath = "";
51 | dstSubfolderSpec = 13;
52 | files = (
53 | 71B852D81FC83A970084F597 /* Codable.appex in Embed App Extensions */,
54 | );
55 | name = "Embed App Extensions";
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | /* End PBXCopyFilesBuildPhase section */
59 |
60 | /* Begin PBXFileReference section */
61 | 719DB98C1FD817920080CD22 /* Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = ""; };
62 | 719DB98E1FD818730080CD22 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; };
63 | 719DB9901FD8187D0080CD22 /* OptionalExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalExtension.swift; sourceTree = ""; };
64 | 71B8528D1FC834F80084F597 /* TrickerX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TrickerX.app; sourceTree = BUILT_PRODUCTS_DIR; };
65 | 71B852901FC834F80084F597 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
66 | 71B852921FC834F80084F597 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
67 | 71B852941FC834F80084F597 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
68 | 71B852971FC834F80084F597 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
69 | 71B852991FC834F90084F597 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
70 | 71B8529A1FC834F90084F597 /* TrickerX.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TrickerX.entitlements; sourceTree = ""; };
71 | 71B852A61FC835610084F597 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
72 | 71B852CD1FC83A970084F597 /* Codable.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Codable.appex; sourceTree = BUILT_PRODUCTS_DIR; };
73 | 71B852D01FC83A970084F597 /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; };
74 | 71B852D21FC83A970084F597 /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; };
75 | 71B852D41FC83A970084F597 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
76 | 71B852D51FC83A970084F597 /* Codable.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Codable.entitlements; sourceTree = ""; };
77 | 71C885811FD8F2800045737E /* TrickerXTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TrickerXTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
78 | 71C885831FD8F2800045737E /* TrickerXTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrickerXTests.swift; sourceTree = ""; };
79 | 71C885851FD8F2800045737E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
80 | 71C8858E1FD8F2F70045737E /* CodableRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableRegexTests.swift; sourceTree = ""; };
81 | 71C885921FD8F34D0045737E /* Regex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = ""; };
82 | /* End PBXFileReference section */
83 |
84 | /* Begin PBXFrameworksBuildPhase section */
85 | 71B8528A1FC834F80084F597 /* Frameworks */ = {
86 | isa = PBXFrameworksBuildPhase;
87 | buildActionMask = 2147483647;
88 | files = (
89 | );
90 | runOnlyForDeploymentPostprocessing = 0;
91 | };
92 | 71B852CA1FC83A970084F597 /* Frameworks */ = {
93 | isa = PBXFrameworksBuildPhase;
94 | buildActionMask = 2147483647;
95 | files = (
96 | 71B852CE1FC83A970084F597 /* Cocoa.framework in Frameworks */,
97 | );
98 | runOnlyForDeploymentPostprocessing = 0;
99 | };
100 | 71C8857E1FD8F2800045737E /* Frameworks */ = {
101 | isa = PBXFrameworksBuildPhase;
102 | buildActionMask = 2147483647;
103 | files = (
104 | );
105 | runOnlyForDeploymentPostprocessing = 0;
106 | };
107 | /* End PBXFrameworksBuildPhase section */
108 |
109 | /* Begin PBXGroup section */
110 | 71B852841FC834F80084F597 = {
111 | isa = PBXGroup;
112 | children = (
113 | 71B8528F1FC834F80084F597 /* TrickerX */,
114 | 71B852CF1FC83A970084F597 /* Codable */,
115 | 71C885821FD8F2800045737E /* TrickerXTests */,
116 | 71B852A51FC835610084F597 /* Frameworks */,
117 | 71B8528E1FC834F80084F597 /* Products */,
118 | );
119 | sourceTree = "";
120 | };
121 | 71B8528E1FC834F80084F597 /* Products */ = {
122 | isa = PBXGroup;
123 | children = (
124 | 71B8528D1FC834F80084F597 /* TrickerX.app */,
125 | 71B852CD1FC83A970084F597 /* Codable.appex */,
126 | 71C885811FD8F2800045737E /* TrickerXTests.xctest */,
127 | );
128 | name = Products;
129 | sourceTree = "";
130 | };
131 | 71B8528F1FC834F80084F597 /* TrickerX */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 71B852901FC834F80084F597 /* AppDelegate.swift */,
135 | 71B852921FC834F80084F597 /* ViewController.swift */,
136 | 71B852941FC834F80084F597 /* Assets.xcassets */,
137 | 71B852961FC834F80084F597 /* Main.storyboard */,
138 | 71B852991FC834F90084F597 /* Info.plist */,
139 | 71B8529A1FC834F90084F597 /* TrickerX.entitlements */,
140 | );
141 | path = TrickerX;
142 | sourceTree = "";
143 | };
144 | 71B852A51FC835610084F597 /* Frameworks */ = {
145 | isa = PBXGroup;
146 | children = (
147 | 71B852A61FC835610084F597 /* Cocoa.framework */,
148 | );
149 | name = Frameworks;
150 | sourceTree = "";
151 | };
152 | 71B852CF1FC83A970084F597 /* Codable */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 71B852D01FC83A970084F597 /* SourceEditorExtension.swift */,
156 | 71B852D21FC83A970084F597 /* SourceEditorCommand.swift */,
157 | 719DB98C1FD817920080CD22 /* Command.swift */,
158 | 719DB98E1FD818730080CD22 /* StringExtension.swift */,
159 | 719DB9901FD8187D0080CD22 /* OptionalExtension.swift */,
160 | 71C885921FD8F34D0045737E /* Regex.swift */,
161 | 71B852D41FC83A970084F597 /* Info.plist */,
162 | 71B852D51FC83A970084F597 /* Codable.entitlements */,
163 | );
164 | path = Codable;
165 | sourceTree = "";
166 | };
167 | 71C885821FD8F2800045737E /* TrickerXTests */ = {
168 | isa = PBXGroup;
169 | children = (
170 | 71C885831FD8F2800045737E /* TrickerXTests.swift */,
171 | 71C8858E1FD8F2F70045737E /* CodableRegexTests.swift */,
172 | 71C885851FD8F2800045737E /* Info.plist */,
173 | );
174 | path = TrickerXTests;
175 | sourceTree = "";
176 | };
177 | /* End PBXGroup section */
178 |
179 | /* Begin PBXNativeTarget section */
180 | 71B8528C1FC834F80084F597 /* TrickerX */ = {
181 | isa = PBXNativeTarget;
182 | buildConfigurationList = 71B8529D1FC834F90084F597 /* Build configuration list for PBXNativeTarget "TrickerX" */;
183 | buildPhases = (
184 | 71B852891FC834F80084F597 /* Sources */,
185 | 71B8528A1FC834F80084F597 /* Frameworks */,
186 | 71B8528B1FC834F80084F597 /* Resources */,
187 | 71B852B51FC835610084F597 /* Embed App Extensions */,
188 | );
189 | buildRules = (
190 | );
191 | dependencies = (
192 | 71B852D71FC83A970084F597 /* PBXTargetDependency */,
193 | );
194 | name = TrickerX;
195 | productName = TrickerX;
196 | productReference = 71B8528D1FC834F80084F597 /* TrickerX.app */;
197 | productType = "com.apple.product-type.application";
198 | };
199 | 71B852CC1FC83A970084F597 /* Codable */ = {
200 | isa = PBXNativeTarget;
201 | buildConfigurationList = 71B852D91FC83A970084F597 /* Build configuration list for PBXNativeTarget "Codable" */;
202 | buildPhases = (
203 | 71B852C91FC83A970084F597 /* Sources */,
204 | 71B852CA1FC83A970084F597 /* Frameworks */,
205 | 71B852CB1FC83A970084F597 /* Resources */,
206 | );
207 | buildRules = (
208 | );
209 | dependencies = (
210 | );
211 | name = Codable;
212 | productName = Codable;
213 | productReference = 71B852CD1FC83A970084F597 /* Codable.appex */;
214 | productType = "com.apple.product-type.xcode-extension";
215 | };
216 | 71C885801FD8F2800045737E /* TrickerXTests */ = {
217 | isa = PBXNativeTarget;
218 | buildConfigurationList = 71C885881FD8F2800045737E /* Build configuration list for PBXNativeTarget "TrickerXTests" */;
219 | buildPhases = (
220 | 71C8857D1FD8F2800045737E /* Sources */,
221 | 71C8857E1FD8F2800045737E /* Frameworks */,
222 | 71C8857F1FD8F2800045737E /* Resources */,
223 | );
224 | buildRules = (
225 | );
226 | dependencies = (
227 | 71C885871FD8F2800045737E /* PBXTargetDependency */,
228 | );
229 | name = TrickerXTests;
230 | productName = TrickerXTests;
231 | productReference = 71C885811FD8F2800045737E /* TrickerXTests.xctest */;
232 | productType = "com.apple.product-type.bundle.unit-test";
233 | };
234 | /* End PBXNativeTarget section */
235 |
236 | /* Begin PBXProject section */
237 | 71B852851FC834F80084F597 /* Project object */ = {
238 | isa = PBXProject;
239 | attributes = {
240 | LastSwiftUpdateCheck = 0910;
241 | LastUpgradeCheck = 0930;
242 | ORGANIZATIONNAME = "Lei Wang";
243 | TargetAttributes = {
244 | 71B8528C1FC834F80084F597 = {
245 | CreatedOnToolsVersion = 9.1;
246 | ProvisioningStyle = Automatic;
247 | };
248 | 71B852CC1FC83A970084F597 = {
249 | CreatedOnToolsVersion = 9.1;
250 | ProvisioningStyle = Automatic;
251 | };
252 | 71C885801FD8F2800045737E = {
253 | CreatedOnToolsVersion = 9.1;
254 | ProvisioningStyle = Automatic;
255 | TestTargetID = 71B8528C1FC834F80084F597;
256 | };
257 | };
258 | };
259 | buildConfigurationList = 71B852881FC834F80084F597 /* Build configuration list for PBXProject "TrickerX" */;
260 | compatibilityVersion = "Xcode 8.0";
261 | developmentRegion = en;
262 | hasScannedForEncodings = 0;
263 | knownRegions = (
264 | en,
265 | Base,
266 | );
267 | mainGroup = 71B852841FC834F80084F597;
268 | productRefGroup = 71B8528E1FC834F80084F597 /* Products */;
269 | projectDirPath = "";
270 | projectRoot = "";
271 | targets = (
272 | 71B8528C1FC834F80084F597 /* TrickerX */,
273 | 71B852CC1FC83A970084F597 /* Codable */,
274 | 71C885801FD8F2800045737E /* TrickerXTests */,
275 | );
276 | };
277 | /* End PBXProject section */
278 |
279 | /* Begin PBXResourcesBuildPhase section */
280 | 71B8528B1FC834F80084F597 /* Resources */ = {
281 | isa = PBXResourcesBuildPhase;
282 | buildActionMask = 2147483647;
283 | files = (
284 | 71B852951FC834F80084F597 /* Assets.xcassets in Resources */,
285 | 71B852981FC834F80084F597 /* Main.storyboard in Resources */,
286 | );
287 | runOnlyForDeploymentPostprocessing = 0;
288 | };
289 | 71B852CB1FC83A970084F597 /* Resources */ = {
290 | isa = PBXResourcesBuildPhase;
291 | buildActionMask = 2147483647;
292 | files = (
293 | );
294 | runOnlyForDeploymentPostprocessing = 0;
295 | };
296 | 71C8857F1FD8F2800045737E /* Resources */ = {
297 | isa = PBXResourcesBuildPhase;
298 | buildActionMask = 2147483647;
299 | files = (
300 | );
301 | runOnlyForDeploymentPostprocessing = 0;
302 | };
303 | /* End PBXResourcesBuildPhase section */
304 |
305 | /* Begin PBXSourcesBuildPhase section */
306 | 71B852891FC834F80084F597 /* Sources */ = {
307 | isa = PBXSourcesBuildPhase;
308 | buildActionMask = 2147483647;
309 | files = (
310 | 71B852931FC834F80084F597 /* ViewController.swift in Sources */,
311 | 71B852911FC834F80084F597 /* AppDelegate.swift in Sources */,
312 | );
313 | runOnlyForDeploymentPostprocessing = 0;
314 | };
315 | 71B852C91FC83A970084F597 /* Sources */ = {
316 | isa = PBXSourcesBuildPhase;
317 | buildActionMask = 2147483647;
318 | files = (
319 | 719DB9911FD8187D0080CD22 /* OptionalExtension.swift in Sources */,
320 | 719DB98F1FD818730080CD22 /* StringExtension.swift in Sources */,
321 | 71B852D11FC83A970084F597 /* SourceEditorExtension.swift in Sources */,
322 | 71C885931FD8F34D0045737E /* Regex.swift in Sources */,
323 | 71B852D31FC83A970084F597 /* SourceEditorCommand.swift in Sources */,
324 | 719DB98D1FD817920080CD22 /* Command.swift in Sources */,
325 | );
326 | runOnlyForDeploymentPostprocessing = 0;
327 | };
328 | 71C8857D1FD8F2800045737E /* Sources */ = {
329 | isa = PBXSourcesBuildPhase;
330 | buildActionMask = 2147483647;
331 | files = (
332 | 71C885951FD912C40045737E /* OptionalExtension.swift in Sources */,
333 | 71C885901FD8F2F70045737E /* CodableRegexTests.swift in Sources */,
334 | 71C885941FD8F34D0045737E /* Regex.swift in Sources */,
335 | 71C885841FD8F2800045737E /* TrickerXTests.swift in Sources */,
336 | 71C885911FD8F33B0045737E /* StringExtension.swift in Sources */,
337 | );
338 | runOnlyForDeploymentPostprocessing = 0;
339 | };
340 | /* End PBXSourcesBuildPhase section */
341 |
342 | /* Begin PBXTargetDependency section */
343 | 71B852D71FC83A970084F597 /* PBXTargetDependency */ = {
344 | isa = PBXTargetDependency;
345 | target = 71B852CC1FC83A970084F597 /* Codable */;
346 | targetProxy = 71B852D61FC83A970084F597 /* PBXContainerItemProxy */;
347 | };
348 | 71C885871FD8F2800045737E /* PBXTargetDependency */ = {
349 | isa = PBXTargetDependency;
350 | target = 71B8528C1FC834F80084F597 /* TrickerX */;
351 | targetProxy = 71C885861FD8F2800045737E /* PBXContainerItemProxy */;
352 | };
353 | /* End PBXTargetDependency section */
354 |
355 | /* Begin PBXVariantGroup section */
356 | 71B852961FC834F80084F597 /* Main.storyboard */ = {
357 | isa = PBXVariantGroup;
358 | children = (
359 | 71B852971FC834F80084F597 /* Base */,
360 | );
361 | name = Main.storyboard;
362 | sourceTree = "";
363 | };
364 | /* End PBXVariantGroup section */
365 |
366 | /* Begin XCBuildConfiguration section */
367 | 71B8529B1FC834F90084F597 /* Debug */ = {
368 | isa = XCBuildConfiguration;
369 | buildSettings = {
370 | ALWAYS_SEARCH_USER_PATHS = NO;
371 | CLANG_ANALYZER_NONNULL = YES;
372 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
373 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
374 | CLANG_CXX_LIBRARY = "libc++";
375 | CLANG_ENABLE_MODULES = YES;
376 | CLANG_ENABLE_OBJC_ARC = YES;
377 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
378 | CLANG_WARN_BOOL_CONVERSION = YES;
379 | CLANG_WARN_COMMA = YES;
380 | CLANG_WARN_CONSTANT_CONVERSION = YES;
381 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
382 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
383 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
384 | CLANG_WARN_EMPTY_BODY = YES;
385 | CLANG_WARN_ENUM_CONVERSION = YES;
386 | CLANG_WARN_INFINITE_RECURSION = YES;
387 | CLANG_WARN_INT_CONVERSION = YES;
388 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
389 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
390 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
391 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
392 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
393 | CLANG_WARN_STRICT_PROTOTYPES = YES;
394 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
395 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
396 | CLANG_WARN_UNREACHABLE_CODE = YES;
397 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
398 | CODE_SIGN_IDENTITY = "Mac Developer";
399 | COPY_PHASE_STRIP = NO;
400 | DEBUG_INFORMATION_FORMAT = dwarf;
401 | ENABLE_STRICT_OBJC_MSGSEND = YES;
402 | ENABLE_TESTABILITY = YES;
403 | GCC_C_LANGUAGE_STANDARD = gnu11;
404 | GCC_DYNAMIC_NO_PIC = NO;
405 | GCC_NO_COMMON_BLOCKS = YES;
406 | GCC_OPTIMIZATION_LEVEL = 0;
407 | GCC_PREPROCESSOR_DEFINITIONS = (
408 | "DEBUG=1",
409 | "$(inherited)",
410 | );
411 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
412 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
413 | GCC_WARN_UNDECLARED_SELECTOR = YES;
414 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
415 | GCC_WARN_UNUSED_FUNCTION = YES;
416 | GCC_WARN_UNUSED_VARIABLE = YES;
417 | MACOSX_DEPLOYMENT_TARGET = 10.12;
418 | MTL_ENABLE_DEBUG_INFO = YES;
419 | ONLY_ACTIVE_ARCH = YES;
420 | SDKROOT = macosx;
421 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
422 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
423 | };
424 | name = Debug;
425 | };
426 | 71B8529C1FC834F90084F597 /* Release */ = {
427 | isa = XCBuildConfiguration;
428 | buildSettings = {
429 | ALWAYS_SEARCH_USER_PATHS = NO;
430 | CLANG_ANALYZER_NONNULL = YES;
431 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
432 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
433 | CLANG_CXX_LIBRARY = "libc++";
434 | CLANG_ENABLE_MODULES = YES;
435 | CLANG_ENABLE_OBJC_ARC = YES;
436 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
437 | CLANG_WARN_BOOL_CONVERSION = YES;
438 | CLANG_WARN_COMMA = YES;
439 | CLANG_WARN_CONSTANT_CONVERSION = YES;
440 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
441 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
442 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
443 | CLANG_WARN_EMPTY_BODY = YES;
444 | CLANG_WARN_ENUM_CONVERSION = YES;
445 | CLANG_WARN_INFINITE_RECURSION = YES;
446 | CLANG_WARN_INT_CONVERSION = YES;
447 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
448 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
449 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
450 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
451 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
452 | CLANG_WARN_STRICT_PROTOTYPES = YES;
453 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
454 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
455 | CLANG_WARN_UNREACHABLE_CODE = YES;
456 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
457 | CODE_SIGN_IDENTITY = "Mac Developer";
458 | COPY_PHASE_STRIP = NO;
459 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
460 | ENABLE_NS_ASSERTIONS = NO;
461 | ENABLE_STRICT_OBJC_MSGSEND = YES;
462 | GCC_C_LANGUAGE_STANDARD = gnu11;
463 | GCC_NO_COMMON_BLOCKS = YES;
464 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
465 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
466 | GCC_WARN_UNDECLARED_SELECTOR = YES;
467 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
468 | GCC_WARN_UNUSED_FUNCTION = YES;
469 | GCC_WARN_UNUSED_VARIABLE = YES;
470 | MACOSX_DEPLOYMENT_TARGET = 10.12;
471 | MTL_ENABLE_DEBUG_INFO = NO;
472 | SDKROOT = macosx;
473 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
474 | };
475 | name = Release;
476 | };
477 | 71B8529E1FC834F90084F597 /* Debug */ = {
478 | isa = XCBuildConfiguration;
479 | buildSettings = {
480 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
481 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
482 | CODE_SIGN_ENTITLEMENTS = TrickerX/TrickerX.entitlements;
483 | CODE_SIGN_STYLE = Automatic;
484 | COMBINE_HIDPI_IMAGES = YES;
485 | DEVELOPMENT_TEAM = ZRW9N2A955;
486 | INFOPLIST_FILE = TrickerX/Info.plist;
487 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
488 | MACOSX_DEPLOYMENT_TARGET = 10.12;
489 | PRODUCT_BUNDLE_IDENTIFIER = com.rayternet.TrickerX;
490 | PRODUCT_NAME = "$(TARGET_NAME)";
491 | SWIFT_VERSION = 4.0;
492 | };
493 | name = Debug;
494 | };
495 | 71B8529F1FC834F90084F597 /* Release */ = {
496 | isa = XCBuildConfiguration;
497 | buildSettings = {
498 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
499 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
500 | CODE_SIGN_ENTITLEMENTS = TrickerX/TrickerX.entitlements;
501 | CODE_SIGN_STYLE = Automatic;
502 | COMBINE_HIDPI_IMAGES = YES;
503 | DEVELOPMENT_TEAM = ZRW9N2A955;
504 | INFOPLIST_FILE = TrickerX/Info.plist;
505 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
506 | MACOSX_DEPLOYMENT_TARGET = 10.12;
507 | PRODUCT_BUNDLE_IDENTIFIER = com.rayternet.TrickerX;
508 | PRODUCT_NAME = "$(TARGET_NAME)";
509 | SWIFT_VERSION = 4.0;
510 | };
511 | name = Release;
512 | };
513 | 71B852DA1FC83A970084F597 /* Debug */ = {
514 | isa = XCBuildConfiguration;
515 | buildSettings = {
516 | CODE_SIGN_ENTITLEMENTS = Codable/Codable.entitlements;
517 | CODE_SIGN_STYLE = Automatic;
518 | COMBINE_HIDPI_IMAGES = YES;
519 | DEVELOPMENT_TEAM = ZRW9N2A955;
520 | INFOPLIST_FILE = Codable/Info.plist;
521 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
522 | PRODUCT_BUNDLE_IDENTIFIER = com.rayternet.TrickerX.Codable;
523 | PRODUCT_NAME = "$(TARGET_NAME)";
524 | SKIP_INSTALL = YES;
525 | SWIFT_VERSION = 4.0;
526 | };
527 | name = Debug;
528 | };
529 | 71B852DB1FC83A970084F597 /* Release */ = {
530 | isa = XCBuildConfiguration;
531 | buildSettings = {
532 | CODE_SIGN_ENTITLEMENTS = Codable/Codable.entitlements;
533 | CODE_SIGN_STYLE = Automatic;
534 | COMBINE_HIDPI_IMAGES = YES;
535 | DEVELOPMENT_TEAM = ZRW9N2A955;
536 | INFOPLIST_FILE = Codable/Info.plist;
537 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
538 | PRODUCT_BUNDLE_IDENTIFIER = com.rayternet.TrickerX.Codable;
539 | PRODUCT_NAME = "$(TARGET_NAME)";
540 | SKIP_INSTALL = YES;
541 | SWIFT_VERSION = 4.0;
542 | };
543 | name = Release;
544 | };
545 | 71C885891FD8F2800045737E /* Debug */ = {
546 | isa = XCBuildConfiguration;
547 | buildSettings = {
548 | BUNDLE_LOADER = "$(TEST_HOST)";
549 | CODE_SIGN_STYLE = Automatic;
550 | COMBINE_HIDPI_IMAGES = YES;
551 | DEVELOPMENT_TEAM = ZRW9N2A955;
552 | INFOPLIST_FILE = TrickerXTests/Info.plist;
553 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
554 | PRODUCT_BUNDLE_IDENTIFIER = com.rayternet.TrickerXTests;
555 | PRODUCT_NAME = "$(TARGET_NAME)";
556 | SWIFT_VERSION = 4.0;
557 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TrickerX.app/Contents/MacOS/TrickerX";
558 | };
559 | name = Debug;
560 | };
561 | 71C8858A1FD8F2800045737E /* Release */ = {
562 | isa = XCBuildConfiguration;
563 | buildSettings = {
564 | BUNDLE_LOADER = "$(TEST_HOST)";
565 | CODE_SIGN_STYLE = Automatic;
566 | COMBINE_HIDPI_IMAGES = YES;
567 | DEVELOPMENT_TEAM = ZRW9N2A955;
568 | INFOPLIST_FILE = TrickerXTests/Info.plist;
569 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
570 | PRODUCT_BUNDLE_IDENTIFIER = com.rayternet.TrickerXTests;
571 | PRODUCT_NAME = "$(TARGET_NAME)";
572 | SWIFT_VERSION = 4.0;
573 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TrickerX.app/Contents/MacOS/TrickerX";
574 | };
575 | name = Release;
576 | };
577 | /* End XCBuildConfiguration section */
578 |
579 | /* Begin XCConfigurationList section */
580 | 71B852881FC834F80084F597 /* Build configuration list for PBXProject "TrickerX" */ = {
581 | isa = XCConfigurationList;
582 | buildConfigurations = (
583 | 71B8529B1FC834F90084F597 /* Debug */,
584 | 71B8529C1FC834F90084F597 /* Release */,
585 | );
586 | defaultConfigurationIsVisible = 0;
587 | defaultConfigurationName = Release;
588 | };
589 | 71B8529D1FC834F90084F597 /* Build configuration list for PBXNativeTarget "TrickerX" */ = {
590 | isa = XCConfigurationList;
591 | buildConfigurations = (
592 | 71B8529E1FC834F90084F597 /* Debug */,
593 | 71B8529F1FC834F90084F597 /* Release */,
594 | );
595 | defaultConfigurationIsVisible = 0;
596 | defaultConfigurationName = Release;
597 | };
598 | 71B852D91FC83A970084F597 /* Build configuration list for PBXNativeTarget "Codable" */ = {
599 | isa = XCConfigurationList;
600 | buildConfigurations = (
601 | 71B852DA1FC83A970084F597 /* Debug */,
602 | 71B852DB1FC83A970084F597 /* Release */,
603 | );
604 | defaultConfigurationIsVisible = 0;
605 | defaultConfigurationName = Release;
606 | };
607 | 71C885881FD8F2800045737E /* Build configuration list for PBXNativeTarget "TrickerXTests" */ = {
608 | isa = XCConfigurationList;
609 | buildConfigurations = (
610 | 71C885891FD8F2800045737E /* Debug */,
611 | 71C8858A1FD8F2800045737E /* Release */,
612 | );
613 | defaultConfigurationIsVisible = 0;
614 | defaultConfigurationName = Release;
615 | };
616 | /* End XCConfigurationList section */
617 | };
618 | rootObject = 71B852851FC834F80084F597 /* Project object */;
619 | }
620 |
--------------------------------------------------------------------------------
/TrickerX.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/TrickerX.xcodeproj/xcshareddata/xcschemes/TrickerX.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/TrickerX.xcodeproj/xcuserdata/ray.xcuserdatad/xcschemes/Codable.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
16 |
22 |
23 |
24 |
30 |
36 |
37 |
38 |
39 |
40 |
46 |
47 |
48 |
49 |
55 |
56 |
57 |
58 |
59 |
60 |
72 |
75 |
76 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
95 |
97 |
103 |
104 |
105 |
106 |
108 |
109 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/TrickerX/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // TrickerX
4 | //
5 | // Created by Lei Wang on 2017/11/24.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 |
15 |
16 | func applicationDidFinishLaunching(_ aNotification: Notification) {
17 | // Insert code here to initialize your application
18 |
19 | NSApp.setActivationPolicy(NSApplication.ActivationPolicy.prohibited)
20 | }
21 |
22 | func applicationWillTerminate(_ aNotification: Notification) {
23 | // Insert code here to tear down your application
24 | }
25 |
26 |
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/TrickerX/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 | }
--------------------------------------------------------------------------------
/TrickerX/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
--------------------------------------------------------------------------------
/TrickerX/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 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSApplicationCategoryType
24 | public.app-category.developer-tools
25 | LSMinimumSystemVersion
26 | $(MACOSX_DEPLOYMENT_TARGET)
27 | NSHumanReadableCopyright
28 | Copyright © 2017年 Lei Wang. All rights reserved.
29 | NSMainStoryboardFile
30 | Main
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/TrickerX/TrickerX.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/TrickerX/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // TrickerX
4 | //
5 | // Created by Lei Wang on 2017/11/24.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class ViewController: NSViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | // Do any additional setup after loading the view.
17 | }
18 |
19 | override var representedObject: Any? {
20 | didSet {
21 | // Update the view, if already loaded.
22 | }
23 | }
24 |
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/TrickerXTests/CodableRegexTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodableRegexTests.swift
3 | // TrickerX
4 | //
5 | // Created by Lei Wang on 2017/12/7.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class CodableRegexTests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | super.tearDown()
21 | }
22 |
23 | func testExample() {
24 | // This is an example of a functional test case.
25 | // Use XCTAssert and related functions to verify your tests produce the correct results.
26 | var toggleComments = "// toggle commentes test"
27 | XCTAssertNotNil(toggleComments.match(regex: .toggleComments))
28 | toggleComments = " // toggle commentes test "
29 | XCTAssertNotNil(toggleComments.match(regex: .toggleComments))
30 | toggleComments = "test // toggle commentes test "
31 | XCTAssertNil(toggleComments.match(regex: .toggleComments))
32 |
33 |
34 | var customKeys = "private let customKey: String //my_custom_key"
35 | XCTAssertNotNil(customKeys.match(regex: .customKey))
36 | XCTAssertEqual(customKeys.match(regex: .customKey)?.match(regex: "\\w+").unwrappedOrEmpty, "my_custom_key")
37 |
38 | XCTAssertNotNil(customKeys.match(regex: .codablePropertyLine))
39 | XCTAssertEqual(customKeys.match(regex: .codablePropertyLine)?.match(regex: .codablePropertyName), "customKey")
40 | let splitStrings = customKeys.split(separator: "/")
41 | XCTAssertEqual(splitStrings.first, "private let customKey: String ")
42 |
43 | customKeys = "private let customKey: String //"
44 | XCTAssertNil(customKeys.match(regex: .customKey))
45 |
46 |
47 | }
48 |
49 | func testPerformanceExample() {
50 | // This is an example of a performance test case.
51 | self.measure {
52 | // Put the code you want to measure the time of here.
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/TrickerXTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/TrickerXTests/TrickerXTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TrickerXTests.swift
3 | // TrickerXTests
4 | //
5 | // Created by Lei Wang on 2017/12/7.
6 | // Copyright © 2017年 Lei Wang. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class TrickerXTests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | super.tearDown()
21 | }
22 |
23 | func testExample() {
24 | // This is an example of a functional test case.
25 | // Use XCTAssert and related functions to verify your tests produce the correct results.
26 | }
27 |
28 | func testPerformanceExample() {
29 | // This is an example of a performance test case.
30 | self.measure {
31 | // Put the code you want to measure the time of here.
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/TrickerX.dmg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wleii/TrickerX/7ecee50d8e393a0ccea758fc1688a4db2c1a3c28/app/TrickerX.dmg
--------------------------------------------------------------------------------
/codable.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wleii/TrickerX/7ecee50d8e393a0ccea758fc1688a4db2c1a3c28/codable.gif
--------------------------------------------------------------------------------
/fastlane/Appfile:
--------------------------------------------------------------------------------
1 | app_identifier "com.rayternet.TrickerX" # The bundle identifier of your app
2 | apple_id "w_leii@sina.cn" # Your Apple email address
3 |
4 | team_id "[[DEV_PORTAL_TEAM_ID]]" # Developer Portal Team ID
5 |
6 | # you can even provide different app identifiers, Apple IDs and team names per lane:
7 | # More information: https://docs.fastlane.tools/advanced/#appfile
8 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | # Customize this file, documentation can be found here:
2 | # https://docs.fastlane.tools/actions/
3 | # All available actions: https://docs.fastlane.tools/actions
4 | # can also be listed using the `fastlane actions` command
5 |
6 | # Change the syntax highlighting to Ruby
7 | # All lines starting with a # are ignored when running `fastlane`
8 |
9 | # If you want to automatically update fastlane if a new version is available:
10 | # update_fastlane
11 |
12 | # This is the minimum version number required.
13 | # Update this, if you use features of a newer version
14 | fastlane_version "2.68.0"
15 |
16 | default_platform :ios
17 |
18 | platform :ios do
19 | before_all do
20 | # ENV["SLACK_URL"] = "https://hooks.slack.com/services/..."
21 | # cocoapods
22 | # carthage
23 | end
24 |
25 | desc "Runs all the tests"
26 | lane :test do
27 | run_tests
28 | end
29 |
30 | desc "release new dmg"
31 | lane :dmg do
32 | build_app(
33 | scheme: "TrickerX",
34 | clean: true,
35 | output_directory: "./app",
36 | output_name: "TrickerX",
37 | export_method: "developer-id",
38 | archive_path: "./app/TrickerX"
39 | )
40 |
41 | sh("./make_dmg")
42 | end
43 |
44 | # You can define as many lanes as you want
45 |
46 | after_all do |lane|
47 | # This block is called, only if the executed lane was successful
48 |
49 | # slack(
50 | # message: "Successfully deployed new App Update."
51 | # )
52 | end
53 |
54 | error do |lane, exception|
55 | # slack(
56 | # message: exception.message,
57 | # success: false
58 | # )
59 | end
60 | end
61 |
62 |
63 | # More information about multiple platforms in fastlane: https://docs.fastlane.tools/advanced/#control-configuration-by-lane-and-by-platform
64 | # All available actions: https://docs.fastlane.tools/actions
65 |
66 | # fastlane reports which actions are used. No personal data is recorded.
67 | # Learn more at https://docs.fastlane.tools/#metrics
68 |
--------------------------------------------------------------------------------
/fastlane/README.md:
--------------------------------------------------------------------------------
1 | fastlane documentation
2 | ================
3 | # Installation
4 |
5 | Make sure you have the latest version of the Xcode command line tools installed:
6 |
7 | ```
8 | xcode-select --install
9 | ```
10 |
11 | Install _fastlane_ using
12 | ```
13 | [sudo] gem install fastlane -NV
14 | ```
15 | or alternatively using `brew cask install fastlane`
16 |
17 | # Available Actions
18 | ## iOS
19 | ### ios test
20 | ```
21 | fastlane ios test
22 | ```
23 | Runs all the tests
24 | ### ios dmg
25 | ```
26 | fastlane ios dmg
27 | ```
28 | release new dmg
29 |
30 | ----
31 |
32 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run.
33 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools).
34 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
35 |
--------------------------------------------------------------------------------
/fastlane/make_dmg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cd ..
4 |
5 | projectPath=$(pwd)
6 | appFilePath=${projectPath}/app/TrickerX.app
7 |
8 | if [ -d "$appFilePath" ]
9 | then
10 | echo "success find $appFilePath"
11 | else
12 | echo "$appFilePath not found."
13 | exit 1
14 | fi
15 |
16 | # clean
17 | rm -rf $projectPath/app/TrickerX.dmg
18 | rm -rf $projectPath/app/Applications
19 | rm -rf $projectPath/app/*.xcarchive
20 | rm -rf $projectPath/app/*.zip
21 |
22 | cd $projectPath/app
23 | ln -s /Applications Applications
24 | cd ..
25 | echo "Link Applications success"
26 |
27 | hdiutil create $projectPath/app/TrickerX.dmg -volname "TrickerX" -srcfolder $projectPath/app
28 |
29 | # clean
30 | rm -rf $projectPath/app/TrickerX.app
31 | rm -rf $projectPath/app/Applications
32 |
--------------------------------------------------------------------------------