├── .gitignore ├── README.md ├── XEBox Extensions ├── Info.plist ├── SourceEditorCommand.swift ├── SourceEditorExtension.swift └── XEBox_Extensions.entitlements ├── XEBox.xcodeproj └── project.pbxproj ├── XEBox ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ └── Main.storyboard ├── Info.plist └── ViewController.swift ├── XEBoxTests ├── Info.plist └── XEBoxTests.swift ├── XEBoxUITests ├── Info.plist └── XEBoxUITests.swift └── images ├── screenshot-NSLocalizedString.gif ├── screenshot-importForMe.gif ├── screenshot-moveUpInBrace.gif └── screenshot-optionalBinding.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | Icon 6 | ._* 7 | .Spotlight-V100 8 | .Trashes 9 | 10 | # Xcode 11 | # 12 | build/ 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | *.xcuserstate 28 | 29 | # CocoaPods 30 | Pods 31 | 32 | # Carthage 33 | Carthage -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XEBox - an Xcode source editor extension toolbox 2 | 3 | [![Platform](https://img.shields.io/badge/xcode-8-blue.svg?style=flat)](https://developer.apple.com/xcode/) 4 | [![Swift 3](https://img.shields.io/badge/Swift-3.0-orange.svg?style=flat)](https://developer.apple.com/swift/) 5 | [![License](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](http://mit-license.org) 6 | [![Twitter](https://img.shields.io/badge/twitter-@robinlu-blue.svg?style=flat)](http://twitter.com/robinlu) 7 | 8 | XEBox is a collection of Xcode source editor extensions I made for swift coding, which including: 9 | * Turn to NSLocalizedString 10 | * Move up into braces 11 | * Turn to optional binding 12 | * Import for me 13 | 14 | ## Turn to NSLocalizedString 15 | Type a quoted string and turn it into the form of: 16 | NSLocalizedString(“string”, comment:”string”) 17 | 18 | 19 | 20 | ## Turn to optional binding 21 | This one turns an “let” assignment into an optional binding. 22 | 23 | 24 | ## Move up into braces 25 | This one moves the selected codes up into the nearest braces. 26 | 27 | 28 | ## Import for me 29 | Type 'import #module#' or just even the module name in a new line and launch the extension, the module will be automatically imported to the head of file and leave you at where you are. 30 | 31 | 32 | 33 | ## How to use 34 | 35 | 1. Download the code 36 | 2. Open the project in Xcode 8.0 or later. 37 | 3. Resolve the code sign issues 38 | 4. Build and run. 39 | 5. You may need to enable the extension from  -> System Preferences -> Extensions -> Xcode Source Editor 40 | 6. You will find the command in the Editor Menu. 41 | 42 | ## Author 43 | [Lu Yibin](http://robin.github.io) 44 | 45 | ## License 46 | LYTabView is available under the MIT license. See the LICENSE file for more info. 47 | -------------------------------------------------------------------------------- /XEBox Extensions/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | XEBox Extensions 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 | XCSourceEditorCommandDefinitions 30 | 31 | 32 | XCSourceEditorCommandClassName 33 | $(PRODUCT_MODULE_NAME).SourceEditorCommand 34 | XCSourceEditorCommandIdentifier 35 | $(PRODUCT_BUNDLE_IDENTIFIER).ImportForMe 36 | XCSourceEditorCommandName 37 | Import For Me 38 | 39 | 40 | XCSourceEditorCommandClassName 41 | $(PRODUCT_MODULE_NAME).SourceEditorCommand 42 | XCSourceEditorCommandIdentifier 43 | $(PRODUCT_BUNDLE_IDENTIFIER).LocalizeString 44 | XCSourceEditorCommandName 45 | Turn to NSLocalizedString 46 | 47 | 48 | XCSourceEditorCommandClassName 49 | $(PRODUCT_MODULE_NAME).SourceEditorCommand 50 | XCSourceEditorCommandIdentifier 51 | $(PRODUCT_BUNDLE_IDENTIFIER).MoveUpIntoBraces 52 | XCSourceEditorCommandName 53 | Move up into braces 54 | 55 | 56 | XCSourceEditorCommandClassName 57 | $(PRODUCT_MODULE_NAME).SourceEditorCommand 58 | XCSourceEditorCommandIdentifier 59 | $(PRODUCT_BUNDLE_IDENTIFIER).UnwrapOptional 60 | XCSourceEditorCommandName 61 | Optional binding 62 | 63 | 64 | XCSourceEditorExtensionPrincipalClass 65 | $(PRODUCT_MODULE_NAME).SourceEditorExtension 66 | 67 | NSExtensionPointIdentifier 68 | com.apple.dt.Xcode.extension.source-editor 69 | 70 | NSHumanReadableCopyright 71 | Copyright © 2016 Lu Yibin. All rights reserved. 72 | 73 | 74 | -------------------------------------------------------------------------------- /XEBox Extensions/SourceEditorCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SourceEditorCommand.swift 3 | // XEBox Extensions 4 | // 5 | // Created by Lu Yibin on 19/10/2016. 6 | // Copyright © 2016 Lu Yibin. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XcodeKit 11 | 12 | class SourceEditorCommand: NSObject, XCSourceEditorCommand { 13 | 14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { 15 | // Implement your command here, invoking the completion handler when done. Pass it nil on success, and an NSError on failure. 16 | guard invocation.buffer.contentUTI == "public.swift-source" else { 17 | completionHandler(nil) 18 | return 19 | } 20 | 21 | switch invocation.commandIdentifier { 22 | case "com.robinlu.XEBox.XEBox-Extensions.ImportForMe": 23 | importForMe(with: invocation) 24 | case "com.robinlu.XEBox.XEBox-Extensions.LocalizeString": 25 | localizingString(with: invocation) 26 | case "com.robinlu.XEBox.XEBox-Extensions.MoveUpIntoBraces": 27 | moveUpIntoBraces(with: invocation) 28 | case "com.robinlu.XEBox.XEBox-Extensions.UnwrapOptional": 29 | unwrapOptional(with: invocation) 30 | default: 31 | fatalError("\(invocation.commandIdentifier) not supported.") 32 | } 33 | 34 | completionHandler(nil) 35 | } 36 | 37 | func importForMe(with invocation: XCSourceEditorCommandInvocation) { 38 | let lastWordRegex = try! NSRegularExpression(pattern: "\\s*([\\w.]+)\\W*$", options: []) 39 | if let range = invocation.buffer.selections[0] as? XCSourceTextRange { 40 | var lastImportLine = 0 41 | let regex = try! NSRegularExpression(pattern: "^\\s*import\\s*\\w", options: []) 42 | for (i, line) in invocation.buffer.lines.enumerated() { 43 | if i == range.start.line { 44 | continue 45 | } 46 | if let buffer = line as? String { 47 | if let result = regex.firstMatch(in: buffer, options: [], range: buffer.fullRange) { 48 | if result.range.location != NSNotFound { 49 | lastImportLine = i 50 | } 51 | } 52 | } 53 | } 54 | 55 | if let currentLine = invocation.buffer.lines[range.start.line] as? String { 56 | if let result = lastWordRegex.firstMatch(in: currentLine, options: [], range: currentLine.fullRange) { 57 | if result.numberOfRanges > 1 { 58 | let wordRange = result.rangeAt(1) 59 | let word = (currentLine as NSString).substring(with: wordRange) 60 | if !word.isEmpty { 61 | invocation.buffer.lines.insert("import \(word)", at: lastImportLine+1) 62 | invocation.buffer.lines.removeObject(at: range.start.line) 63 | } 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | func localizingString(with invocation: XCSourceEditorCommandInvocation) { 71 | let quoteRegex = try! NSRegularExpression(pattern: "([\"])(?:(?=(\\\\?))\\2.)*?\\1", options: []) 72 | if let range = invocation.buffer.selections[0] as? XCSourceTextRange { 73 | if let currentLine = invocation.buffer.lines[range.start.line] as? String { 74 | var nearestResult : NSTextCheckingResult? = nil 75 | for result in quoteRegex.matches(in: currentLine, options: [], range: currentLine.fullRange) { 76 | if result.range.location == NSNotFound { 77 | break; 78 | } 79 | if nearestResult == nil || (DistanceToNSRange(location: range.start.column, range: nearestResult!.range) > DistanceToNSRange(location: range.start.column, range: result.range)) { 80 | nearestResult = result 81 | } 82 | } 83 | if let result = nearestResult { 84 | guard result.range.location != NSNotFound else { 85 | return 86 | } 87 | let quote = (currentLine as NSString).substring(with: result.range) 88 | let newQuote = "NSLocalizedString(\(quote), comment:\(quote))" 89 | let newLine = (currentLine as NSString).replacingOccurrences(of: quote, with: newQuote, options: [], range: result.range) 90 | invocation.buffer.lines.replaceObject(at: range.start.line, with: newLine) 91 | let newStart = XCSourceTextPosition(line: range.start.line, column: result.range.location + newQuote.characters.count) 92 | invocation.buffer.selections[0] = XCSourceTextRange(start: newStart, end: newStart) 93 | } 94 | } 95 | } 96 | } 97 | 98 | func moveUpIntoBraces(with invocation: XCSourceEditorCommandInvocation) { 99 | let endBraceRegex = try! NSRegularExpression(pattern: "\\s*\\}\\s*(//.*)?$", options: []) 100 | if let range = invocation.buffer.selections[0] as? XCSourceTextRange { 101 | let selectedRange = NSRange(location: range.start.line, length: range.end.line - range.start.line+1) 102 | let prefix : String = { 103 | if invocation.buffer.usesTabsForIndentation { 104 | return "\t" 105 | } else { 106 | return String(repeating: " ", count: invocation.buffer.indentationWidth) 107 | } 108 | }() 109 | let selectedLines = invocation.buffer.lines.subarray(with: selectedRange).map({ (line) -> String in 110 | return "\(prefix)\(line)" 111 | }) 112 | invocation.buffer.lines.removeObjects(in: selectedRange) 113 | for i in (0..\n","\(indent)}"]) 145 | let start = XCSourceTextPosition(line: range.start.line, column: newLine.characters.count - 2) 146 | let newSelection = XCSourceTextRange(start: start, end: start) 147 | invocation.buffer.selections.replaceObject(at: 0, with: newSelection) 148 | } 149 | } 150 | } 151 | } 152 | } 153 | 154 | func DistanceToNSRange(location:Int, range:NSRange) -> Int { 155 | return min(abs(location - range.location), abs(location - (range.location + range.length))); 156 | } 157 | 158 | extension String { 159 | var fullRange: NSRange { 160 | return NSRange(location: 0, length: characters.count) 161 | } 162 | 163 | func positionOfFirstNonSpace() -> Int? { 164 | let nonSpaceRegex = try! NSRegularExpression(pattern: "\\S", options: []) 165 | if let result = nonSpaceRegex.firstMatch(in: self, options: [], range: self.fullRange) { 166 | guard result.range.location != NSNotFound else { 167 | return nil 168 | } 169 | return result.range.location 170 | } 171 | return nil 172 | } 173 | 174 | func index(of position:Int) -> String.Index { 175 | return self.index(self.startIndex, offsetBy: position) 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /XEBox Extensions/SourceEditorExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SourceEditorExtension.swift 3 | // XEBox Extensions 4 | // 5 | // Created by Lu Yibin on 19/10/2016. 6 | // Copyright © 2016 Lu Yibin. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XcodeKit 11 | 12 | class SourceEditorExtension: NSObject, XCSourceEditorExtension { 13 | 14 | func extensionDidFinishLaunching() { 15 | // If your extension needs to do any work at launch, implement this optional method. 16 | } 17 | 18 | /* 19 | var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] { 20 | // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter. 21 | return [] 22 | } 23 | */ 24 | 25 | } 26 | -------------------------------------------------------------------------------- /XEBox Extensions/XEBox_Extensions.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /XEBox.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | AE66B9D61DB758D0007B4EFD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE66B9D51DB758D0007B4EFD /* AppDelegate.swift */; }; 11 | AE66B9D81DB758D0007B4EFD /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE66B9D71DB758D0007B4EFD /* ViewController.swift */; }; 12 | AE66B9DA1DB758D0007B4EFD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AE66B9D91DB758D0007B4EFD /* Assets.xcassets */; }; 13 | AE66B9DD1DB758D0007B4EFD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AE66B9DB1DB758D0007B4EFD /* Main.storyboard */; }; 14 | AE66B9E81DB758D0007B4EFD /* XEBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE66B9E71DB758D0007B4EFD /* XEBoxTests.swift */; }; 15 | AE66B9F31DB758D0007B4EFD /* XEBoxUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE66B9F21DB758D0007B4EFD /* XEBoxUITests.swift */; }; 16 | AE66BA071DB75920007B4EFD /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AE66BA061DB75920007B4EFD /* Cocoa.framework */; }; 17 | AE66BA0C1DB75920007B4EFD /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE66BA0B1DB75920007B4EFD /* SourceEditorExtension.swift */; }; 18 | AE66BA0E1DB75920007B4EFD /* SourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE66BA0D1DB75920007B4EFD /* SourceEditorCommand.swift */; }; 19 | AE66BA121DB75920007B4EFD /* XEBox Extensions.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = AE66BA041DB75920007B4EFD /* XEBox Extensions.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | AE66B9E41DB758D0007B4EFD /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = AE66B9CA1DB758D0007B4EFD /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = AE66B9D11DB758D0007B4EFD; 28 | remoteInfo = XEBox; 29 | }; 30 | AE66B9EF1DB758D0007B4EFD /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = AE66B9CA1DB758D0007B4EFD /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = AE66B9D11DB758D0007B4EFD; 35 | remoteInfo = XEBox; 36 | }; 37 | AE66BA101DB75920007B4EFD /* PBXContainerItemProxy */ = { 38 | isa = PBXContainerItemProxy; 39 | containerPortal = AE66B9CA1DB758D0007B4EFD /* Project object */; 40 | proxyType = 1; 41 | remoteGlobalIDString = AE66BA031DB75920007B4EFD; 42 | remoteInfo = "XEBox Extensions"; 43 | }; 44 | /* End PBXContainerItemProxy section */ 45 | 46 | /* Begin PBXCopyFilesBuildPhase section */ 47 | AE66BA161DB75920007B4EFD /* Embed App Extensions */ = { 48 | isa = PBXCopyFilesBuildPhase; 49 | buildActionMask = 2147483647; 50 | dstPath = ""; 51 | dstSubfolderSpec = 13; 52 | files = ( 53 | AE66BA121DB75920007B4EFD /* XEBox Extensions.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 | AE66B9D21DB758D0007B4EFD /* XEBox.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XEBox.app; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | AE66B9D51DB758D0007B4EFD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 63 | AE66B9D71DB758D0007B4EFD /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 64 | AE66B9D91DB758D0007B4EFD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 65 | AE66B9DC1DB758D0007B4EFD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 66 | AE66B9DE1DB758D0007B4EFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 67 | AE66B9E31DB758D0007B4EFD /* XEBoxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XEBoxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | AE66B9E71DB758D0007B4EFD /* XEBoxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XEBoxTests.swift; sourceTree = ""; }; 69 | AE66B9E91DB758D0007B4EFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | AE66B9EE1DB758D0007B4EFD /* XEBoxUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XEBoxUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | AE66B9F21DB758D0007B4EFD /* XEBoxUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XEBoxUITests.swift; sourceTree = ""; }; 72 | AE66B9F41DB758D0007B4EFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 73 | AE66BA041DB75920007B4EFD /* XEBox Extensions.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "XEBox Extensions.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 74 | AE66BA061DB75920007B4EFD /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 75 | AE66BA0A1DB75920007B4EFD /* XEBox_Extensions.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = XEBox_Extensions.entitlements; sourceTree = ""; }; 76 | AE66BA0B1DB75920007B4EFD /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; 77 | AE66BA0D1DB75920007B4EFD /* SourceEditorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorCommand.swift; sourceTree = ""; }; 78 | AE66BA0F1DB75920007B4EFD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | AE66B9CF1DB758D0007B4EFD /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | AE66B9E01DB758D0007B4EFD /* Frameworks */ = { 90 | isa = PBXFrameworksBuildPhase; 91 | buildActionMask = 2147483647; 92 | files = ( 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | AE66B9EB1DB758D0007B4EFD /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | AE66BA011DB75920007B4EFD /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | AE66BA071DB75920007B4EFD /* Cocoa.framework in Frameworks */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | /* End PBXFrameworksBuildPhase section */ 112 | 113 | /* Begin PBXGroup section */ 114 | AE66B9C91DB758D0007B4EFD = { 115 | isa = PBXGroup; 116 | children = ( 117 | AE66B9D41DB758D0007B4EFD /* XEBox */, 118 | AE66B9E61DB758D0007B4EFD /* XEBoxTests */, 119 | AE66B9F11DB758D0007B4EFD /* XEBoxUITests */, 120 | AE66BA081DB75920007B4EFD /* XEBox Extensions */, 121 | AE66BA051DB75920007B4EFD /* Frameworks */, 122 | AE66B9D31DB758D0007B4EFD /* Products */, 123 | ); 124 | sourceTree = ""; 125 | }; 126 | AE66B9D31DB758D0007B4EFD /* Products */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | AE66B9D21DB758D0007B4EFD /* XEBox.app */, 130 | AE66B9E31DB758D0007B4EFD /* XEBoxTests.xctest */, 131 | AE66B9EE1DB758D0007B4EFD /* XEBoxUITests.xctest */, 132 | AE66BA041DB75920007B4EFD /* XEBox Extensions.appex */, 133 | ); 134 | name = Products; 135 | sourceTree = ""; 136 | }; 137 | AE66B9D41DB758D0007B4EFD /* XEBox */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | AE66B9D51DB758D0007B4EFD /* AppDelegate.swift */, 141 | AE66B9D71DB758D0007B4EFD /* ViewController.swift */, 142 | AE66B9D91DB758D0007B4EFD /* Assets.xcassets */, 143 | AE66B9DB1DB758D0007B4EFD /* Main.storyboard */, 144 | AE66B9DE1DB758D0007B4EFD /* Info.plist */, 145 | ); 146 | path = XEBox; 147 | sourceTree = ""; 148 | }; 149 | AE66B9E61DB758D0007B4EFD /* XEBoxTests */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | AE66B9E71DB758D0007B4EFD /* XEBoxTests.swift */, 153 | AE66B9E91DB758D0007B4EFD /* Info.plist */, 154 | ); 155 | path = XEBoxTests; 156 | sourceTree = ""; 157 | }; 158 | AE66B9F11DB758D0007B4EFD /* XEBoxUITests */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | AE66B9F21DB758D0007B4EFD /* XEBoxUITests.swift */, 162 | AE66B9F41DB758D0007B4EFD /* Info.plist */, 163 | ); 164 | path = XEBoxUITests; 165 | sourceTree = ""; 166 | }; 167 | AE66BA051DB75920007B4EFD /* Frameworks */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | AE66BA061DB75920007B4EFD /* Cocoa.framework */, 171 | ); 172 | name = Frameworks; 173 | sourceTree = ""; 174 | }; 175 | AE66BA081DB75920007B4EFD /* XEBox Extensions */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | AE66BA0B1DB75920007B4EFD /* SourceEditorExtension.swift */, 179 | AE66BA0D1DB75920007B4EFD /* SourceEditorCommand.swift */, 180 | AE66BA0F1DB75920007B4EFD /* Info.plist */, 181 | AE66BA091DB75920007B4EFD /* Supporting Files */, 182 | ); 183 | path = "XEBox Extensions"; 184 | sourceTree = ""; 185 | }; 186 | AE66BA091DB75920007B4EFD /* Supporting Files */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | AE66BA0A1DB75920007B4EFD /* XEBox_Extensions.entitlements */, 190 | ); 191 | name = "Supporting Files"; 192 | sourceTree = ""; 193 | }; 194 | /* End PBXGroup section */ 195 | 196 | /* Begin PBXNativeTarget section */ 197 | AE66B9D11DB758D0007B4EFD /* XEBox */ = { 198 | isa = PBXNativeTarget; 199 | buildConfigurationList = AE66B9F71DB758D0007B4EFD /* Build configuration list for PBXNativeTarget "XEBox" */; 200 | buildPhases = ( 201 | AE66B9CE1DB758D0007B4EFD /* Sources */, 202 | AE66B9CF1DB758D0007B4EFD /* Frameworks */, 203 | AE66B9D01DB758D0007B4EFD /* Resources */, 204 | AE66BA161DB75920007B4EFD /* Embed App Extensions */, 205 | ); 206 | buildRules = ( 207 | ); 208 | dependencies = ( 209 | AE66BA111DB75920007B4EFD /* PBXTargetDependency */, 210 | ); 211 | name = XEBox; 212 | productName = XEBox; 213 | productReference = AE66B9D21DB758D0007B4EFD /* XEBox.app */; 214 | productType = "com.apple.product-type.application"; 215 | }; 216 | AE66B9E21DB758D0007B4EFD /* XEBoxTests */ = { 217 | isa = PBXNativeTarget; 218 | buildConfigurationList = AE66B9FA1DB758D0007B4EFD /* Build configuration list for PBXNativeTarget "XEBoxTests" */; 219 | buildPhases = ( 220 | AE66B9DF1DB758D0007B4EFD /* Sources */, 221 | AE66B9E01DB758D0007B4EFD /* Frameworks */, 222 | AE66B9E11DB758D0007B4EFD /* Resources */, 223 | ); 224 | buildRules = ( 225 | ); 226 | dependencies = ( 227 | AE66B9E51DB758D0007B4EFD /* PBXTargetDependency */, 228 | ); 229 | name = XEBoxTests; 230 | productName = XEBoxTests; 231 | productReference = AE66B9E31DB758D0007B4EFD /* XEBoxTests.xctest */; 232 | productType = "com.apple.product-type.bundle.unit-test"; 233 | }; 234 | AE66B9ED1DB758D0007B4EFD /* XEBoxUITests */ = { 235 | isa = PBXNativeTarget; 236 | buildConfigurationList = AE66B9FD1DB758D0007B4EFD /* Build configuration list for PBXNativeTarget "XEBoxUITests" */; 237 | buildPhases = ( 238 | AE66B9EA1DB758D0007B4EFD /* Sources */, 239 | AE66B9EB1DB758D0007B4EFD /* Frameworks */, 240 | AE66B9EC1DB758D0007B4EFD /* Resources */, 241 | ); 242 | buildRules = ( 243 | ); 244 | dependencies = ( 245 | AE66B9F01DB758D0007B4EFD /* PBXTargetDependency */, 246 | ); 247 | name = XEBoxUITests; 248 | productName = XEBoxUITests; 249 | productReference = AE66B9EE1DB758D0007B4EFD /* XEBoxUITests.xctest */; 250 | productType = "com.apple.product-type.bundle.ui-testing"; 251 | }; 252 | AE66BA031DB75920007B4EFD /* XEBox Extensions */ = { 253 | isa = PBXNativeTarget; 254 | buildConfigurationList = AE66BA131DB75920007B4EFD /* Build configuration list for PBXNativeTarget "XEBox Extensions" */; 255 | buildPhases = ( 256 | AE66BA001DB75920007B4EFD /* Sources */, 257 | AE66BA011DB75920007B4EFD /* Frameworks */, 258 | AE66BA021DB75920007B4EFD /* Resources */, 259 | ); 260 | buildRules = ( 261 | ); 262 | dependencies = ( 263 | ); 264 | name = "XEBox Extensions"; 265 | productName = "XEBox Extensions"; 266 | productReference = AE66BA041DB75920007B4EFD /* XEBox Extensions.appex */; 267 | productType = "com.apple.product-type.xcode-extension"; 268 | }; 269 | /* End PBXNativeTarget section */ 270 | 271 | /* Begin PBXProject section */ 272 | AE66B9CA1DB758D0007B4EFD /* Project object */ = { 273 | isa = PBXProject; 274 | attributes = { 275 | LastSwiftUpdateCheck = 0800; 276 | LastUpgradeCheck = 0800; 277 | ORGANIZATIONNAME = "Lu Yibin"; 278 | TargetAttributes = { 279 | AE66B9D11DB758D0007B4EFD = { 280 | CreatedOnToolsVersion = 8.0; 281 | DevelopmentTeam = YMZ2R5RGSC; 282 | ProvisioningStyle = Automatic; 283 | }; 284 | AE66B9E21DB758D0007B4EFD = { 285 | CreatedOnToolsVersion = 8.0; 286 | DevelopmentTeam = YMZ2R5RGSC; 287 | ProvisioningStyle = Automatic; 288 | TestTargetID = AE66B9D11DB758D0007B4EFD; 289 | }; 290 | AE66B9ED1DB758D0007B4EFD = { 291 | CreatedOnToolsVersion = 8.0; 292 | DevelopmentTeam = YMZ2R5RGSC; 293 | ProvisioningStyle = Automatic; 294 | TestTargetID = AE66B9D11DB758D0007B4EFD; 295 | }; 296 | AE66BA031DB75920007B4EFD = { 297 | CreatedOnToolsVersion = 8.0; 298 | DevelopmentTeam = YMZ2R5RGSC; 299 | ProvisioningStyle = Automatic; 300 | }; 301 | }; 302 | }; 303 | buildConfigurationList = AE66B9CD1DB758D0007B4EFD /* Build configuration list for PBXProject "XEBox" */; 304 | compatibilityVersion = "Xcode 3.2"; 305 | developmentRegion = English; 306 | hasScannedForEncodings = 0; 307 | knownRegions = ( 308 | en, 309 | Base, 310 | ); 311 | mainGroup = AE66B9C91DB758D0007B4EFD; 312 | productRefGroup = AE66B9D31DB758D0007B4EFD /* Products */; 313 | projectDirPath = ""; 314 | projectRoot = ""; 315 | targets = ( 316 | AE66B9D11DB758D0007B4EFD /* XEBox */, 317 | AE66B9E21DB758D0007B4EFD /* XEBoxTests */, 318 | AE66B9ED1DB758D0007B4EFD /* XEBoxUITests */, 319 | AE66BA031DB75920007B4EFD /* XEBox Extensions */, 320 | ); 321 | }; 322 | /* End PBXProject section */ 323 | 324 | /* Begin PBXResourcesBuildPhase section */ 325 | AE66B9D01DB758D0007B4EFD /* Resources */ = { 326 | isa = PBXResourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | AE66B9DA1DB758D0007B4EFD /* Assets.xcassets in Resources */, 330 | AE66B9DD1DB758D0007B4EFD /* Main.storyboard in Resources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | AE66B9E11DB758D0007B4EFD /* Resources */ = { 335 | isa = PBXResourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | ); 339 | runOnlyForDeploymentPostprocessing = 0; 340 | }; 341 | AE66B9EC1DB758D0007B4EFD /* Resources */ = { 342 | isa = PBXResourcesBuildPhase; 343 | buildActionMask = 2147483647; 344 | files = ( 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | }; 348 | AE66BA021DB75920007B4EFD /* Resources */ = { 349 | isa = PBXResourcesBuildPhase; 350 | buildActionMask = 2147483647; 351 | files = ( 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | /* End PBXResourcesBuildPhase section */ 356 | 357 | /* Begin PBXSourcesBuildPhase section */ 358 | AE66B9CE1DB758D0007B4EFD /* Sources */ = { 359 | isa = PBXSourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | AE66B9D81DB758D0007B4EFD /* ViewController.swift in Sources */, 363 | AE66B9D61DB758D0007B4EFD /* AppDelegate.swift in Sources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | AE66B9DF1DB758D0007B4EFD /* Sources */ = { 368 | isa = PBXSourcesBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | AE66B9E81DB758D0007B4EFD /* XEBoxTests.swift in Sources */, 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | }; 375 | AE66B9EA1DB758D0007B4EFD /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | AE66B9F31DB758D0007B4EFD /* XEBoxUITests.swift in Sources */, 380 | ); 381 | runOnlyForDeploymentPostprocessing = 0; 382 | }; 383 | AE66BA001DB75920007B4EFD /* Sources */ = { 384 | isa = PBXSourcesBuildPhase; 385 | buildActionMask = 2147483647; 386 | files = ( 387 | AE66BA0C1DB75920007B4EFD /* SourceEditorExtension.swift in Sources */, 388 | AE66BA0E1DB75920007B4EFD /* SourceEditorCommand.swift in Sources */, 389 | ); 390 | runOnlyForDeploymentPostprocessing = 0; 391 | }; 392 | /* End PBXSourcesBuildPhase section */ 393 | 394 | /* Begin PBXTargetDependency section */ 395 | AE66B9E51DB758D0007B4EFD /* PBXTargetDependency */ = { 396 | isa = PBXTargetDependency; 397 | target = AE66B9D11DB758D0007B4EFD /* XEBox */; 398 | targetProxy = AE66B9E41DB758D0007B4EFD /* PBXContainerItemProxy */; 399 | }; 400 | AE66B9F01DB758D0007B4EFD /* PBXTargetDependency */ = { 401 | isa = PBXTargetDependency; 402 | target = AE66B9D11DB758D0007B4EFD /* XEBox */; 403 | targetProxy = AE66B9EF1DB758D0007B4EFD /* PBXContainerItemProxy */; 404 | }; 405 | AE66BA111DB75920007B4EFD /* PBXTargetDependency */ = { 406 | isa = PBXTargetDependency; 407 | target = AE66BA031DB75920007B4EFD /* XEBox Extensions */; 408 | targetProxy = AE66BA101DB75920007B4EFD /* PBXContainerItemProxy */; 409 | }; 410 | /* End PBXTargetDependency section */ 411 | 412 | /* Begin PBXVariantGroup section */ 413 | AE66B9DB1DB758D0007B4EFD /* Main.storyboard */ = { 414 | isa = PBXVariantGroup; 415 | children = ( 416 | AE66B9DC1DB758D0007B4EFD /* Base */, 417 | ); 418 | name = Main.storyboard; 419 | sourceTree = ""; 420 | }; 421 | /* End PBXVariantGroup section */ 422 | 423 | /* Begin XCBuildConfiguration section */ 424 | AE66B9F51DB758D0007B4EFD /* Debug */ = { 425 | isa = XCBuildConfiguration; 426 | buildSettings = { 427 | ALWAYS_SEARCH_USER_PATHS = NO; 428 | CLANG_ANALYZER_NONNULL = YES; 429 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 430 | CLANG_CXX_LIBRARY = "libc++"; 431 | CLANG_ENABLE_MODULES = YES; 432 | CLANG_ENABLE_OBJC_ARC = YES; 433 | CLANG_WARN_BOOL_CONVERSION = YES; 434 | CLANG_WARN_CONSTANT_CONVERSION = YES; 435 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 436 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 437 | CLANG_WARN_EMPTY_BODY = YES; 438 | CLANG_WARN_ENUM_CONVERSION = YES; 439 | CLANG_WARN_INFINITE_RECURSION = YES; 440 | CLANG_WARN_INT_CONVERSION = YES; 441 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 442 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 443 | CLANG_WARN_UNREACHABLE_CODE = YES; 444 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 445 | CODE_SIGN_IDENTITY = "-"; 446 | COPY_PHASE_STRIP = NO; 447 | DEBUG_INFORMATION_FORMAT = dwarf; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | ENABLE_TESTABILITY = YES; 450 | GCC_C_LANGUAGE_STANDARD = gnu99; 451 | GCC_DYNAMIC_NO_PIC = NO; 452 | GCC_NO_COMMON_BLOCKS = YES; 453 | GCC_OPTIMIZATION_LEVEL = 0; 454 | GCC_PREPROCESSOR_DEFINITIONS = ( 455 | "DEBUG=1", 456 | "$(inherited)", 457 | ); 458 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 459 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 460 | GCC_WARN_UNDECLARED_SELECTOR = YES; 461 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 462 | GCC_WARN_UNUSED_FUNCTION = YES; 463 | GCC_WARN_UNUSED_VARIABLE = YES; 464 | MACOSX_DEPLOYMENT_TARGET = 10.12; 465 | MTL_ENABLE_DEBUG_INFO = YES; 466 | ONLY_ACTIVE_ARCH = YES; 467 | SDKROOT = macosx; 468 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 469 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 470 | }; 471 | name = Debug; 472 | }; 473 | AE66B9F61DB758D0007B4EFD /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | ALWAYS_SEARCH_USER_PATHS = NO; 477 | CLANG_ANALYZER_NONNULL = YES; 478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 479 | CLANG_CXX_LIBRARY = "libc++"; 480 | CLANG_ENABLE_MODULES = YES; 481 | CLANG_ENABLE_OBJC_ARC = YES; 482 | CLANG_WARN_BOOL_CONVERSION = YES; 483 | CLANG_WARN_CONSTANT_CONVERSION = YES; 484 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 485 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 486 | CLANG_WARN_EMPTY_BODY = YES; 487 | CLANG_WARN_ENUM_CONVERSION = YES; 488 | CLANG_WARN_INFINITE_RECURSION = YES; 489 | CLANG_WARN_INT_CONVERSION = YES; 490 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 491 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 492 | CLANG_WARN_UNREACHABLE_CODE = YES; 493 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 494 | CODE_SIGN_IDENTITY = "-"; 495 | COPY_PHASE_STRIP = NO; 496 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 497 | ENABLE_NS_ASSERTIONS = NO; 498 | ENABLE_STRICT_OBJC_MSGSEND = YES; 499 | GCC_C_LANGUAGE_STANDARD = gnu99; 500 | GCC_NO_COMMON_BLOCKS = YES; 501 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 502 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 503 | GCC_WARN_UNDECLARED_SELECTOR = YES; 504 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 505 | GCC_WARN_UNUSED_FUNCTION = YES; 506 | GCC_WARN_UNUSED_VARIABLE = YES; 507 | MACOSX_DEPLOYMENT_TARGET = 10.12; 508 | MTL_ENABLE_DEBUG_INFO = NO; 509 | SDKROOT = macosx; 510 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 511 | }; 512 | name = Release; 513 | }; 514 | AE66B9F81DB758D0007B4EFD /* Debug */ = { 515 | isa = XCBuildConfiguration; 516 | buildSettings = { 517 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 518 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 519 | CODE_SIGN_IDENTITY = "Mac Developer"; 520 | COMBINE_HIDPI_IMAGES = YES; 521 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 522 | INFOPLIST_FILE = XEBox/Info.plist; 523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 524 | PRODUCT_BUNDLE_IDENTIFIER = com.robinlu.XEBox; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | SWIFT_VERSION = 3.0; 527 | }; 528 | name = Debug; 529 | }; 530 | AE66B9F91DB758D0007B4EFD /* Release */ = { 531 | isa = XCBuildConfiguration; 532 | buildSettings = { 533 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 534 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 535 | CODE_SIGN_IDENTITY = "Mac Developer"; 536 | COMBINE_HIDPI_IMAGES = YES; 537 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 538 | INFOPLIST_FILE = XEBox/Info.plist; 539 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 540 | PRODUCT_BUNDLE_IDENTIFIER = com.robinlu.XEBox; 541 | PRODUCT_NAME = "$(TARGET_NAME)"; 542 | SWIFT_VERSION = 3.0; 543 | }; 544 | name = Release; 545 | }; 546 | AE66B9FB1DB758D0007B4EFD /* Debug */ = { 547 | isa = XCBuildConfiguration; 548 | buildSettings = { 549 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 550 | BUNDLE_LOADER = "$(TEST_HOST)"; 551 | COMBINE_HIDPI_IMAGES = YES; 552 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 553 | INFOPLIST_FILE = XEBoxTests/Info.plist; 554 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 555 | PRODUCT_BUNDLE_IDENTIFIER = com.robinlu.XEBoxTests; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | SWIFT_VERSION = 3.0; 558 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XEBox.app/Contents/MacOS/XEBox"; 559 | }; 560 | name = Debug; 561 | }; 562 | AE66B9FC1DB758D0007B4EFD /* Release */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 566 | BUNDLE_LOADER = "$(TEST_HOST)"; 567 | COMBINE_HIDPI_IMAGES = YES; 568 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 569 | INFOPLIST_FILE = XEBoxTests/Info.plist; 570 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 571 | PRODUCT_BUNDLE_IDENTIFIER = com.robinlu.XEBoxTests; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | SWIFT_VERSION = 3.0; 574 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XEBox.app/Contents/MacOS/XEBox"; 575 | }; 576 | name = Release; 577 | }; 578 | AE66B9FE1DB758D0007B4EFD /* Debug */ = { 579 | isa = XCBuildConfiguration; 580 | buildSettings = { 581 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 582 | COMBINE_HIDPI_IMAGES = YES; 583 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 584 | INFOPLIST_FILE = XEBoxUITests/Info.plist; 585 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 586 | PRODUCT_BUNDLE_IDENTIFIER = com.robinlu.XEBoxUITests; 587 | PRODUCT_NAME = "$(TARGET_NAME)"; 588 | SWIFT_VERSION = 3.0; 589 | TEST_TARGET_NAME = XEBox; 590 | }; 591 | name = Debug; 592 | }; 593 | AE66B9FF1DB758D0007B4EFD /* Release */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 597 | COMBINE_HIDPI_IMAGES = YES; 598 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 599 | INFOPLIST_FILE = XEBoxUITests/Info.plist; 600 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 601 | PRODUCT_BUNDLE_IDENTIFIER = com.robinlu.XEBoxUITests; 602 | PRODUCT_NAME = "$(TARGET_NAME)"; 603 | SWIFT_VERSION = 3.0; 604 | TEST_TARGET_NAME = XEBox; 605 | }; 606 | name = Release; 607 | }; 608 | AE66BA141DB75920007B4EFD /* Debug */ = { 609 | isa = XCBuildConfiguration; 610 | buildSettings = { 611 | CODE_SIGN_ENTITLEMENTS = "XEBox Extensions/XEBox_Extensions.entitlements"; 612 | CODE_SIGN_IDENTITY = "Mac Developer"; 613 | COMBINE_HIDPI_IMAGES = YES; 614 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 615 | INFOPLIST_FILE = "XEBox Extensions/Info.plist"; 616 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; 617 | MACOSX_DEPLOYMENT_TARGET = 10.11; 618 | PRODUCT_BUNDLE_IDENTIFIER = "com.robinlu.XEBox.XEBox-Extensions"; 619 | PRODUCT_NAME = "$(TARGET_NAME)"; 620 | SKIP_INSTALL = YES; 621 | SWIFT_VERSION = 3.0; 622 | }; 623 | name = Debug; 624 | }; 625 | AE66BA151DB75920007B4EFD /* Release */ = { 626 | isa = XCBuildConfiguration; 627 | buildSettings = { 628 | CODE_SIGN_ENTITLEMENTS = "XEBox Extensions/XEBox_Extensions.entitlements"; 629 | CODE_SIGN_IDENTITY = "Mac Developer"; 630 | COMBINE_HIDPI_IMAGES = YES; 631 | DEVELOPMENT_TEAM = YMZ2R5RGSC; 632 | INFOPLIST_FILE = "XEBox Extensions/Info.plist"; 633 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; 634 | MACOSX_DEPLOYMENT_TARGET = 10.11; 635 | PRODUCT_BUNDLE_IDENTIFIER = "com.robinlu.XEBox.XEBox-Extensions"; 636 | PRODUCT_NAME = "$(TARGET_NAME)"; 637 | SKIP_INSTALL = YES; 638 | SWIFT_VERSION = 3.0; 639 | }; 640 | name = Release; 641 | }; 642 | /* End XCBuildConfiguration section */ 643 | 644 | /* Begin XCConfigurationList section */ 645 | AE66B9CD1DB758D0007B4EFD /* Build configuration list for PBXProject "XEBox" */ = { 646 | isa = XCConfigurationList; 647 | buildConfigurations = ( 648 | AE66B9F51DB758D0007B4EFD /* Debug */, 649 | AE66B9F61DB758D0007B4EFD /* Release */, 650 | ); 651 | defaultConfigurationIsVisible = 0; 652 | defaultConfigurationName = Release; 653 | }; 654 | AE66B9F71DB758D0007B4EFD /* Build configuration list for PBXNativeTarget "XEBox" */ = { 655 | isa = XCConfigurationList; 656 | buildConfigurations = ( 657 | AE66B9F81DB758D0007B4EFD /* Debug */, 658 | AE66B9F91DB758D0007B4EFD /* Release */, 659 | ); 660 | defaultConfigurationIsVisible = 0; 661 | defaultConfigurationName = Release; 662 | }; 663 | AE66B9FA1DB758D0007B4EFD /* Build configuration list for PBXNativeTarget "XEBoxTests" */ = { 664 | isa = XCConfigurationList; 665 | buildConfigurations = ( 666 | AE66B9FB1DB758D0007B4EFD /* Debug */, 667 | AE66B9FC1DB758D0007B4EFD /* Release */, 668 | ); 669 | defaultConfigurationIsVisible = 0; 670 | defaultConfigurationName = Release; 671 | }; 672 | AE66B9FD1DB758D0007B4EFD /* Build configuration list for PBXNativeTarget "XEBoxUITests" */ = { 673 | isa = XCConfigurationList; 674 | buildConfigurations = ( 675 | AE66B9FE1DB758D0007B4EFD /* Debug */, 676 | AE66B9FF1DB758D0007B4EFD /* Release */, 677 | ); 678 | defaultConfigurationIsVisible = 0; 679 | defaultConfigurationName = Release; 680 | }; 681 | AE66BA131DB75920007B4EFD /* Build configuration list for PBXNativeTarget "XEBox Extensions" */ = { 682 | isa = XCConfigurationList; 683 | buildConfigurations = ( 684 | AE66BA141DB75920007B4EFD /* Debug */, 685 | AE66BA151DB75920007B4EFD /* Release */, 686 | ); 687 | defaultConfigurationIsVisible = 0; 688 | defaultConfigurationName = Release; 689 | }; 690 | /* End XCConfigurationList section */ 691 | }; 692 | rootObject = AE66B9CA1DB758D0007B4EFD /* Project object */; 693 | } 694 | -------------------------------------------------------------------------------- /XEBox/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // XEBox 4 | // 5 | // Created by Lu Yibin on 19/10/2016. 6 | // Copyright © 2016 Lu Yibin. 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 | 20 | func applicationWillTerminate(_ aNotification: Notification) { 21 | // Insert code here to tear down your application 22 | } 23 | 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /XEBox/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 | } -------------------------------------------------------------------------------- /XEBox/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | Default 509 | 510 | 511 | 512 | 513 | 514 | 515 | Left to Right 516 | 517 | 518 | 519 | 520 | 521 | 522 | Right to Left 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | Default 534 | 535 | 536 | 537 | 538 | 539 | 540 | Left to Right 541 | 542 | 543 | 544 | 545 | 546 | 547 | Right to Left 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | -------------------------------------------------------------------------------- /XEBox/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2016 Lu Yibin. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /XEBox/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // XEBox 4 | // 5 | // Created by Lu Yibin on 19/10/2016. 6 | // Copyright © 2016 Lu Yibin. 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 | -------------------------------------------------------------------------------- /XEBoxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /XEBoxTests/XEBoxTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XEBoxTests.swift 3 | // XEBoxTests 4 | // 5 | // Created by Lu Yibin on 19/10/2016. 6 | // Copyright © 2016 Lu Yibin. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import XEBox 11 | 12 | class XEBoxTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /XEBoxUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | -------------------------------------------------------------------------------- /XEBoxUITests/XEBoxUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XEBoxUITests.swift 3 | // XEBoxUITests 4 | // 5 | // Created by Lu Yibin on 19/10/2016. 6 | // Copyright © 2016 Lu Yibin. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class XEBoxUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /images/screenshot-NSLocalizedString.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robin/XEBox/05ec5bcf868b08b871f5155f8c55bfc400628349/images/screenshot-NSLocalizedString.gif -------------------------------------------------------------------------------- /images/screenshot-importForMe.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robin/XEBox/05ec5bcf868b08b871f5155f8c55bfc400628349/images/screenshot-importForMe.gif -------------------------------------------------------------------------------- /images/screenshot-moveUpInBrace.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robin/XEBox/05ec5bcf868b08b871f5155f8c55bfc400628349/images/screenshot-moveUpInBrace.gif -------------------------------------------------------------------------------- /images/screenshot-optionalBinding.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robin/XEBox/05ec5bcf868b08b871f5155f8c55bfc400628349/images/screenshot-optionalBinding.gif --------------------------------------------------------------------------------