From 22c57e94aef7cf8d609c44af585a239066eb39ab Mon Sep 17 00:00:00 2001 From: Benjamin Mironer Date: Mon, 25 Sep 2017 19:36:30 +0200 Subject: [PATCH 1/5] FIxed issue 66 - hang when calling ibtool on XCode 9 --- Sources/Code/Commander.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Sources/Code/Commander.swift b/Sources/Code/Commander.swift index 7a2229b..90c0321 100644 --- a/Sources/Code/Commander.swift +++ b/Sources/Code/Commander.swift @@ -32,7 +32,15 @@ class Commander { task.standardError = errpipe task.launch() - + + var errors: [String] = [] + let errdata = errpipe.fileHandleForReading.readDataToEndOfFile() + + if var string = String(data: errdata, encoding: .utf8) { + string = string.trimmingCharacters(in: .newlines) + errors = string.components(separatedBy: "\n") + } + var outputs: [String] = [] let outdata = outpipe.fileHandleForReading.readDataToEndOfFile() @@ -41,14 +49,6 @@ class Commander { outputs = string.components(separatedBy: "\n") } - var errors: [String] = [] - let errdata = errpipe.fileHandleForReading.readDataToEndOfFile() - - if var string = String(data: errdata, encoding: .utf8) { - string = string.trimmingCharacters(in: .newlines) - errors = string.components(separatedBy: "\n") - } - task.waitUntilExit() let status = task.terminationStatus From ace18023be57ea91155cd27beb8bc2fd5d05a7c6 Mon Sep 17 00:00:00 2001 From: Benjamin Mironer Date: Mon, 25 Sep 2017 19:37:28 +0200 Subject: [PATCH 2/5] Fixed reproducibility of file search tests --- Tests/Code/StringsFilesSearchTests.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Code/StringsFilesSearchTests.swift b/Tests/Code/StringsFilesSearchTests.swift index 6c6967e..f4ac0ec 100644 --- a/Tests/Code/StringsFilesSearchTests.swift +++ b/Tests/Code/StringsFilesSearchTests.swift @@ -21,7 +21,7 @@ class StringsFilesSearchTests: XCTestCase { let results = StringsFilesSearch.shared.findAllIBFiles(within: basePath, withLocale: "Base") XCTAssertEqual(results.count, expectedIBFilePaths.count) - XCTAssertEqual(results, expectedIBFilePaths) + XCTAssertEqual(results.sorted(), expectedIBFilePaths.sorted()) } func testFindAllStringsFiles() { @@ -33,7 +33,7 @@ class StringsFilesSearchTests: XCTestCase { let results = StringsFilesSearch.shared.findAllStringsFiles(within: basePath, withLocale: "de") XCTAssertEqual(results.count, expectedStringsFilePaths.count) - XCTAssertEqual(results, expectedStringsFilePaths) + XCTAssertEqual(results.sorted(), expectedStringsFilePaths.sorted()) } func testiOSFindAllLocalesForStringsFile() { @@ -43,7 +43,7 @@ class StringsFilesSearchTests: XCTestCase { let results = StringsFilesSearch.shared.findAllLocalesForStringsFile(sourceFilePath: baseStoryboardPath) XCTAssertEqual(results.count, expectedStringsPaths.count) - XCTAssertEqual(results, expectedStringsPaths) + XCTAssertEqual(results.sorted(), expectedStringsPaths.sorted()) } From e9d821cab635e80e38202ad146541f9542de4666 Mon Sep 17 00:00:00 2001 From: Max Bothe Date: Sat, 16 Sep 2017 14:44:20 +0200 Subject: [PATCH 3/5] Remove superfluous disable command of swiftlint --- Sources/Code/StringsFileUpdater.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/Code/StringsFileUpdater.swift b/Sources/Code/StringsFileUpdater.swift index 5e4418d..f9ba576 100644 --- a/Sources/Code/StringsFileUpdater.swift +++ b/Sources/Code/StringsFileUpdater.swift @@ -7,7 +7,6 @@ // // swiftlint:disable function_body_length -// swiftlint:disable file_length import Foundation From 1b5efd568f51865f3dc808eba71d48c3ebb870fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cihat=20Gu=CC=88ndu=CC=88z?= Date: Tue, 26 Sep 2017 14:23:42 +0200 Subject: [PATCH 4/5] Update to Swift 4 & Xcode 9 + Update SwiftLint + Fix warnings --- .swiftlint.yml | 129 ++++- BartyCrouch.xcodeproj/project.pbxproj | 325 ++++++------- ...AF463047-11C0-4394-8F30-AA5C0CDDCEA1.plist | 32 ++ .../Info.plist | 24 + .../xcschemes/BartyCrouch CLI.xcscheme | 4 +- .../xcschemes/BartyCrouchKit.xcscheme | 4 +- Cartfile | 6 +- Cartfile.resolved | 6 +- Carthage/Checkouts/CommandLine/.gitignore | 2 + Carthage/Checkouts/CommandLine/.travis.yml | 19 +- .../CommandLineKit.xcodeproj/project.pbxproj | 22 +- .../xcschemes/CommandLine.xcscheme | 2 +- .../CommandLineKit/CommandLine.swift | 456 ++++++++++++++++++ .../CommandLine/CommandLineKit/Option.swift | 262 +++------- .../CommandLineKit/StringExtensions.swift | 102 +--- Carthage/Checkouts/CommandLine/Package.swift | 5 +- Carthage/Checkouts/CommandLine/README.md | 16 +- ...eKitTests.swift => CommandLineTests.swift} | 219 ++++----- .../StringExtensionTests.swift | 24 +- .../CommandLine/install-linux-swift.sh | 28 -- Carthage/Checkouts/CommandLine/script/test | 14 + Carthage/Checkouts/Handyswift/.swift-version | 2 +- Carthage/Checkouts/Handyswift/.swiftlint.yml | 135 +++++- .../Checkouts/Handyswift/HandySwift.podspec | 11 +- .../HandySwift.xcodeproj/project.pbxproj | 146 +++--- .../xcschemes/HandySwift OSX.xcscheme | 2 +- .../xcschemes/HandySwift iOS.xcscheme | 2 +- .../xcschemes/HandySwift tvOS.xcscheme | 2 +- Carthage/Checkouts/Handyswift/LICENSE.md | 2 +- Carthage/Checkouts/Handyswift/Package.swift | 4 +- Carthage/Checkouts/Handyswift/README.md | 197 +++----- .../Sources/Extensions/ArrayExtension.swift | 116 ++++- .../Extensions/CharacterViewExtension.swift | 23 +- .../Sources/Extensions/ColorExtension.swift | 127 ----- .../Extensions/CoreGraphicsExtensions.swift | 87 ---- .../Extensions/DictionaryExtension.swift | 24 +- .../DispatchTimeIntervalExtension.swift | 31 ++ .../Sources/Extensions/IntExtension.swift | 13 +- .../Extensions/IntegerTypeExtension.swift | 2 +- .../Sources/Extensions/StringExtension.swift | 53 +- .../Extensions/TimeIntervalExtension.swift | 94 ++++ .../Handyswift/Sources/Globals.swift | 42 +- .../Sources/Structs/FrequencyTable.swift | 36 +- .../Sources/Structs/SortedArray.swift | 156 +++--- .../Sources/Supporting Files/Info.plist | 2 +- .../Extensions/ArrayExtensionTests.swift | 35 +- .../CharacterViewExtensionTests.swift | 9 +- .../Extensions/ColorExtensionTests.swift | 69 --- .../CoreGraphicsExtensionsTests.swift | 137 ------ .../Extensions/DictionaryExtensionTests.swift | 9 +- .../DispatchTimeIntervalExtensionTests.swift | 19 + .../Tests/Extensions/IntExtensionTests.swift | 11 +- .../IntegerTypeExtensionTests.swift | 3 +- .../Extensions/StringExtensionTests.swift | 7 +- .../TimeIntervalExtensionTests.swift | 35 ++ .../Handyswift/Tests/GlobalsTests.swift | 11 +- .../Tests/Structs/FrequencyTableTests.swift | 6 +- .../Tests/Structs/SortedArrayTests.swift | 25 +- .../UsageExamples.playground/Contents.swift | 119 +++-- .../Polyglot/StringExtensionPolyglot.swift | 6 +- .../PolyglotSample.xcodeproj/project.pbxproj | 142 ++++-- .../xcschemes/PolyglotSample.xcscheme | 4 +- .../Polyglot/PolyglotSample/AppDelegate.swift | 2 +- .../Polyglot/PolyglotSample/Info.plist | 2 +- .../PolyglotSample/ViewController.swift | 9 +- .../Polyglot/PolyglotTests/Info.plist | 2 +- .../PolyglotTests/PolyglotTests.swift | 8 +- .../PolyglotTests/StringExtensionTests.swift | 6 +- .../CommandLineKit.swift | 6 +- Carthage/CommandLine/Info.plist | 28 ++ Carthage/CommandLine/Option.swift | 450 +++++++++++++++++ Carthage/CommandLine/StringExtensions.swift | 213 ++++++++ .../Extensions/ArrayExtension.swift | 135 ++++++ .../Extensions/CharacterViewExtension.swift | 32 ++ .../Extensions/DictionaryExtension.swift | 43 ++ .../DispatchTimeIntervalExtension.swift | 31 ++ .../HandySwift/Extensions/IntExtension.swift | 20 + .../Extensions/IntegerTypeExtension.swift | 20 + .../Extensions/StringExtension.swift | 57 +++ .../Extensions/TimeIntervalExtension.swift | 94 ++++ Carthage/HandySwift/Globals.swift | 20 + .../HandySwift/Structs/FrequencyTable.swift | 50 ++ Carthage/HandySwift/Structs/SortedArray.swift | 150 ++++++ .../HandySwift/Supporting Files/HandySwift.h | 17 + .../HandySwift/Supporting Files/Info.plist | 26 + Carthage/Polyglot/Polyglot.swift | 184 +++++++ Carthage/Polyglot/Session.swift | 74 +++ .../Polyglot/StringExtensionPolyglot.swift | 44 ++ Sources/Code/CodeCommander.swift | 8 +- Sources/Code/CommandLineActor.swift | 51 +- Sources/Code/CommandLineParser.swift | 86 +++- Sources/Code/Commander.swift | 11 +- Sources/Code/ExtractLocStringsCommander.swift | 9 +- Sources/Code/GenStringsCommander.swift | 8 +- Sources/Code/IBToolCommander.swift | 4 - Sources/Code/StringsFileUpdater.swift | 73 ++- Sources/Code/StringsFilesSearch.swift | 6 +- Sources/Code/SubCommander.swift | 7 +- .../SwiftExample1.swift | 2 +- Tests/Assets/Code Files/SwiftExample1.swift | 2 +- Tests/Code/CommandLineActorTests.swift | 17 +- Tests/Code/CommandLineParserTests.swift | 35 +- .../ExtractLocStringsCommanderTests.swift | 20 +- Tests/Code/GenStringsCommanderTests.swift | 12 +- Tests/Code/IBToolCommanderTests.swift | 3 +- Tests/Code/StringsFileUpdaterTests.swift | 36 +- Tests/Code/StringsFilesSearchTests.swift | 6 +- 107 files changed, 3925 insertions(+), 1851 deletions(-) create mode 100644 BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/AF463047-11C0-4394-8F30-AA5C0CDDCEA1.plist create mode 100644 Carthage/Checkouts/CommandLine/CommandLineKit/CommandLine.swift rename Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/{CommandLineKitTests.swift => CommandLineTests.swift} (77%) delete mode 100755 Carthage/Checkouts/CommandLine/install-linux-swift.sh create mode 100755 Carthage/Checkouts/CommandLine/script/test delete mode 100644 Carthage/Checkouts/Handyswift/Sources/Extensions/ColorExtension.swift delete mode 100644 Carthage/Checkouts/Handyswift/Sources/Extensions/CoreGraphicsExtensions.swift create mode 100644 Carthage/Checkouts/Handyswift/Sources/Extensions/DispatchTimeIntervalExtension.swift create mode 100644 Carthage/Checkouts/Handyswift/Sources/Extensions/TimeIntervalExtension.swift delete mode 100644 Carthage/Checkouts/Handyswift/Tests/Extensions/ColorExtensionTests.swift delete mode 100644 Carthage/Checkouts/Handyswift/Tests/Extensions/CoreGraphicsExtensionsTests.swift create mode 100644 Carthage/Checkouts/Handyswift/Tests/Extensions/DispatchTimeIntervalExtensionTests.swift create mode 100644 Carthage/Checkouts/Handyswift/Tests/Extensions/TimeIntervalExtensionTests.swift rename Carthage/{Checkouts/CommandLine/CommandLineKit => CommandLine}/CommandLineKit.swift (98%) create mode 100644 Carthage/CommandLine/Info.plist create mode 100644 Carthage/CommandLine/Option.swift create mode 100644 Carthage/CommandLine/StringExtensions.swift create mode 100644 Carthage/HandySwift/Extensions/ArrayExtension.swift create mode 100644 Carthage/HandySwift/Extensions/CharacterViewExtension.swift create mode 100644 Carthage/HandySwift/Extensions/DictionaryExtension.swift create mode 100644 Carthage/HandySwift/Extensions/DispatchTimeIntervalExtension.swift create mode 100644 Carthage/HandySwift/Extensions/IntExtension.swift create mode 100644 Carthage/HandySwift/Extensions/IntegerTypeExtension.swift create mode 100644 Carthage/HandySwift/Extensions/StringExtension.swift create mode 100644 Carthage/HandySwift/Extensions/TimeIntervalExtension.swift create mode 100644 Carthage/HandySwift/Globals.swift create mode 100644 Carthage/HandySwift/Structs/FrequencyTable.swift create mode 100644 Carthage/HandySwift/Structs/SortedArray.swift create mode 100644 Carthage/HandySwift/Supporting Files/HandySwift.h create mode 100644 Carthage/HandySwift/Supporting Files/Info.plist create mode 100644 Carthage/Polyglot/Polyglot.swift create mode 100644 Carthage/Polyglot/Session.swift create mode 100644 Carthage/Polyglot/StringExtensionPolyglot.swift diff --git a/.swiftlint.yml b/.swiftlint.yml index dc67e6f..edab931 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,8 +1,29 @@ opt_in_rules: +- attributes +- closure_end_indentation +- closure_spacing - empty_count +- explicit_init +- file_header +- first_where +- let_var_whitespace +- nimble_operator +- no_extension_access_modifier +- number_separator +- object_literal +- operator_usage_whitespace +- overridden_super_call +- private_outlet +- prohibited_super_call +- redundant_nil_coalescing +- sorted_imports +- switch_case_on_newline +- trailing_closure +- unneeded_parentheses_in_closure_argument +- vertical_parameter_alignment_on_call disabled_rules: -- vertical_whitespace # Turn off until configurable to 2 newlines +- todo - cyclomatic_complexity included: @@ -11,6 +32,108 @@ included: excluded: - Carthage -- Sources/Constants +- Package.swift +- UsageExamples.playground -line_length: 180 +line_length: 160 + +file_header: + required_pattern: | + \/\/ + \/\/ .*?\.swift + \/\/ BartyCrouch + \/\/ + \/\/ Created by [^\(\)\d\n]+ on \S{6,10}\. + \/\/ Copyright © \d{4} Flinesoft\. All rights reserved\. + \/\/ +custom_rules: + closing_brace_whitespace: + included: ".*.swift" + regex: '(?:\n| {2,})\}\)? *\n *[^ \n\})\]]' + name: "Closing Brace Whitespace" + message: "Empty line required after closing curly braces if code with same indentation follows." + severity: warning + closure_params_parantheses: + included: ".*.swift" + regex: '\{\s*\([^):]+\)\s*in' + name: "Unnecessary Closure Params Parantheses" + message: "Don't use parantheses around non-typed parameters in a closure." + severity: warning + if_as_guard: + included: ".*.swift" + regex: '\n *if [^\{]+\{\s*return[^\n]*\n *\}(?! *else)' + name: "If as Guard" + message: "Don't use an if statement to just return – use guard for such cases instead." + severity: warning + late_force_unwrapping: + included: ".*.swift" + regex: '\(\S+\?\.\S+\)!' + name: "Late Force Unwrapping" + message: "Don't use ? first to force unwrap later – directly unwrap within the parantheses." + severity: warning + multiple_closure_params: + included: ".*.swift" + regex: '\} *\) *\{' + name: "Multiple Closure Params" + message: "Don't use multiple in-line closures – save one or more of them to variables instead." + severity: warning + single_line_guard: + included: ".*.swift" + regex: 'guard[^\{]{2,80}else\s*\{\s*\n\s*return.{2,40}\}' + name: "Single Line Guard" + message: "Use a single line guard for simple checks." + severity: warning + too_much_indentation: + included: ".*.swift" + regex: '\n {0}[^\s\/][^\n]*[^,|&]\n+ {5,}\S|\n {4}[^\s\/][^\n]*[^,|&]\n+ {9,}\S|\n {8}[^\s\/][^\n]*[^,|&]\n+ {13,}\S|\n {12}[^\s\/][^\n]*[^,|&]\n+ {17,}\S|\n {16}[^\s\/][^\n]*[^,|&]\n+ {21,}\S|\n {20}[^\s\/][^\n]*[^,|&]\n+ {25,}\S' + name: "Too Much Indentation" + message: "Don't indent code by more than 4 whitespaces." + severity: warning + too_much_unindentation: + included: ".*.swift" + regex: ' {28}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,23}[^\s\/]| {24}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,19}[^\s\/]| {20}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,15}[^\s\/]| {16}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,11}[^\s\/]| {12}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,7}[^\s\/]| {8}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,3}[^\s\/]' + name: "Too Much Unindentation" + message: "Don't unindent code by more than 4 whitespaces." + severity: warning + unnecessary_case_break: + included: ".*.swift" + regex: '(case |default)(?:[^\n\}]+\n){2,}\s*break|\n *\n *break(?:\n *\n|\n *\})' + name: "Unnecessary Case Break" + message: "Don't use break in switch cases – Swift breaks by default." + severity: warning + unnecessary_nil_assignment: + included: ".*.swift" + regex: 'var \S+\s*:\s*[^\s]+\?\s*=\s*nil' + name: "Unnecessary Nil Assignment" + message: "Don't assign nil as a value when defining an optional type – it's nil by default." + severity: warning + vertical_whitespace_between_cases: + included: ".*.swift" + regex: '[^\n{][ \t]*\n[ \t]*(?:case[^\n]+|default):[ \t]*\n' + name: "Vertical Whitespace Between Cases" + message: "Include a vertical whitespace (empty line) between cases in switch statements." + severity: warning + vertical_whitespaces_around_mark: + included: ".*.swift" + regex: '\/\/\s*MARK:[^\n]*(\n\n)|(\n\n\n)[ \t]*\/\/\s*MARK:|[^\s{]\n[^\n\/]*\/\/\s*MARK:' + name: "Vertical Whitespaces Around MARK:" + message: "Include a single vertical whitespace (empty line) before and none after MARK: comments." + severity: warning + vertical_whitespace_opening_braces: + included: ".*.swift" + regex: '[{(\[][ \t]*\n[ \t]*\n' + name: "Vertical Whitespace after Opening Braces" + message: "Don't include vertical whitespace (empty line) after opening braces." + severity: warning + vertical_whitespace_closing_braces: + included: ".*.swift" + regex: '\n[ \t]*\n[ \t]*[)}\]]' + name: "Vertical Whitespace before Closing Braces" + message: "Don't include vertical whitespace (empty line) before closing braces." + severity: warning + whitespace_comment_start: + included: ".*.swift" + regex: '[^:]\/\/[^\s\/]' + name: "Whitespace Comment Start" + message: "A comment should always start with a whitespace." + severity: warning diff --git a/BartyCrouch.xcodeproj/project.pbxproj b/BartyCrouch.xcodeproj/project.pbxproj index 76e6777..1d97a63 100644 --- a/BartyCrouch.xcodeproj/project.pbxproj +++ b/BartyCrouch.xcodeproj/project.pbxproj @@ -7,8 +7,40 @@ objects = { /* Begin PBXBuildFile section */ - 82053A231CD3221900434DAD /* StringExtensionPolyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82053A221CD3221900434DAD /* StringExtensionPolyglot.swift */; }; - 82053A241CD3221900434DAD /* StringExtensionPolyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82053A221CD3221900434DAD /* StringExtensionPolyglot.swift */; }; + 00CAD6B81F7A6EF80090DD38 /* CommandLineKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6181F7A6EA60090DD38 /* CommandLineKit.swift */; }; + 00CAD6B91F7A6EF80090DD38 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD61A1F7A6EA60090DD38 /* Option.swift */; }; + 00CAD6BA1F7A6EF80090DD38 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD61B1F7A6EA60090DD38 /* StringExtensions.swift */; }; + 00CAD6BB1F7A6F0A0090DD38 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64A1F7A6EA60090DD38 /* ArrayExtension.swift */; }; + 00CAD6BC1F7A6F0A0090DD38 /* CharacterViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64B1F7A6EA60090DD38 /* CharacterViewExtension.swift */; }; + 00CAD6BD1F7A6F0A0090DD38 /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64C1F7A6EA60090DD38 /* DictionaryExtension.swift */; }; + 00CAD6BE1F7A6F0A0090DD38 /* DispatchTimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64D1F7A6EA60090DD38 /* DispatchTimeIntervalExtension.swift */; }; + 00CAD6BF1F7A6F0A0090DD38 /* IntegerTypeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64E1F7A6EA60090DD38 /* IntegerTypeExtension.swift */; }; + 00CAD6C01F7A6F0A0090DD38 /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64F1F7A6EA60090DD38 /* IntExtension.swift */; }; + 00CAD6C11F7A6F0A0090DD38 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6501F7A6EA60090DD38 /* StringExtension.swift */; }; + 00CAD6C21F7A6F0A0090DD38 /* TimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6511F7A6EA60090DD38 /* TimeIntervalExtension.swift */; }; + 00CAD6C31F7A6F0A0090DD38 /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6521F7A6EA60090DD38 /* Globals.swift */; }; + 00CAD6C41F7A6F0A0090DD38 /* FrequencyTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6541F7A6EA60090DD38 /* FrequencyTable.swift */; }; + 00CAD6C51F7A6F0A0090DD38 /* SortedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6551F7A6EA60090DD38 /* SortedArray.swift */; }; + 00CAD6C61F7A6F110090DD38 /* Polyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6831F7A6EA60090DD38 /* Polyglot.swift */; }; + 00CAD6C71F7A6F110090DD38 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6841F7A6EA60090DD38 /* Session.swift */; }; + 00CAD6C81F7A6F110090DD38 /* StringExtensionPolyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6851F7A6EA60090DD38 /* StringExtensionPolyglot.swift */; }; + 00CAD6C91F7A743D0090DD38 /* CommandLineKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6181F7A6EA60090DD38 /* CommandLineKit.swift */; }; + 00CAD6CA1F7A743D0090DD38 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD61A1F7A6EA60090DD38 /* Option.swift */; }; + 00CAD6CB1F7A743D0090DD38 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD61B1F7A6EA60090DD38 /* StringExtensions.swift */; }; + 00CAD6CC1F7A744D0090DD38 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64A1F7A6EA60090DD38 /* ArrayExtension.swift */; }; + 00CAD6CD1F7A744D0090DD38 /* CharacterViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64B1F7A6EA60090DD38 /* CharacterViewExtension.swift */; }; + 00CAD6CE1F7A744D0090DD38 /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64C1F7A6EA60090DD38 /* DictionaryExtension.swift */; }; + 00CAD6CF1F7A744D0090DD38 /* DispatchTimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64D1F7A6EA60090DD38 /* DispatchTimeIntervalExtension.swift */; }; + 00CAD6D01F7A744D0090DD38 /* IntegerTypeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64E1F7A6EA60090DD38 /* IntegerTypeExtension.swift */; }; + 00CAD6D11F7A744D0090DD38 /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD64F1F7A6EA60090DD38 /* IntExtension.swift */; }; + 00CAD6D21F7A744D0090DD38 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6501F7A6EA60090DD38 /* StringExtension.swift */; }; + 00CAD6D31F7A744D0090DD38 /* TimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6511F7A6EA60090DD38 /* TimeIntervalExtension.swift */; }; + 00CAD6D41F7A744D0090DD38 /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6521F7A6EA60090DD38 /* Globals.swift */; }; + 00CAD6D51F7A744D0090DD38 /* FrequencyTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6541F7A6EA60090DD38 /* FrequencyTable.swift */; }; + 00CAD6D61F7A744D0090DD38 /* SortedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6551F7A6EA60090DD38 /* SortedArray.swift */; }; + 00CAD6D71F7A74540090DD38 /* Polyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6831F7A6EA60090DD38 /* Polyglot.swift */; }; + 00CAD6D81F7A74540090DD38 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6841F7A6EA60090DD38 /* Session.swift */; }; + 00CAD6D91F7A74540090DD38 /* StringExtensionPolyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD6851F7A6EA60090DD38 /* StringExtensionPolyglot.swift */; }; 82053A261CD32A0200434DAD /* LongOldExample.strings in Resources */ = {isa = PBXBuildFile; fileRef = 82053A251CD32A0200434DAD /* LongOldExample.strings */; }; 82053A281CD32B4900434DAD /* LongNewExample.strings in Resources */ = {isa = PBXBuildFile; fileRef = 82053A271CD32B4900434DAD /* LongNewExample.strings */; }; 82125E931D0312CF00B9C66B /* Commander.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82125E921D0312CF00B9C66B /* Commander.swift */; }; @@ -36,42 +68,8 @@ 82CDE2EB1C6BF9D900055FE6 /* IBToolCommander.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CDE2EA1C6BF9D900055FE6 /* IBToolCommander.swift */; }; 82CDE2ED1C6BFE8F00055FE6 /* IBToolCommanderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CDE2EC1C6BFE8F00055FE6 /* IBToolCommanderTests.swift */; }; 82CDE2EF1C6BFE9D00055FE6 /* StringsFileUpdaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CDE2EE1C6BFE9D00055FE6 /* StringsFileUpdaterTests.swift */; }; - 82DD98351C7DE1560065F046 /* Polyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DD98321C7DE1560065F046 /* Polyglot.swift */; }; - 82DD98361C7DE1560065F046 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DD98331C7DE1560065F046 /* Session.swift */; }; - 82DD98381C7DE18B0065F046 /* Polyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DD98321C7DE1560065F046 /* Polyglot.swift */; }; - 82DD98391C7DE18B0065F046 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82DD98331C7DE1560065F046 /* Session.swift */; }; A140FE0F1D4BD6FB001E0C4B /* Commander.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82125E921D0312CF00B9C66B /* Commander.swift */; }; A1B73EB01E00744D0070D20F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1B73EAE1E00744D0070D20F /* Localizable.strings */; }; - A1B73EC41E00ABDE0070D20F /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB51E00ABDE0070D20F /* ArrayExtension.swift */; }; - A1B73EC51E00ABDE0070D20F /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB51E00ABDE0070D20F /* ArrayExtension.swift */; }; - A1B73EC61E00ABDE0070D20F /* CharacterViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB61E00ABDE0070D20F /* CharacterViewExtension.swift */; }; - A1B73EC71E00ABDE0070D20F /* CharacterViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB61E00ABDE0070D20F /* CharacterViewExtension.swift */; }; - A1B73EC81E00ABDE0070D20F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB71E00ABDE0070D20F /* ColorExtension.swift */; }; - A1B73EC91E00ABDE0070D20F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB71E00ABDE0070D20F /* ColorExtension.swift */; }; - A1B73ECA1E00ABDE0070D20F /* CoreGraphicsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB81E00ABDE0070D20F /* CoreGraphicsExtensions.swift */; }; - A1B73ECB1E00ABDE0070D20F /* CoreGraphicsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB81E00ABDE0070D20F /* CoreGraphicsExtensions.swift */; }; - A1B73ECC1E00ABDE0070D20F /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB91E00ABDE0070D20F /* DictionaryExtension.swift */; }; - A1B73ECD1E00ABDE0070D20F /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EB91E00ABDE0070D20F /* DictionaryExtension.swift */; }; - A1B73ECE1E00ABDE0070D20F /* IntegerTypeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBA1E00ABDE0070D20F /* IntegerTypeExtension.swift */; }; - A1B73ECF1E00ABDE0070D20F /* IntegerTypeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBA1E00ABDE0070D20F /* IntegerTypeExtension.swift */; }; - A1B73ED01E00ABDE0070D20F /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBB1E00ABDE0070D20F /* IntExtension.swift */; }; - A1B73ED11E00ABDE0070D20F /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBB1E00ABDE0070D20F /* IntExtension.swift */; }; - A1B73ED21E00ABDE0070D20F /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBC1E00ABDE0070D20F /* StringExtension.swift */; }; - A1B73ED31E00ABDE0070D20F /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBC1E00ABDE0070D20F /* StringExtension.swift */; }; - A1B73ED41E00ABDE0070D20F /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBD1E00ABDE0070D20F /* Globals.swift */; }; - A1B73ED51E00ABDE0070D20F /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBD1E00ABDE0070D20F /* Globals.swift */; }; - A1B73ED61E00ABDE0070D20F /* FrequencyTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBF1E00ABDE0070D20F /* FrequencyTable.swift */; }; - A1B73ED71E00ABDE0070D20F /* FrequencyTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EBF1E00ABDE0070D20F /* FrequencyTable.swift */; }; - A1B73ED81E00ABDE0070D20F /* SortedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EC01E00ABDE0070D20F /* SortedArray.swift */; }; - A1B73ED91E00ABDE0070D20F /* SortedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B73EC01E00ABDE0070D20F /* SortedArray.swift */; }; - A1B73EDA1E00ABDE0070D20F /* HandySwift.h in Headers */ = {isa = PBXBuildFile; fileRef = A1B73EC21E00ABDE0070D20F /* HandySwift.h */; }; - A1B73EDB1E00ABDE0070D20F /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A1B73EC31E00ABDE0070D20F /* Info.plist */; }; - A1FF9D9F1D9324F900D5E85E /* CommandLineKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FF9D9C1D9324F900D5E85E /* CommandLineKit.swift */; }; - A1FF9DA01D9324F900D5E85E /* CommandLineKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FF9D9C1D9324F900D5E85E /* CommandLineKit.swift */; }; - A1FF9DA11D9324F900D5E85E /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FF9D9D1D9324F900D5E85E /* Option.swift */; }; - A1FF9DA21D9324F900D5E85E /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FF9D9D1D9324F900D5E85E /* Option.swift */; }; - A1FF9DA31D9324F900D5E85E /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FF9D9E1D9324F900D5E85E /* StringExtensions.swift */; }; - A1FF9DA41D9324F900D5E85E /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FF9D9E1D9324F900D5E85E /* StringExtensions.swift */; }; E4EDD5ED1E314F080010D878 /* BartyCrouchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82CDE27F1C6ABF3A00055FE6 /* BartyCrouchKit.framework */; }; E78B1E141DFAB33200C7C290 /* ExtractLocStringsCommander.swift in Sources */ = {isa = PBXBuildFile; fileRef = E78B1E131DFAB33200C7C290 /* ExtractLocStringsCommander.swift */; }; E78B1E151DFAB33900C7C290 /* ExtractLocStringsCommander.swift in Sources */ = {isa = PBXBuildFile; fileRef = E78B1E131DFAB33200C7C290 /* ExtractLocStringsCommander.swift */; }; @@ -106,9 +104,25 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 00CAD6181F7A6EA60090DD38 /* CommandLineKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandLineKit.swift; sourceTree = ""; }; + 00CAD61A1F7A6EA60090DD38 /* Option.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Option.swift; sourceTree = ""; }; + 00CAD61B1F7A6EA60090DD38 /* StringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = ""; }; + 00CAD64A1F7A6EA60090DD38 /* ArrayExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = ""; }; + 00CAD64B1F7A6EA60090DD38 /* CharacterViewExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterViewExtension.swift; sourceTree = ""; }; + 00CAD64C1F7A6EA60090DD38 /* DictionaryExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryExtension.swift; sourceTree = ""; }; + 00CAD64D1F7A6EA60090DD38 /* DispatchTimeIntervalExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DispatchTimeIntervalExtension.swift; sourceTree = ""; }; + 00CAD64E1F7A6EA60090DD38 /* IntegerTypeExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerTypeExtension.swift; sourceTree = ""; }; + 00CAD64F1F7A6EA60090DD38 /* IntExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntExtension.swift; sourceTree = ""; }; + 00CAD6501F7A6EA60090DD38 /* StringExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; + 00CAD6511F7A6EA60090DD38 /* TimeIntervalExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeIntervalExtension.swift; sourceTree = ""; }; + 00CAD6521F7A6EA60090DD38 /* Globals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; }; + 00CAD6541F7A6EA60090DD38 /* FrequencyTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrequencyTable.swift; sourceTree = ""; }; + 00CAD6551F7A6EA60090DD38 /* SortedArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortedArray.swift; sourceTree = ""; }; + 00CAD6831F7A6EA60090DD38 /* Polyglot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Polyglot.swift; sourceTree = ""; }; + 00CAD6841F7A6EA60090DD38 /* Session.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Session.swift; sourceTree = ""; }; + 00CAD6851F7A6EA60090DD38 /* StringExtensionPolyglot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensionPolyglot.swift; sourceTree = ""; }; 8203A2971C6D159D00BCE479 /* NewExample.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = NewExample.strings; sourceTree = ""; }; 8203A2981C6D159D00BCE479 /* OldExample.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = OldExample.strings; sourceTree = ""; }; - 82053A221CD3221900434DAD /* StringExtensionPolyglot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionPolyglot.swift; sourceTree = ""; }; 82053A251CD32A0200434DAD /* LongOldExample.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = LongOldExample.strings; sourceTree = ""; }; 82053A271CD32B4900434DAD /* LongNewExample.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = LongNewExample.strings; sourceTree = ""; }; 820649CD1C7CA636009E501E /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; @@ -157,8 +171,6 @@ 82CDE2EC1C6BFE8F00055FE6 /* IBToolCommanderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IBToolCommanderTests.swift; sourceTree = ""; }; 82CDE2EE1C6BFE9D00055FE6 /* StringsFileUpdaterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringsFileUpdaterTests.swift; sourceTree = ""; }; 82CDE2F71C6C08F800055FE6 /* BartyCrouchTests-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BartyCrouchTests-Bridging-Header.h"; sourceTree = ""; }; - 82DD98321C7DE1560065F046 /* Polyglot.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Polyglot.swift; sourceTree = ""; }; - 82DD98331C7DE1560065F046 /* Session.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Session.swift; sourceTree = ""; }; 82F2E1041D27CF7900C6386A /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; 82F2E1051D27DB8A00C6386A /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = ""; }; 82F2E1061D27DB8A00C6386A /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; @@ -166,22 +178,6 @@ A1A1BE7C1F3212BB006A0049 /* BartyCrouch.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = BartyCrouch.podspec; sourceTree = ""; }; A1B73EAF1E00744D0070D20F /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; A1B73EB11E00A8320070D20F /* Cartfile.resolved */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile.resolved; sourceTree = ""; }; - A1B73EB51E00ABDE0070D20F /* ArrayExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = ""; }; - A1B73EB61E00ABDE0070D20F /* CharacterViewExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CharacterViewExtension.swift; sourceTree = ""; }; - A1B73EB71E00ABDE0070D20F /* ColorExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = ""; }; - A1B73EB81E00ABDE0070D20F /* CoreGraphicsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreGraphicsExtensions.swift; sourceTree = ""; }; - A1B73EB91E00ABDE0070D20F /* DictionaryExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryExtension.swift; sourceTree = ""; }; - A1B73EBA1E00ABDE0070D20F /* IntegerTypeExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntegerTypeExtension.swift; sourceTree = ""; }; - A1B73EBB1E00ABDE0070D20F /* IntExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntExtension.swift; sourceTree = ""; }; - A1B73EBC1E00ABDE0070D20F /* StringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = ""; }; - A1B73EBD1E00ABDE0070D20F /* Globals.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; }; - A1B73EBF1E00ABDE0070D20F /* FrequencyTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FrequencyTable.swift; sourceTree = ""; }; - A1B73EC01E00ABDE0070D20F /* SortedArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortedArray.swift; sourceTree = ""; }; - A1B73EC21E00ABDE0070D20F /* HandySwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandySwift.h; sourceTree = ""; }; - A1B73EC31E00ABDE0070D20F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A1FF9D9C1D9324F900D5E85E /* CommandLineKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CommandLineKit.swift; path = Carthage/Checkouts/CommandLine/CommandLineKit/CommandLineKit.swift; sourceTree = SOURCE_ROOT; }; - A1FF9D9D1D9324F900D5E85E /* Option.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Option.swift; path = Carthage/Checkouts/CommandLine/CommandLineKit/Option.swift; sourceTree = SOURCE_ROOT; }; - A1FF9D9E1D9324F900D5E85E /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StringExtensions.swift; path = Carthage/Checkouts/CommandLine/CommandLineKit/StringExtensions.swift; sourceTree = SOURCE_ROOT; }; E4EDD5F91E3151BE0010D878 /* SwiftExample2Arguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExample2Arguments.swift; sourceTree = ""; }; E4EDD5FB1E3151BE0010D878 /* SwiftExample3Arguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExample3Arguments.swift; sourceTree = ""; }; E4EDD5FD1E3151BE0010D878 /* SwiftExample4Arguments.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftExample4Arguments.swift; sourceTree = ""; }; @@ -222,25 +218,68 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 820649CE1C7CA6FA009E501E /* Carthage */ = { + 00CAD6171F7A6EA60090DD38 /* CommandLine */ = { isa = PBXGroup; children = ( - A1B73EB31E00ABDE0070D20F /* HandySwift */, - 820649CF1C7CA705009E501E /* CommandLine */, - 82DD98311C7DE1560065F046 /* Polyglot */, + 00CAD6181F7A6EA60090DD38 /* CommandLineKit.swift */, + 00CAD61A1F7A6EA60090DD38 /* Option.swift */, + 00CAD61B1F7A6EA60090DD38 /* StringExtensions.swift */, ); - path = Carthage; + path = CommandLine; + sourceTree = ""; + }; + 00CAD6481F7A6EA60090DD38 /* HandySwift */ = { + isa = PBXGroup; + children = ( + 00CAD6491F7A6EA60090DD38 /* Extensions */, + 00CAD6521F7A6EA60090DD38 /* Globals.swift */, + 00CAD6531F7A6EA60090DD38 /* Structs */, + ); + path = HandySwift; sourceTree = ""; }; - 820649CF1C7CA705009E501E /* CommandLine */ = { + 00CAD6491F7A6EA60090DD38 /* Extensions */ = { isa = PBXGroup; children = ( - A1FF9D9C1D9324F900D5E85E /* CommandLineKit.swift */, - A1FF9D9D1D9324F900D5E85E /* Option.swift */, - A1FF9D9E1D9324F900D5E85E /* StringExtensions.swift */, + 00CAD64A1F7A6EA60090DD38 /* ArrayExtension.swift */, + 00CAD64B1F7A6EA60090DD38 /* CharacterViewExtension.swift */, + 00CAD64C1F7A6EA60090DD38 /* DictionaryExtension.swift */, + 00CAD64D1F7A6EA60090DD38 /* DispatchTimeIntervalExtension.swift */, + 00CAD64E1F7A6EA60090DD38 /* IntegerTypeExtension.swift */, + 00CAD64F1F7A6EA60090DD38 /* IntExtension.swift */, + 00CAD6501F7A6EA60090DD38 /* StringExtension.swift */, + 00CAD6511F7A6EA60090DD38 /* TimeIntervalExtension.swift */, ); - name = CommandLine; - path = Checkouts/CommandLine/CommandLine; + path = Extensions; + sourceTree = ""; + }; + 00CAD6531F7A6EA60090DD38 /* Structs */ = { + isa = PBXGroup; + children = ( + 00CAD6541F7A6EA60090DD38 /* FrequencyTable.swift */, + 00CAD6551F7A6EA60090DD38 /* SortedArray.swift */, + ); + path = Structs; + sourceTree = ""; + }; + 00CAD6821F7A6EA60090DD38 /* Polyglot */ = { + isa = PBXGroup; + children = ( + 00CAD6831F7A6EA60090DD38 /* Polyglot.swift */, + 00CAD6841F7A6EA60090DD38 /* Session.swift */, + 00CAD6851F7A6EA60090DD38 /* StringExtensionPolyglot.swift */, + ); + path = Polyglot; + sourceTree = ""; + }; + 820649CE1C7CA6FA009E501E /* Carthage */ = { + isa = PBXGroup; + children = ( + 00CAD6821F7A6EA60090DD38 /* Polyglot */, + 00CAD6481F7A6EA60090DD38 /* HandySwift */, + 00CAD6171F7A6EA60090DD38 /* CommandLine */, + ); + path = Carthage; sourceTree = ""; }; 82463DFF1CD9116800D28A2C /* Command Line */ = { @@ -461,17 +500,6 @@ path = tvOS; sourceTree = ""; }; - 82DD98311C7DE1560065F046 /* Polyglot */ = { - isa = PBXGroup; - children = ( - 82DD98321C7DE1560065F046 /* Polyglot.swift */, - 82DD98331C7DE1560065F046 /* Session.swift */, - 82053A221CD3221900434DAD /* StringExtensionPolyglot.swift */, - ); - name = Polyglot; - path = Checkouts/Polyglot/Polyglot; - sourceTree = ""; - }; A14DE16D1D71B0400010F856 /* UnsortedKeys */ = { isa = PBXGroup; children = ( @@ -501,51 +529,6 @@ name = "Root Files"; sourceTree = ""; }; - A1B73EB31E00ABDE0070D20F /* HandySwift */ = { - isa = PBXGroup; - children = ( - A1B73EB41E00ABDE0070D20F /* Extensions */, - A1B73EBD1E00ABDE0070D20F /* Globals.swift */, - A1B73EBE1E00ABDE0070D20F /* Structs */, - A1B73EC11E00ABDE0070D20F /* Supporting Files */, - ); - name = HandySwift; - path = Checkouts/Handyswift/Sources; - sourceTree = ""; - }; - A1B73EB41E00ABDE0070D20F /* Extensions */ = { - isa = PBXGroup; - children = ( - A1B73EB51E00ABDE0070D20F /* ArrayExtension.swift */, - A1B73EB61E00ABDE0070D20F /* CharacterViewExtension.swift */, - A1B73EB71E00ABDE0070D20F /* ColorExtension.swift */, - A1B73EB81E00ABDE0070D20F /* CoreGraphicsExtensions.swift */, - A1B73EB91E00ABDE0070D20F /* DictionaryExtension.swift */, - A1B73EBA1E00ABDE0070D20F /* IntegerTypeExtension.swift */, - A1B73EBB1E00ABDE0070D20F /* IntExtension.swift */, - A1B73EBC1E00ABDE0070D20F /* StringExtension.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - A1B73EBE1E00ABDE0070D20F /* Structs */ = { - isa = PBXGroup; - children = ( - A1B73EBF1E00ABDE0070D20F /* FrequencyTable.swift */, - A1B73EC01E00ABDE0070D20F /* SortedArray.swift */, - ); - path = Structs; - sourceTree = ""; - }; - A1B73EC11E00ABDE0070D20F /* Supporting Files */ = { - isa = PBXGroup; - children = ( - A1B73EC21E00ABDE0070D20F /* HandySwift.h */, - A1B73EC31E00ABDE0070D20F /* Info.plist */, - ); - path = "Supporting Files"; - sourceTree = ""; - }; E4EDD5F71E3151BE0010D878 /* Multiple Arguments Code Custom Function */ = { isa = PBXGroup; children = ( @@ -649,7 +632,6 @@ buildActionMask = 2147483647; files = ( 82CDE2981C6ABFB800055FE6 /* BartyCrouch.h in Headers */, - A1B73EDA1E00ABDE0070D20F /* HandySwift.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -717,7 +699,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = Flinesoft; TargetAttributes = { 82CDE2721C6ABE5C00055FE6 = { @@ -725,11 +707,11 @@ }; 82CDE27E1C6ABF3A00055FE6 = { CreatedOnToolsVersion = 7.2.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; 82CDE2871C6ABF3A00055FE6 = { CreatedOnToolsVersion = 7.2.1; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; }; }; @@ -761,7 +743,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - A1B73EDB1E00ABDE0070D20F /* Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -800,34 +781,34 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A1B73ED91E00ABDE0070D20F /* SortedArray.swift in Sources */, - A1FF9DA01D9324F900D5E85E /* CommandLineKit.swift in Sources */, + 00CAD6CC1F7A744D0090DD38 /* ArrayExtension.swift in Sources */, + 00CAD6D51F7A744D0090DD38 /* FrequencyTable.swift in Sources */, 828ED5361C710C2F00E0E947 /* IBToolCommander.swift in Sources */, - A1FF9DA21D9324F900D5E85E /* Option.swift in Sources */, - A1B73EC51E00ABDE0070D20F /* ArrayExtension.swift in Sources */, + 00CAD6D71F7A74540090DD38 /* Polyglot.swift in Sources */, 824DAA6B1CDB80E10077F93A /* CommandLineParser.swift in Sources */, - A1B73ED11E00ABDE0070D20F /* IntExtension.swift in Sources */, - A1B73ED51E00ABDE0070D20F /* Globals.swift in Sources */, - A1B73ECD1E00ABDE0070D20F /* DictionaryExtension.swift in Sources */, - A1B73ED31E00ABDE0070D20F /* StringExtension.swift in Sources */, + 00CAD6CF1F7A744D0090DD38 /* DispatchTimeIntervalExtension.swift in Sources */, + 00CAD6C91F7A743D0090DD38 /* CommandLineKit.swift in Sources */, 828ED5351C710C2B00E0E947 /* StringsFileUpdater.swift in Sources */, - A1B73EC71E00ABDE0070D20F /* CharacterViewExtension.swift in Sources */, - 82DD98381C7DE18B0065F046 /* Polyglot.swift in Sources */, 828ED5371C710C3100E0E947 /* StringsFilesSearch.swift in Sources */, 824DAA641CDB6F520077F93A /* SubCommander.swift in Sources */, + 00CAD6D21F7A744D0090DD38 /* StringExtension.swift in Sources */, E78B1E151DFAB33900C7C290 /* ExtractLocStringsCommander.swift in Sources */, - A1B73ECF1E00ABDE0070D20F /* IntegerTypeExtension.swift in Sources */, - A1B73ECB1E00ABDE0070D20F /* CoreGraphicsExtensions.swift in Sources */, + 00CAD6CA1F7A743D0090DD38 /* Option.swift in Sources */, + 00CAD6CE1F7A744D0090DD38 /* DictionaryExtension.swift in Sources */, + 00CAD6D91F7A74540090DD38 /* StringExtensionPolyglot.swift in Sources */, 82CDE2761C6ABE5D00055FE6 /* main.swift in Sources */, A140FE0F1D4BD6FB001E0C4B /* Commander.swift in Sources */, - 82DD98391C7DE18B0065F046 /* Session.swift in Sources */, + 00CAD6D11F7A744D0090DD38 /* IntExtension.swift in Sources */, + 00CAD6D81F7A74540090DD38 /* Session.swift in Sources */, + 00CAD6CB1F7A743D0090DD38 /* StringExtensions.swift in Sources */, + 00CAD6CD1F7A744D0090DD38 /* CharacterViewExtension.swift in Sources */, + 00CAD6D41F7A744D0090DD38 /* Globals.swift in Sources */, 824DAA5E1CDB60E00077F93A /* CommandLineActor.swift in Sources */, - A1FF9DA41D9324F900D5E85E /* StringExtensions.swift in Sources */, E78B1E181DFABB1900C7C290 /* CodeCommander.swift in Sources */, 824DAA5F1CDB60E90077F93A /* GenStringsCommander.swift in Sources */, - 82053A241CD3221900434DAD /* StringExtensionPolyglot.swift in Sources */, - A1B73ED71E00ABDE0070D20F /* FrequencyTable.swift in Sources */, - A1B73EC91E00ABDE0070D20F /* ColorExtension.swift in Sources */, + 00CAD6D01F7A744D0090DD38 /* IntegerTypeExtension.swift in Sources */, + 00CAD6D31F7A744D0090DD38 /* TimeIntervalExtension.swift in Sources */, + 00CAD6D61F7A744D0090DD38 /* SortedArray.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -836,34 +817,34 @@ buildActionMask = 2147483647; files = ( 82125E931D0312CF00B9C66B /* Commander.swift in Sources */, - 82DD98361C7DE1560065F046 /* Session.swift in Sources */, + 00CAD6C71F7A6F110090DD38 /* Session.swift in Sources */, + 00CAD6BB1F7A6F0A0090DD38 /* ArrayExtension.swift in Sources */, E78B1E141DFAB33200C7C290 /* ExtractLocStringsCommander.swift in Sources */, + 00CAD6B81F7A6EF80090DD38 /* CommandLineKit.swift in Sources */, + 00CAD6C51F7A6F0A0090DD38 /* SortedArray.swift in Sources */, 824DAA5D1CDB60E00077F93A /* CommandLineActor.swift in Sources */, - A1B73ED81E00ABDE0070D20F /* SortedArray.swift in Sources */, - A1FF9D9F1D9324F900D5E85E /* CommandLineKit.swift in Sources */, - A1B73ED21E00ABDE0070D20F /* StringExtension.swift in Sources */, - A1B73EC61E00ABDE0070D20F /* CharacterViewExtension.swift in Sources */, + 00CAD6C01F7A6F0A0090DD38 /* IntExtension.swift in Sources */, 821DED3A1C70CFBB00B8353B /* StringsFilesSearch.swift in Sources */, - A1B73ED01E00ABDE0070D20F /* IntExtension.swift in Sources */, + 00CAD6C21F7A6F0A0090DD38 /* TimeIntervalExtension.swift in Sources */, 82CDE2E01C6BF35500055FE6 /* StringsFileUpdater.swift in Sources */, + 00CAD6C41F7A6F0A0090DD38 /* FrequencyTable.swift in Sources */, E7974AFE1DFAECA700E31754 /* SwiftExample3Arguments.swift in Sources */, - A1B73EC81E00ABDE0070D20F /* ColorExtension.swift in Sources */, - A1B73ED41E00ABDE0070D20F /* Globals.swift in Sources */, + 00CAD6B91F7A6EF80090DD38 /* Option.swift in Sources */, + 00CAD6BA1F7A6EF80090DD38 /* StringExtensions.swift in Sources */, 82463DFA1CD910FD00D28A2C /* GenStringsCommander.swift in Sources */, - A1B73ECE1E00ABDE0070D20F /* IntegerTypeExtension.swift in Sources */, + 00CAD6C61F7A6F110090DD38 /* Polyglot.swift in Sources */, + 00CAD6C31F7A6F0A0090DD38 /* Globals.swift in Sources */, E7974AFD1DFAECA700E31754 /* SwiftExample2Arguments.swift in Sources */, - A1B73ECA1E00ABDE0070D20F /* CoreGraphicsExtensions.swift in Sources */, - A1B73ED61E00ABDE0070D20F /* FrequencyTable.swift in Sources */, E7974B011DFAFD2D00E31754 /* SwiftExample4Arguments.swift in Sources */, - A1FF9DA11D9324F900D5E85E /* Option.swift in Sources */, - A1B73ECC1E00ABDE0070D20F /* DictionaryExtension.swift in Sources */, - 82053A231CD3221900434DAD /* StringExtensionPolyglot.swift in Sources */, 82CDE2EB1C6BF9D900055FE6 /* IBToolCommander.swift in Sources */, - A1FF9DA31D9324F900D5E85E /* StringExtensions.swift in Sources */, - A1B73EC41E00ABDE0070D20F /* ArrayExtension.swift in Sources */, - 82DD98351C7DE1560065F046 /* Polyglot.swift in Sources */, + 00CAD6BC1F7A6F0A0090DD38 /* CharacterViewExtension.swift in Sources */, + 00CAD6BE1F7A6F0A0090DD38 /* DispatchTimeIntervalExtension.swift in Sources */, + 00CAD6BD1F7A6F0A0090DD38 /* DictionaryExtension.swift in Sources */, + 00CAD6C81F7A6F110090DD38 /* StringExtensionPolyglot.swift in Sources */, 824DAA6A1CDB80E10077F93A /* CommandLineParser.swift in Sources */, + 00CAD6BF1F7A6F0A0090DD38 /* IntegerTypeExtension.swift in Sources */, E78B1E171DFABA5500C7C290 /* CodeCommander.swift in Sources */, + 00CAD6C11F7A6F0A0090DD38 /* StringExtension.swift in Sources */, 824DAA631CDB6F520077F93A /* SubCommander.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -961,14 +942,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -1013,14 +1000,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -1057,6 +1050,7 @@ MACOSX_DEPLOYMENT_TARGET = 10.11; PRODUCT_NAME = bartycrouch; SDKROOT = macosx; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -1068,6 +1062,7 @@ PRODUCT_NAME = bartycrouch; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -1092,7 +1087,7 @@ SDKROOT = macosx; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -1116,7 +1111,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -1135,7 +1130,7 @@ SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "Tests/Supporting Files/BartyCrouchTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -1153,7 +1148,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OBJC_BRIDGING_HEADER = "Tests/Supporting Files/BartyCrouchTests-Bridging-Header.h"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/AF463047-11C0-4394-8F30-AA5C0CDDCEA1.plist b/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/AF463047-11C0-4394-8F30-AA5C0CDDCEA1.plist new file mode 100644 index 0000000..4b55873 --- /dev/null +++ b/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/AF463047-11C0-4394-8F30-AA5C0CDDCEA1.plist @@ -0,0 +1,32 @@ + + + + + classNames + + StringsFileUpdaterTests + + testIncrementallyUpdateKeysPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.9942 + baselineIntegrationDisplayName + Local Baseline + + + testInitPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.04819 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/Info.plist b/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/Info.plist index bf7c339..39ffd02 100644 --- a/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/Info.plist +++ b/BartyCrouch.xcodeproj/xcshareddata/xcbaselines/82CDE2871C6ABF3A00055FE6.xcbaseline/Info.plist @@ -28,6 +28,30 @@ targetArchitecture x86_64 + AF463047-11C0-4394-8F30-AA5C0CDDCEA1 + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 2900 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro14,3 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + C69D606B-F80F-42E0-B169-81AA93D17265 localComputer diff --git a/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouch CLI.xcscheme b/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouch CLI.xcscheme index 17a411e..ca7d869 100644 --- a/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouch CLI.xcscheme +++ b/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouch CLI.xcscheme @@ -1,6 +1,6 @@ @@ -45,6 +46,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouchKit.xcscheme b/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouchKit.xcscheme index a7529d6..bf091de 100644 --- a/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouchKit.xcscheme +++ b/BartyCrouch.xcodeproj/xcshareddata/xcschemes/BartyCrouchKit.xcscheme @@ -1,6 +1,6 @@ 1.4 +github "Flinesoft/HandySwift" ~> 2.4 diff --git a/Cartfile.resolved b/Cartfile.resolved index 8c69ff2..0b9eb20 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ -github "Dschee/CommandLine" "5a87809cae05941cb996ce925f885e7a60602dcc" -github "Flinesoft/Handyswift" "1.4.1" -github "Dschee/Polyglot" "df05686560c1943eb7175921a697cb65852aaeaf" +github "Dschee/Polyglot" "8a0ee9879f973e2e9f90d8136989b5a743f7bcb8" +github "Flinesoft/HandySwift" "2.4.0" +github "pdesantis/CommandLine" "bf0e1eb1df769cadea8bae75c4acf1c140aa2449" diff --git a/Carthage/Checkouts/CommandLine/.gitignore b/Carthage/Checkouts/CommandLine/.gitignore index 5668d16..a2e1c0a 100644 --- a/Carthage/Checkouts/CommandLine/.gitignore +++ b/Carthage/Checkouts/CommandLine/.gitignore @@ -2,6 +2,7 @@ # build/ .build/ +.build-linux *.pbxuser !default.pbxuser *.mode1v3 @@ -17,4 +18,5 @@ DerivedData *.hmap *.ipa *.xcuserstate +.DS_Store diff --git a/Carthage/Checkouts/CommandLine/.travis.yml b/Carthage/Checkouts/CommandLine/.travis.yml index ef6ac7c..b4c8b76 100644 --- a/Carthage/Checkouts/CommandLine/.travis.yml +++ b/Carthage/Checkouts/CommandLine/.travis.yml @@ -5,21 +5,12 @@ matrix: xcode_project: CommandLine.xcodeproj xcode_scheme: CommandLine script: xcodebuild -scheme CommandLine test - osx_image: xcode7.3 - - os: osx - language: objective-c # this is a lie - xcode_project: CommandLine.xcodeproj - xcode_scheme: CommandLine - script: xcodebuild -scheme CommandLine test - osx_image: xcode8 + osx_image: xcode8.2 - os: linux - sudo: required dist: trusty + sudo: false + services: docker before_install: - - sudo apt-get install -y clang libicu-dev - - sudo locale-gen sv_SE.UTF-8 # for alternate-locale tests - - ./install-linux-swift.sh - - export PATH="/swift/usr/bin:${PATH}" + - docker pull swiftdocker/swift:latest script: - - swift build -v - - swift test + - docker run -v "$(pwd):/src" swiftdocker/swift:latest /src/script/test diff --git a/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/project.pbxproj b/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/project.pbxproj index b2439e0..66c553d 100644 --- a/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/project.pbxproj +++ b/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/project.pbxproj @@ -8,8 +8,8 @@ /* Begin PBXBuildFile section */ 5D06884F19674D7D00BBFAAC /* CommandLineKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D06884319674D7D00BBFAAC /* CommandLineKit.framework */; }; - 5D06885619674D7D00BBFAAC /* CommandLineKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D06885519674D7D00BBFAAC /* CommandLineKitTests.swift */; }; - 5D06886019674DA600BBFAAC /* CommandLineKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D06885F19674DA600BBFAAC /* CommandLineKit.swift */; }; + 5D06885619674D7D00BBFAAC /* CommandLineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D06885519674D7D00BBFAAC /* CommandLineTests.swift */; }; + 5D06886019674DA600BBFAAC /* CommandLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D06885F19674DA600BBFAAC /* CommandLine.swift */; }; 5D068867196A212A00BBFAAC /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D068866196A212A00BBFAAC /* Option.swift */; }; 5D449A18198B015E00F9A8A6 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D449A17198B015E00F9A8A6 /* StringExtensions.swift */; }; 5D8DC809198D8BA0007CD61B /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D8DC808198D8BA0007CD61B /* StringExtensionTests.swift */; }; @@ -80,8 +80,8 @@ 5D06884719674D7D00BBFAAC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5D06884E19674D7D00BBFAAC /* CommandLineKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CommandLineKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5D06885419674D7D00BBFAAC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Tests/CommandLineKitTests/Info.plist; sourceTree = SOURCE_ROOT; }; - 5D06885519674D7D00BBFAAC /* CommandLineKitTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = CommandLineKitTests.swift; path = Tests/CommandLineKitTests/CommandLineKitTests.swift; sourceTree = SOURCE_ROOT; tabWidth = 2; usesTabs = 0; }; - 5D06885F19674DA600BBFAAC /* CommandLineKit.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = CommandLineKit.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; + 5D06885519674D7D00BBFAAC /* CommandLineTests.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = CommandLineTests.swift; path = Tests/CommandLineKitTests/CommandLineTests.swift; sourceTree = SOURCE_ROOT; tabWidth = 2; usesTabs = 0; }; + 5D06885F19674DA600BBFAAC /* CommandLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = CommandLine.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5D068866196A212A00BBFAAC /* Option.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Option.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5D449A17198B015E00F9A8A6 /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5D449B63198B412E00F9A8A6 /* ReadMe.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ReadMe.md; sourceTree = ""; }; @@ -138,7 +138,7 @@ 5D06884519674D7D00BBFAAC /* CommandLineKit */ = { isa = PBXGroup; children = ( - 5D06885F19674DA600BBFAAC /* CommandLineKit.swift */, + 5D06885F19674DA600BBFAAC /* CommandLine.swift */, 5D068866196A212A00BBFAAC /* Option.swift */, 5D449A17198B015E00F9A8A6 /* StringExtensions.swift */, 5D06884619674D7D00BBFAAC /* Supporting Files */, @@ -157,7 +157,7 @@ 5D06885219674D7D00BBFAAC /* CommandLineKitTests */ = { isa = PBXGroup; children = ( - 5D06885519674D7D00BBFAAC /* CommandLineKitTests.swift */, + 5D06885519674D7D00BBFAAC /* CommandLineTests.swift */, 5D8DC808198D8BA0007CD61B /* StringExtensionTests.swift */, 5D06885319674D7D00BBFAAC /* Supporting Files */, ); @@ -236,7 +236,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0810; ORGANIZATIONNAME = "Ben Gollmer"; TargetAttributes = { 5D06884219674D7D00BBFAAC = { @@ -292,7 +292,7 @@ files = ( 5D449A18198B015E00F9A8A6 /* StringExtensions.swift in Sources */, 5D068867196A212A00BBFAAC /* Option.swift in Sources */, - 5D06886019674DA600BBFAAC /* CommandLineKit.swift in Sources */, + 5D06886019674DA600BBFAAC /* CommandLine.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -300,7 +300,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5D06885619674D7D00BBFAAC /* CommandLineKitTests.swift in Sources */, + 5D06885619674D7D00BBFAAC /* CommandLineTests.swift in Sources */, 5D8DC809198D8BA0007CD61B /* StringExtensionTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -365,8 +365,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; @@ -413,8 +415,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; diff --git a/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/xcshareddata/xcschemes/CommandLine.xcscheme b/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/xcshareddata/xcschemes/CommandLine.xcscheme index 10b7d26..a13d7b4 100644 --- a/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/xcshareddata/xcschemes/CommandLine.xcscheme +++ b/Carthage/Checkouts/CommandLine/CommandLineKit.xcodeproj/xcshareddata/xcschemes/CommandLine.xcscheme @@ -1,6 +1,6 @@ { + var usedFlags = Set(minimumCapacity: _options.count * 2) + + for option in _options { + for case let flag? in [option.shortFlag, option.longFlag] { + usedFlags.insert(flag) + } + } + + return usedFlags + } + + /** + * After calling `parse()`, this property will contain any values that weren't captured + * by an Option. For example: + * + * ``` + * let cli = CommandLine() + * let fileType = StringOption(shortFlag: "t", longFlag: "type", required: true, helpMessage: "Type of file") + * + * do { + * try cli.parse() + * print("File type is \(type), files are \(cli.unparsedArguments)") + * catch { + * cli.printUsage(error) + * exit(EX_USAGE) + * } + * + * --- + * + * $ ./readfiles --type=pdf ~/file1.pdf ~/file2.pdf + * File type is pdf, files are ["~/file1.pdf", "~/file2.pdf"] + * ``` + */ + public private(set) var unparsedArguments: [String] = [String]() + + /** + * If supplied, this function will be called when printing usage messages. + * + * You can use the `defaultFormat` function to get the normally-formatted + * output, either before or after modifying the provided string. For example: + * + * ``` + * let cli = CommandLine() + * cli.formatOutput = { str, type in + * switch(type) { + * case .Error: + * // Make errors shouty + * return defaultFormat(str.uppercaseString, type: type) + * case .OptionHelp: + * // Don't use the default indenting + * return ">> \(s)\n" + * default: + * return defaultFormat(str, type: type) + * } + * } + * ``` + * + * - note: Newlines are not appended to the result of this function. If you don't use + * `defaultFormat()`, be sure to add them before returning. + */ + public var formatOutput: ((String, OutputType) -> String)? + + /** + * The maximum width of all options' `flagDescription` properties; provided for use by + * output formatters. + * + * - seealso: `defaultFormat`, `formatOutput` + */ + public var maxFlagDescriptionWidth: Int { + if _maxFlagDescriptionWidth == 0 { + _maxFlagDescriptionWidth = _options.map { $0.flagDescription.characters.count }.sorted().first ?? 0 + } + + return _maxFlagDescriptionWidth + } + + /** + * The type of output being supplied to an output formatter. + * + * - seealso: `formatOutput` + */ + public enum OutputType { + /** About text: `Usage: command-example [options]` and the like */ + case about + + /** An error message: `Missing required option --extract` */ + case error + + /** An Option's `flagDescription`: `-h, --help:` */ + case optionFlag + + /** An Option's help message */ + case optionHelp + } + + /** A ParseError is thrown if the `parse()` method fails. */ + public enum ParseError: Error, CustomStringConvertible { + /** Thrown if an unrecognized argument is passed to `parse()` in strict mode */ + case invalidArgument(String) + + /** Thrown if the value for an Option is invalid (e.g. a string is passed to an IntOption) */ + case invalidValueForOption(Option, [String]) + + /** Thrown if an Option with required: true is missing */ + case missingRequiredOptions([Option]) + + public var description: String { + switch self { + case let .invalidArgument(arg): + return "Invalid argument: \(arg)" + case let .invalidValueForOption(opt, vals): + let vs = vals.joined(separator: ", ") + return "Invalid value(s) for option \(opt.flagDescription): \(vs)" + case let .missingRequiredOptions(opts): + return "Missing required options: \(opts.map { return $0.flagDescription })" + } + } + } + + /** + * Initializes a CommandLine object. + * + * - parameter arguments: Arguments to parse. If omitted, the arguments passed to the app + * on the command line will automatically be used. + * + * - returns: An initalized CommandLine object. + */ + public init(arguments: [String] = Swift.CommandLine.arguments) { + self._arguments = arguments + + /* Initialize locale settings from the environment */ + setlocale(LC_ALL, "") + } + + /* Returns all argument values from flagIndex to the next flag or the end of the argument array. */ + private func _getFlagValues(_ flagIndex: Int, _ attachedArg: String? = nil) -> [String] { + var args: [String] = [String]() + var skipFlagChecks = false + + if let a = attachedArg { + args.append(a) + } + + for i in flagIndex + 1 ..< _arguments.count { + if !skipFlagChecks { + if _arguments[i] == argumentStopper { + skipFlagChecks = true + continue + } + + if _arguments[i].hasPrefix(shortOptionPrefix) && Int(_arguments[i]) == nil && + _arguments[i].toDouble() == nil { + break + } + } + + args.append(_arguments[i]) + } + + return args + } + + /** + * Adds an Option to the command line. + * + * - parameter option: The option to add. + */ + public func addOption(_ option: Option) { + let uf = _usedFlags + for case let flag? in [option.shortFlag, option.longFlag] { + assert(!uf.contains(flag), "Flag '\(flag)' already in use") + } + + _options.append(option) + _maxFlagDescriptionWidth = 0 + } + + /** + * Adds one or more Options to the command line. + * + * - parameter options: An array containing the options to add. + */ + public func addOptions(_ options: [Option]) { + for o in options { + addOption(o) + } + } + + /** + * Adds one or more Options to the command line. + * + * - parameter options: The options to add. + */ + public func addOptions(_ options: Option...) { + for o in options { + addOption(o) + } + } + + /** + * Sets the command line Options. Any existing options will be overwritten. + * + * - parameter options: An array containing the options to set. + */ + public func setOptions(_ options: [Option]) { + _options = [Option]() + addOptions(options) + } + + /** + * Sets the command line Options. Any existing options will be overwritten. + * + * - parameter options: The options to set. + */ + public func setOptions(_ options: Option...) { + _options = [Option]() + addOptions(options) + } + + /** + * Parses command-line arguments into their matching Option values. + * + * - parameter strict: Fail if any unrecognized flags are present (default: false). + * + * - throws: A `ParseError` if argument parsing fails: + * - `.InvalidArgument` if an unrecognized flag is present and `strict` is true + * - `.InvalidValueForOption` if the value supplied to an option is not valid (for + * example, a string is supplied for an IntOption) + * - `.MissingRequiredOptions` if a required option isn't present + */ + public func parse(strict: Bool = false) throws { + var strays = _arguments + + /* Nuke executable name */ + strays[0] = "" + + let argumentsEnumerator = _arguments.enumerated() + for (idx, arg) in argumentsEnumerator { + if arg == argumentStopper { + break + } + + if !arg.hasPrefix(shortOptionPrefix) { + continue + } + + let skipChars = arg.hasPrefix(longOptionPrefix) ? + longOptionPrefix.characters.count : shortOptionPrefix.characters.count + let flagWithArg = arg[arg.index(arg.startIndex, offsetBy: skipChars)..=3.2) + let splitFlag = flagWithArg.split(separator: argumentAttacher, maxSplits: 1) + let flag = String(splitFlag[0]) + let attachedArg: String? = splitFlag.count == 2 ? String(splitFlag[1]) : nil +#else + let splitFlag = flagWithArg.split(by: argumentAttacher, maxSplits: 1) + let flag = splitFlag[0] + let attachedArg: String? = splitFlag.count == 2 ? splitFlag[1] : nil +#endif + + var flagMatched = false + for option in _options where option.flagMatch(flag) { + let vals = self._getFlagValues(idx, attachedArg) + guard option.setValue(vals) else { + throw ParseError.invalidValueForOption(option, vals) + } + + var claimedIdx = idx + option.claimedValues + if attachedArg != nil { claimedIdx -= 1 } + for i in idx...claimedIdx { + strays[i] = "" + } + + flagMatched = true + break + } + + /* Flags that do not take any arguments can be concatenated */ + let flagLength = flag.characters.count + if !flagMatched && !arg.hasPrefix(longOptionPrefix) { + let flagCharactersEnumerator = flag.characters.enumerated() + for (i, c) in flagCharactersEnumerator { + for option in _options where option.flagMatch(String(c)) { + /* Values are allowed at the end of the concatenated flags, e.g. + * -xvf + */ + let vals = (i == flagLength - 1) ? self._getFlagValues(idx, attachedArg) : [String]() + guard option.setValue(vals) else { + throw ParseError.invalidValueForOption(option, vals) + } + + var claimedIdx = idx + option.claimedValues + if attachedArg != nil { claimedIdx -= 1 } + for i in idx...claimedIdx { + strays[i] = "" + } + + flagMatched = true + break + } + } + } + + /* Invalid flag */ + guard !strict || flagMatched else { + throw ParseError.invalidArgument(arg) + } + } + + /* Check to see if any required options were not matched */ + let missingOptions = _options.filter { $0.required && !$0.wasSet } + guard missingOptions.count == 0 else { + throw ParseError.missingRequiredOptions(missingOptions) + } + + unparsedArguments = strays.filter { $0 != "" } + } + + /** + * Provides the default formatting of `printUsage()` output. + * + * - parameter s: The string to format. + * - parameter type: Type of output. + * + * - returns: The formatted string. + * - seealso: `formatOutput` + */ + public func defaultFormat(s: String, type: OutputType) -> String { + switch type { + case .about: + return "\(s)\n" + case .error: + return "\(s)\n\n" + case .optionFlag: + return " \(s.padded(toWidth: maxFlagDescriptionWidth)):\n" + case .optionHelp: + return " \(s)\n" + } + } + + /* printUsage() is generic for OutputStreamType because the Swift compiler crashes + * on inout protocol function parameters in Xcode 7 beta 1 (rdar://21372694). + */ + + /** + * Prints a usage message. + * + * - parameter to: An OutputStreamType to write the error message to. + */ + public func printUsage(_ to: inout TargetStream) { + /* Nil coalescing operator (??) doesn't work on closures :( */ + let format = formatOutput != nil ? formatOutput! : defaultFormat + + let name = _arguments[0] + print(format("Usage: \(name) [options]", .about), terminator: "", to: &to) + + for opt in _options { + print(format(opt.flagDescription, .optionFlag), terminator: "", to: &to) + print(format(opt.helpMessage, .optionHelp), terminator: "", to: &to) + } + } + + /** + * Prints a usage message. + * + * - parameter error: An error thrown from `parse()`. A description of the error + * (e.g. "Missing required option --extract") will be printed before the usage message. + * - parameter to: An OutputStreamType to write the error message to. + */ + public func printUsage(_ error: Error, to: inout TargetStream) { + let format = formatOutput != nil ? formatOutput! : defaultFormat + print(format("\(error)", .error), terminator: "", to: &to) + printUsage(&to) + } + + /** + * Prints a usage message. + * + * - parameter error: An error thrown from `parse()`. A description of the error + * (e.g. "Missing required option --extract") will be printed before the usage message. + */ + public func printUsage(_ error: Error) { + var out = StderrOutputStream.stream + printUsage(error, to: &out) + } + + /** + * Prints a usage message. + */ + public func printUsage() { + var out = StderrOutputStream.stream + printUsage(&out) + } +} diff --git a/Carthage/Checkouts/CommandLine/CommandLineKit/Option.swift b/Carthage/Checkouts/CommandLine/CommandLineKit/Option.swift index 82b8efd..051e258 100644 --- a/Carthage/Checkouts/CommandLine/CommandLineKit/Option.swift +++ b/Carthage/Checkouts/CommandLine/CommandLineKit/Option.swift @@ -18,27 +18,27 @@ /** * The base class for a command-line option. */ -open class Option { - open let shortFlag: String? - open let longFlag: String? - open let required: Bool - open let helpMessage: String - +public class Option { + public let shortFlag: String? + public let longFlag: String? + public let required: Bool + public let helpMessage: String + /** True if the option was set when parsing command-line arguments */ - open var wasSet: Bool { + public var wasSet: Bool { return false } - open var claimedValues: Int { return 0 } + public var claimedValues: Int { return 0 } - open var flagDescription: String { + public var flagDescription: String { switch (shortFlag, longFlag) { case let (sf?, lf?): - return "\(ShortOptionPrefix)\(sf), \(LongOptionPrefix)\(lf)" + return "\(shortOptionPrefix)\(sf), \(longOptionPrefix)\(lf)" case (nil, let lf?): - return "\(LongOptionPrefix)\(lf)" + return "\(longOptionPrefix)\(lf)" case (let sf?, nil): - return "\(ShortOptionPrefix)\(sf)" + return "\(shortOptionPrefix)\(sf)" default: return "" } @@ -49,100 +49,82 @@ open class Option { assert(sf.characters.count == 1, "Short flag must be a single character") assert(Int(sf) == nil && sf.toDouble() == nil, "Short flag cannot be a numeric value") } - + if let lf = longFlag { assert(Int(lf) == nil && lf.toDouble() == nil, "Long flag cannot be a numeric value") } - + self.shortFlag = shortFlag self.longFlag = longFlag self.helpMessage = helpMessage self.required = required } - + /* The optional casts in these initalizers force them to call the private initializer. Without * the casts, they recursively call themselves. */ - + /** Initializes a new Option that has both long and short flags. */ public convenience init(shortFlag: String, longFlag: String, required: Bool = false, helpMessage: String) { self.init(shortFlag as String?, longFlag, required, helpMessage) } - + /** Initializes a new Option that has only a short flag. */ public convenience init(shortFlag: String, required: Bool = false, helpMessage: String) { self.init(shortFlag as String?, nil, required, helpMessage) } - + /** Initializes a new Option that has only a long flag. */ public convenience init(longFlag: String, required: Bool = false, helpMessage: String) { self.init(nil, longFlag as String?, required, helpMessage) } - #if swift(>=3.0) - func flagMatch(_ flag: String) -> Bool { - return flag == shortFlag || flag == longFlag - } - - func setValue(_ values: [String]) -> Bool { - return false - } - #else func flagMatch(_ flag: String) -> Bool { return flag == shortFlag || flag == longFlag } - + func setValue(_ values: [String]) -> Bool { return false } - #endif } /** * A boolean option. The presence of either the short or long flag will set the value to true; * absence of the flag(s) is equivalent to false. */ -open class BoolOption: Option { - fileprivate var _value: Bool = false - - open var value: Bool { +public class BoolOption: Option { + private var _value: Bool = false + + public var value: Bool { return _value } - override open var wasSet: Bool { + override public var wasSet: Bool { return _value } - #if swift(>=3.0) override func setValue(_ values: [String]) -> Bool { _value = true return true } - #else - override func setValue(_ values: [String]) -> Bool { - _value = true - return true - } - #endif } /** An option that accepts a positive or negative integer value. */ -open class IntOption: Option { - fileprivate var _value: Int? - - open var value: Int? { +public class IntOption: Option { + private var _value: Int? + + public var value: Int? { return _value } - - override open var wasSet: Bool { + + override public var wasSet: Bool { return _value != nil } - override open var claimedValues: Int { + override public var claimedValues: Int { return _value != nil ? 1 : 0 } - #if swift(>=3.0) override func setValue(_ values: [String]) -> Bool { if values.count == 0 { return false @@ -155,72 +137,49 @@ open class IntOption: Option { return false } - #else - override func setValue(_ values: [String]) -> Bool { - if values.count == 0 { - return false - } - - if let val = Int(values[0]) { - _value = val - return true - } - - return false - } - #endif } /** * An option that represents an integer counter. Each time the short or long flag is found * on the command-line, the counter will be incremented. */ -open class CounterOption: Option { - fileprivate var _value: Int = 0 - - open var value: Int { +public class CounterOption: Option { + private var _value: Int = 0 + + public var value: Int { return _value } - - override open var wasSet: Bool { + + override public var wasSet: Bool { return _value > 0 } - open func reset() { + public func reset() { _value = 0 } - #if swift(>=3.0) override func setValue(_ values: [String]) -> Bool { _value += 1 return true } - #else - override func setValue(_ values: [String]) -> Bool { - _value += 1 - return true - } - #endif } /** An option that accepts a positive or negative floating-point value. */ -open class DoubleOption: Option { - fileprivate var _value: Double? - - open var value: Double? { +public class DoubleOption: Option { + private var _value: Double? + + public var value: Double? { return _value } - override open var wasSet: Bool { + override public var wasSet: Bool { return _value != nil } - override open var claimedValues: Int { + override public var claimedValues: Int { return _value != nil ? 1 : 0 } - #if swift(>=3.0) - override func setValue(_ values: [String]) -> Bool { if values.count == 0 { return false @@ -233,43 +192,24 @@ open class DoubleOption: Option { return false } - - #else - - override func setValue(_ values: [String]) -> Bool { - if values.count == 0 { - return false - } - - if let val = values[0].toDouble() { - _value = val - return true - } - - return false - } - - #endif } /** An option that accepts a string value. */ -open class StringOption: Option { - fileprivate var _value: String? = nil - - open var value: String? { +public class StringOption: Option { + private var _value: String? = nil + + public var value: String? { return _value } - - override open var wasSet: Bool { + + override public var wasSet: Bool { return _value != nil } - override open var claimedValues: Int { + override public var claimedValues: Int { return _value != nil ? 1 : 0 } - #if swift(>=3.0) - override func setValue(_ values: [String]) -> Bool { if values.count == 0 { return false @@ -278,34 +218,21 @@ open class StringOption: Option { _value = values[0] return true } - - #else - - override func setValue(_ values: [String]) -> Bool { - if values.count == 0 { - return false - } - - _value = values[0] - return true - } - - #endif } /** An option that accepts one or more string values. */ -open class MultiStringOption: Option { - fileprivate var _value: [String]? - - open var value: [String]? { +public class MultiStringOption: Option { + private var _value: [String]? + + public var value: [String]? { return _value } - - override open var wasSet: Bool { + + override public var wasSet: Bool { return _value != nil } - override open var claimedValues: Int { + override public var claimedValues: Int { if let v = _value { return v.count } @@ -313,19 +240,6 @@ open class MultiStringOption: Option { return 0 } - #if swift(>=3.0) - - override func setValue(_ values: [String]) -> Bool { - if values.count == 0 { - return false - } - - _value = values - return true - } - - #else - override func setValue(_ values: [String]) -> Bool { if values.count == 0 { return false @@ -334,12 +248,8 @@ open class MultiStringOption: Option { _value = values return true } - - #endif } -#if swift(>=3.0) - /** An option that represents an enum value. */ public class EnumOption: Option where T.RawValue == String { private var _value: T? @@ -392,59 +302,3 @@ public class EnumOption: Option where T.RawValue == String { } } - -#else - -open class EnumOption: Option { - fileprivate var _value: T? - open var value: T? { - return _value - } - - override open var wasSet: Bool { - return _value != nil - } - - override open var claimedValues: Int { - return _value != nil ? 1 : 0 - } - - /* Re-defining the intializers is necessary to make the Swift 2 compiler happy, as - * of Xcode 7 beta 2. - */ - - fileprivate override init(_ shortFlag: String?, _ longFlag: String?, _ required: Bool, _ helpMessage: String) { - super.init(shortFlag, longFlag, required, helpMessage) - } - - /** Initializes a new Option that has both long and short flags. */ - public convenience init(shortFlag: String, longFlag: String, required: Bool = false, helpMessage: String) { - self.init(shortFlag as String?, longFlag, required, helpMessage) - } - - /** Initializes a new Option that has only a short flag. */ - public convenience init(shortFlag: String, required: Bool = false, helpMessage: String) { - self.init(shortFlag as String?, nil, required, helpMessage) - } - - /** Initializes a new Option that has only a long flag. */ - public convenience init(longFlag: String, required: Bool = false, helpMessage: String) { - self.init(nil, longFlag as String?, required, helpMessage) - } - - override func setValue(_ values: [String]) -> Bool { - if values.count == 0 { - return false - } - - if let v = T(rawValue: values[0]) { - _value = v - return true - } - - return false - } - -} - -#endif diff --git a/Carthage/Checkouts/CommandLine/CommandLineKit/StringExtensions.swift b/Carthage/Checkouts/CommandLine/CommandLineKit/StringExtensions.swift index f9a4bef..7b0a570 100644 --- a/Carthage/Checkouts/CommandLine/CommandLineKit/StringExtensions.swift +++ b/Carthage/Checkouts/CommandLine/CommandLineKit/StringExtensions.swift @@ -26,22 +26,12 @@ internal extension String { /* Retrieves locale-specified decimal separator from the environment * using localeconv(3). */ - fileprivate func _localDecimalPoint() -> Character { - let locale = localeconv() - if locale != nil { - #if swift(>=3.0) - if let decimalPoint = locale?.pointee.decimal_point { - return Character(UnicodeScalar(UInt32(decimalPoint.pointee))!) - } - #else - let decimalPoint = locale.pointee.decimal_point - if decimalPoint != nil { - return Character(UnicodeScalar(UInt32(decimalPoint.pointee))) - } - #endif + private func _localDecimalPoint() -> Character { + guard let locale = localeconv(), let decimalPoint = locale.pointee.decimal_point else { + return "." } - return "." + return Character(UnicodeScalar(UInt8(bitPattern: decimalPoint.pointee))) } /** @@ -50,47 +40,12 @@ internal extension String { * - returns: A Double if the string can be parsed, nil otherwise. */ func toDouble() -> Double? { - var characteristic: String = "0" - var mantissa: String = "0" - var inMantissa: Bool = false - var isNegative: Bool = false - let decimalPoint = self._localDecimalPoint() - - #if swift(>=3.0) - let charactersEnumerator = self.characters.enumerated() - #else - let charactersEnumerator = self.characters.enumerated() - #endif - for (i, c) in charactersEnumerator { - if i == 0 && c == "-" { - isNegative = true - continue - } - - if c == decimalPoint { - inMantissa = true - continue - } - - if Int(String(c)) != nil { - if !inMantissa { - characteristic.append(c) - } else { - mantissa.append(c) - } - } else { - /* Non-numeric character found, bail */ - return nil - } - } - - let doubleCharacteristic = Double(Int(characteristic)!) - return (doubleCharacteristic + - Double(Int(mantissa)!) / pow(Double(10), Double(mantissa.characters.count - 1))) * - (isNegative ? -1 : 1) + let decimalPoint = String(self._localDecimalPoint()) + guard decimalPoint == "." || self.range(of: ".") == nil else { return nil } + let localeSelf = self.replacingOccurrences(of: decimalPoint, with: ".") + return Double(localeSelf) } - #if swift(>=3.0) /** * Splits a string into an array of string components. * @@ -107,52 +62,27 @@ internal extension String { for i in self.characters.indices { let c = self[i] if c == by && (maxSplits == 0 || numSplits < maxSplits) { +#if swift(>=3.2) + s.append(String(self[curIdx..=3.2) + s.append(String(self[curIdx.. [String] { - var s = [String]() - var numSplits = 0 - - var curIdx = self.startIndex - for i in self.characters.indices { - let c = self[i] - if c == by && (maxSplits == 0 || numSplits < maxSplits) { - s.append(self[curIdx...index(after: i) - numSplits += 1 - } - } - - if curIdx != self.endIndex { - s.append(self[curIdx..(shortFlag: "o", longFlag: "operation", required: true, helpMessage: "File operation - c for create, x for extract, l for list, or v for verify.") cli.setOptions(op) diff --git a/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/CommandLineKitTests.swift b/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/CommandLineTests.swift similarity index 77% rename from Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/CommandLineKitTests.swift rename to Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/CommandLineTests.swift index 4732a83..5b6cbb2 100644 --- a/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/CommandLineKitTests.swift +++ b/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/CommandLineTests.swift @@ -15,14 +15,9 @@ * limitations under the License. */ -import XCTest import Foundation +import XCTest @testable import CommandLineKit -#if os(OSX) - import Darwin -#elseif os(Linux) - import Glibc -#endif internal class CommandLineTests: XCTestCase { static var allTests : [(String, (CommandLineTests) -> () throws -> Void)] { @@ -64,7 +59,7 @@ internal class CommandLineTests: XCTestCase { } func testBoolOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "--bool", "-c", "-c", "-ddd" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "--bool", "-c", "-c", "-ddd" ]) /* Short flag */ let a = BoolOption(shortFlag: "a", longFlag: "a1", helpMessage: "") @@ -100,7 +95,7 @@ internal class CommandLineTests: XCTestCase { } func testIntOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "1", "--bigs", "2", "-c", "3", + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "1", "--bigs", "2", "-c", "3", "-c", "4", "-ddd", "-e", "bad", "-f", "-g", "-5" ]) /* Short flag */ @@ -118,9 +113,9 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!, 1, "Failed to get correct value from short int") - XCTAssertEqual(b.value!, 2, "Failed to get correct value from long int") - XCTAssertEqual(c.value!, 4, "Failed to get correct value from multi-flagged int") + XCTAssertEqual(a.value, 1, "Failed to get correct value from short int") + XCTAssertEqual(b.value, 2, "Failed to get correct value from long int") + XCTAssertEqual(c.value, 4, "Failed to get correct value from multi-flagged int") } catch { XCTFail("Failed to parse int options: \(error)") } @@ -145,7 +140,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed invalid int option") - } catch let CommandLineKit.ParseError.InvalidValueForOption(opt, vals) { + } catch let CommandLineKit.CommandLine.ParseError.invalidValueForOption(opt, vals) { XCTAssert(opt === e, "Incorrect option in ParseError: \(opt.longFlag)") XCTAssertEqual(vals, ["bad"], "Incorrect values in ParseError: \(vals)") XCTAssertNil(e.value, "Got non-nil value from invalid int") @@ -160,7 +155,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed int option with no value") - } catch let CommandLineKit.ParseError.InvalidValueForOption(opt, vals) { + } catch let CommandLineKit.CommandLine.ParseError.invalidValueForOption(opt, vals) { XCTAssert(opt === f, "Incorrect option in ParseError: \(opt.longFlag)") XCTAssertEqual(vals, [], "Incorrect values in ParseError: \(vals)") XCTAssertNil(f.value, "Got non-nil value from no value int") @@ -174,14 +169,14 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(g.value!, -5, "Failed to get correct value from int option with negative value") + XCTAssertEqual(g.value, -5, "Failed to get correct value from int option with negative value") } catch { XCTFail("Failed to parse int option with negative value: \(error)") } } func testCounterOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "--bach", "-c", "-c", + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "--bach", "-c", "-c", "--doggerel", "-doggerel", "--doggerel", "-eeee"]) /* Short flag */ @@ -220,7 +215,7 @@ internal class CommandLineTests: XCTestCase { } func testDoubleOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "1.4", "--baritone", "2.5", + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "1.4", "--baritone", "2.5", "-c", "5.0", "-c", "5.2", "--dingus", "8.5", "--dingus", "8.8", "-e", "95", "-f", "bad", "-g", "-h", "-3.14159" ]) @@ -245,11 +240,11 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!, 1.4, "Failed to get correct value from short double") - XCTAssertEqual(b.value!, 2.5, "Failed to get correct value from long double") - XCTAssertEqual(c.value!, 5.2, "Failed to get correct value from multi-flagged short double") - XCTAssertEqual(d.value!, 8.8, "Failed to get correct value from multi-flagged long double") - XCTAssertEqual(e.value!, 95.0, "Failed to get correct double value from integer argument") + XCTAssertEqual(a.value, 1.4, "Failed to get correct value from short double") + XCTAssertEqual(b.value, 2.5, "Failed to get correct value from long double") + XCTAssertEqual(c.value, 5.2, "Failed to get correct value from multi-flagged short double") + XCTAssertEqual(d.value, 8.8, "Failed to get correct value from multi-flagged long double") + XCTAssertEqual(e.value, 95.0, "Failed to get correct double value from integer argument") } catch { XCTFail("Failed to parse double options: \(error)") } @@ -261,7 +256,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed invalid double option") - } catch let CommandLineKit.ParseError.InvalidValueForOption(opt, vals) { + } catch let CommandLineKit.CommandLine.ParseError.invalidValueForOption(opt, vals) { XCTAssert(opt === f, "Incorrect option in ParseError: \(opt.longFlag)") XCTAssertEqual(vals, ["bad"], "Incorrect values in ParseError: \(vals)") XCTAssertNil(f.value, "Got non-nil value from invalid double") @@ -277,7 +272,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed double option with no value") - } catch let CommandLineKit.ParseError.InvalidValueForOption(opt, vals) { + } catch let CommandLineKit.CommandLine.ParseError.invalidValueForOption(opt, vals) { XCTAssert(opt === g, "Incorrect option in ParseError: \(opt.longFlag)") XCTAssertEqual(vals, [], "Incorrect values in ParseError: \(vals)") XCTAssertNil(g.value, "Got non-nil value from no value double") @@ -291,14 +286,14 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(h.value!, -3.14159, "Failed to get correct value from double with negative value") + XCTAssertEqual(h.value, -3.14159, "Failed to get correct value from double with negative value") } catch { XCTFail("Failed to parse double option with negative value: \(error)") } } func testDoubleOptionsInAlternateLocale() { - let cli = CommandLineKit(arguments: ["CommandLineTests", "-a", "3,14159"]) + let cli = CommandLine(arguments: ["CommandLineTests", "-a", "3,14159"]) let a = DoubleOption(shortFlag: "a", longFlag: "a1", required: true, helpMessage: "") cli.addOptions(a) @@ -307,14 +302,14 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!, 3.14159, "Failed to get correct value from double in alternate locale") + XCTAssertEqual(a.value, 3.14159, "Failed to get correct value from double in alternate locale") } catch { XCTFail("Failed to parse double options in alternate locale: \(error)") } } func testStringOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "one", "--b1", "two", "-c", "x", "-c", "xx", + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "one", "--b1", "two", "-c", "x", "-c", "xx", "--d1", "y", "--d1", "yy", "-e" ]) /* Short flag */ @@ -333,10 +328,10 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!, "one", "Failed to get correct value from short string") - XCTAssertEqual(b.value!, "two", "Failed to get correct value from long string") - XCTAssertEqual(c.value!, "xx", "Failed to get correct value from multi-flagged short string") - XCTAssertEqual(d.value!, "yy", "Failed to get correct value from multi-flagged long string") + XCTAssertEqual(a.value, "one", "Failed to get correct value from short string") + XCTAssertEqual(b.value, "two", "Failed to get correct value from long string") + XCTAssertEqual(c.value, "xx", "Failed to get correct value from multi-flagged short string") + XCTAssertEqual(d.value, "yy", "Failed to get correct value from multi-flagged long string") } catch { XCTFail("Failed to parse string options: \(error)") } @@ -348,7 +343,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed string option with no value") - } catch let CommandLineKit.ParseError.InvalidValueForOption(opt, vals) { + } catch let CommandLineKit.CommandLine.ParseError.invalidValueForOption(opt, vals) { XCTAssert(opt === e, "Incorrect option in ParseError: \(opt.longFlag)") XCTAssertEqual(vals, [], "Incorrect values in ParseError: \(vals)") XCTAssertNil(e.value, "Got non-nil value from no value string") @@ -358,7 +353,7 @@ internal class CommandLineTests: XCTestCase { } func testMultiStringOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "one", "-b", "two", "2wo", + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "one", "-b", "two", "2wo", "--c1", "three", "--d1", "four", "4our", "-e" ]) /* Short flags */ @@ -373,16 +368,16 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!.count, 1, "Failed to get correct number of values from single short multistring") - XCTAssertEqual(a.value![0], "one", "Filed to get correct value from single short multistring") - XCTAssertEqual(b.value!.count, 2, "Failed to get correct number of values from multi short multistring") - XCTAssertEqual(b.value![0], "two", "Failed to get correct first value from multi short multistring") - XCTAssertEqual(b.value![1], "2wo", "Failed to get correct second value from multi short multistring") - XCTAssertEqual(c.value!.count, 1, "Failed to get correct number of values from single long multistring") - XCTAssertEqual(c.value![0], "three", "Filed to get correct value from single long multistring") - XCTAssertEqual(d.value!.count, 2, "Failed to get correct number of values from multi long multistring") - XCTAssertEqual(d.value![0], "four", "Failed to get correct first value from multi long multistring") - XCTAssertEqual(d.value![1], "4our", "Failed to get correct second value from multi long multistring") + XCTAssertEqual(a.value?.count, 1, "Failed to get correct number of values from single short multistring") + XCTAssertEqual(a.value?[0], "one", "Filed to get correct value from single short multistring") + XCTAssertEqual(b.value?.count, 2, "Failed to get correct number of values from multi short multistring") + XCTAssertEqual(b.value?[0], "two", "Failed to get correct first value from multi short multistring") + XCTAssertEqual(b.value?[1], "2wo", "Failed to get correct second value from multi short multistring") + XCTAssertEqual(c.value?.count, 1, "Failed to get correct number of values from single long multistring") + XCTAssertEqual(c.value?[0], "three", "Filed to get correct value from single long multistring") + XCTAssertEqual(d.value?.count, 2, "Failed to get correct number of values from multi long multistring") + XCTAssertEqual(d.value?[0], "four", "Failed to get correct first value from multi long multistring") + XCTAssertEqual(d.value?[1], "4our", "Failed to get correct second value from multi long multistring") } catch { XCTFail("Failed to parse multi string options: \(error)") } @@ -394,7 +389,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed multi string option with no value") - } catch let CommandLineKit.ParseError.InvalidValueForOption(opt, vals) { + } catch let CommandLineKit.CommandLine.ParseError.invalidValueForOption(opt, vals) { XCTAssert(opt === e, "Incorrect option in ParseError: \(opt.longFlag)") XCTAssertEqual(vals, [], "Incorrect values in ParseError: \(vals)") XCTAssertNil(e.value, "Got non-nil value from no value multistring") @@ -404,7 +399,7 @@ internal class CommandLineTests: XCTestCase { } func testConcatOptionWithValue() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-xvf", "file1", "file2" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-xvf", "file1", "file2" ]) let x = BoolOption(shortFlag: "x", longFlag: "x1", helpMessage: "") let v = CounterOption(shortFlag: "v", longFlag: "v1", helpMessage: "") @@ -416,16 +411,16 @@ internal class CommandLineTests: XCTestCase { try cli.parse() XCTAssertTrue(x.value as Bool, "Failed to get true value from concat flags with value") XCTAssertEqual(v.value, 1, "Failed to get correct value from concat flags with value") - XCTAssertEqual(f.value!.count, 2, "Failed to get values from concat flags with value") - XCTAssertEqual(f.value![0], "file1", "Failed to get first value from concat flags with value") - XCTAssertEqual(f.value![1], "file2", "Failed to get second value from concat flags with value") + XCTAssertEqual(f.value?.count, 2, "Failed to get values from concat flags with value") + XCTAssertEqual(f.value?[0], "file1", "Failed to get first value from concat flags with value") + XCTAssertEqual(f.value?[1], "file2", "Failed to get second value from concat flags with value") } catch { XCTFail("Failed to parse concat flags with value: \(error)") } } func testMissingRequiredOption() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "-b", "foo", "-q", "quux" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "-b", "foo", "-q", "quux" ]) let c = StringOption(shortFlag: "c", longFlag: "c1", required: true, helpMessage: "") cli.addOption(c) @@ -433,7 +428,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTFail("Parsed missing required option") - } catch let CommandLineKit.ParseError.MissingRequiredOptions(opts) { + } catch let CommandLineKit.CommandLine.ParseError.missingRequiredOptions(opts) { XCTAssert(opts[0] === c, "Failed to identify missing required options: \(opts)") XCTAssertNil(c.value, "Got non-nil value from missing option") } catch { @@ -442,7 +437,7 @@ internal class CommandLineTests: XCTestCase { } func testAttachedArgumentValues() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a=5", "--bb=klaxon" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-a=5", "--bb=klaxon" ]) let a = IntOption(shortFlag: "a", longFlag: "a1", required: true, helpMessage: "") let b = StringOption(shortFlag: "b", longFlag: "bb", required: true, helpMessage: "") @@ -451,15 +446,15 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!, 5, "Failed to get correct int attached value") - XCTAssertEqual(b.value!, "klaxon", "Failed to get correct string attached value") + XCTAssertEqual(a.value, 5, "Failed to get correct int attached value") + XCTAssertEqual(b.value, "klaxon", "Failed to get correct string attached value") } catch { XCTFail("Failed to parse attached argument values: \(error)") } } func testEmojiOptions() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-👻", "3", "--👍", "☀️" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-👻", "3", "--👍", "☀️" ]) let a = IntOption(shortFlag: "👻", longFlag: "👻", required: true, helpMessage: "") let b = StringOption(shortFlag: "👍", longFlag: "👍", required: true, helpMessage: "") @@ -469,8 +464,8 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(a.value!, 3) - XCTAssertEqual(b.value!, "☀️") + XCTAssertEqual(a.value, 3) + XCTAssertEqual(b.value, "☀️") } catch { XCTFail("Failed to parse emoji options: \(error)") } @@ -478,37 +473,37 @@ internal class CommandLineTests: XCTestCase { func testEnumOption() { enum Operation: String { - case Create = "c" - case Extract = "x" - case List = "l" - case Verify = "v" + case create = "c" + case extract = "x" + case list = "l" + case verify = "v" } - let cli = CommandLineKit(arguments: [ "CommandLineTests", "--operation", "x" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "--operation", "x" ]) let op = EnumOption(shortFlag: "o", longFlag: "operation", required: true, helpMessage: "") cli.setOptions(op) do { try cli.parse() - XCTAssertEqual(op.value!, Operation.Extract, "Failed to get correct value from enum option") + XCTAssertEqual(op.value, Operation.extract, "Failed to get correct value from enum option") } catch { XCTFail("Failed to parse enum options: \(error)") } } func testArgumentStopper() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "--", "-value", "--", "-55" ]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "--", "-value", "--", "-55" ]) let op = MultiStringOption(shortFlag: "a", longFlag: "a1", required: true, helpMessage: "") cli.setOptions(op) do { try cli.parse() - XCTAssertEqual(op.value!.count, 3, "Failed to get correct number of options with stopper") - XCTAssertEqual(op.value![0], "-value", "Failed to get correct value from options with stopper") - XCTAssertEqual(op.value![1], "--", "Failed to get correct value from options with stopper") - XCTAssertEqual(op.value![2], "-55", "Failed to get correct value from options with stopper") + XCTAssertEqual(op.value?.count, 3, "Failed to get correct number of options with stopper") + XCTAssertEqual(op.value?[0], "-value", "Failed to get correct value from options with stopper") + XCTAssertEqual(op.value?[1], "--", "Failed to get correct value from options with stopper") + XCTAssertEqual(op.value?[2], "-55", "Failed to get correct value from options with stopper") } catch { XCTFail("Failed to parse options with an argument stopper: \(error)") } @@ -524,7 +519,7 @@ internal class CommandLineTests: XCTestCase { ] for args in argLines { - let cli = CommandLineKit(arguments: args) + let cli = CommandLine(arguments: args) let extract = BoolOption(shortFlag: "x", longFlag: "extract", helpMessage: "") let verbosity = CounterOption(shortFlag: "v", longFlag: "verbose", helpMessage: "") let filePath = StringOption(shortFlag: "f", longFlag: "file", required: true, helpMessage: "") @@ -535,7 +530,7 @@ internal class CommandLineTests: XCTestCase { try cli.parse() XCTAssertEqual(extract.value, true, "Failed to parse extract value from arg line \(args)") XCTAssertEqual(verbosity.value, 1, "Failed to parse verbosity value from arg line \(args)") - XCTAssertEqual(filePath.value!, "/path/to/file", "Failed to parse file path value from arg line \(args)") + XCTAssertEqual(filePath.value, "/path/to/file", "Failed to parse file path value from arg line \(args)") } catch { XCTFail("Failed to parse arg line \(args): \(error)") } @@ -543,7 +538,7 @@ internal class CommandLineTests: XCTestCase { } func testEmptyFlags() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-", "--"]) + let cli = CommandLine(arguments: [ "CommandLineTests", "-", "--"]) do { try cli.parse() @@ -558,7 +553,7 @@ internal class CommandLineTests: XCTestCase { /* func testShortFlagReuse() { - let cli = CommandLineKit(arguments: []) + let cli = CommandLine(arguments: []) let op1 = BoolOption(shortFlag: "v", longFlag: "verbose", helpMessage: "") let op2 = StringOption(shortFlag: "v", longFlag: "verify", helpMessage: "") cli.addOptions(op1, op2) @@ -566,7 +561,7 @@ internal class CommandLineTests: XCTestCase { } func testLongFlagReuse() { - let cli = CommandLineKit(arguments: []) + let cli = CommandLine(arguments: []) let op1 = BoolOption(shortFlag: "v", longFlag: "verbose", helpMessage: "") let op2 = StringOption(shortFlag: "d", longFlag: "verbose", helpMessage: "") cli.addOptions(op1, op2) @@ -574,7 +569,7 @@ internal class CommandLineTests: XCTestCase { } func testSetOptionFlagReuse() { - let cli = CommandLineKit(arguments: []) + let cli = CommandLine(arguments: []) let opts = [ BoolOption(shortFlag: "v", longFlag: "verbose", helpMessage: ""), StringOption(shortFlag: "v", longFlag: "verify", helpMessage: "") @@ -586,14 +581,14 @@ internal class CommandLineTests: XCTestCase { */ func testDifferentCaseFlagReuse() { - let cli = CommandLineKit(arguments: []) + let cli = CommandLine(arguments: []) let op1 = BoolOption(shortFlag: "v", longFlag: "verbose", helpMessage: "") let op2 = StringOption(shortFlag: "V", longFlag: "verify", helpMessage: "") cli.addOptions(op1, op2) } func testMixedExample() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-dvvv", "--name", "John Q. Public", + let cli = CommandLine(arguments: [ "CommandLineTests", "-dvvv", "--name", "John Q. Public", "-f", "45", "-p", "0.05", "-x", "extra1", "extra2", "extra3" ]) setlocale(LC_ALL, "C") @@ -616,17 +611,17 @@ internal class CommandLineTests: XCTestCase { try cli.parse() XCTAssertTrue(boolOpt.value, "Failed to get correct bool value from mixed command line") XCTAssertEqual(counterOpt.value, 3, "Failed to get correct counter value from mixed command line") - XCTAssertEqual(stringOpt.value!, "John Q. Public", "Failed to get correct string value from mixed command line") - XCTAssertEqual(intOpt.value!, 45, "Failed to get correct int value from mixed command line") - XCTAssertEqual(doubleOpt.value!, 0.05, "Failed to get correct double value from mixed command line") - XCTAssertEqual(extraOpt.value!.count , 3, "Failed to get correct number of multistring options from mixed command line") + XCTAssertEqual(stringOpt.value, "John Q. Public", "Failed to get correct string value from mixed command line") + XCTAssertEqual(intOpt.value, 45, "Failed to get correct int value from mixed command line") + XCTAssertEqual(doubleOpt.value, 0.05, "Failed to get correct double value from mixed command line") + XCTAssertEqual(extraOpt.value?.count , 3, "Failed to get correct number of multistring options from mixed command line") } catch { XCTFail("Failed to parse mixed command line: \(error)") } } func testWasSetProperty() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-a", "-b", "-c", "str", "-d", "1", + let cli = CommandLine(arguments: [ "CommandLineTests", "-a", "-b", "-c", "str", "-d", "1", "-e", "3.14159", "-f", "extra1", "extra2", "extra3" ]) setlocale(LC_ALL, "C") @@ -666,7 +661,7 @@ internal class CommandLineTests: XCTestCase { } func testShortFlagOnlyOption() { - let cli = CommandLineKit(arguments: ["-s", "itchy", "--itchy", "scratchy"]) + let cli = CommandLine(arguments: ["-s", "itchy", "--itchy", "scratchy"]) let o1 = StringOption(shortFlag: "s", helpMessage: "short only") let o2 = StringOption(shortFlag: "i", helpMessage: "another short") @@ -674,7 +669,7 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() - XCTAssertEqual(o1.value!, "itchy", "Failed to get correct string value from short-flag-only option") + XCTAssertEqual(o1.value, "itchy", "Failed to get correct string value from short-flag-only option") XCTAssertNil(o2.value, "Incorrectly set value for short-flag-only option") } catch { XCTFail("Failed to parse short-flag-only command line: \(error)") @@ -682,7 +677,7 @@ internal class CommandLineTests: XCTestCase { } func testLongFlagOnlyOption() { - let cli = CommandLineKit(arguments: ["-s", "itchy", "--itchy", "scratchy"]) + let cli = CommandLine(arguments: ["-s", "itchy", "--itchy", "scratchy"]) let o1 = StringOption(longFlag: "scratchy", helpMessage: "long only") let o2 = StringOption(longFlag: "itchy", helpMessage: "long short") @@ -691,14 +686,14 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTAssertNil(o1.value, "Incorrectly set value for long-flag-only option") - XCTAssertEqual(o2.value!, "scratchy", "Failed to get correct string value from long-flag-only option") + XCTAssertEqual(o2.value, "scratchy", "Failed to get correct string value from long-flag-only option") } catch { XCTFail("Failed to parse long-flag-only command line: \(error)") } } func testStrictMode() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "--valid", "--invalid"]) + let cli = CommandLine(arguments: [ "CommandLineTests", "--valid", "--invalid"]) let validOpt = BoolOption(shortFlag: "v", longFlag: "valid", helpMessage: "Known flag.") cli.addOptions(validOpt) @@ -709,13 +704,9 @@ internal class CommandLineTests: XCTestCase { } do { - #if swift(>=3.0) - try cli.parse(strict: true) - #else - try cli.parse(true) - #endif + try cli.parse(strict: true) XCTFail("Successfully parsed invalid flags in strict mode") - } catch let CommandLineKit.ParseError.InvalidArgument(arg) { + } catch let CommandLineKit.CommandLine.ParseError.invalidArgument(arg) { XCTAssertEqual(arg, "--invalid", "Incorrect argument identified in InvalidArgument: \(arg)") } catch { XCTFail("Unexpected parse error: \(error)") @@ -723,7 +714,7 @@ internal class CommandLineTests: XCTestCase { } func testUnparsedArguments() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "onefish", "twofish", "-b", "redfish", "-c", "green", "blue", "-xvvi", "9", "-w", "--who", "--formats=json", "xml", "binary", "--verbose", "fish", "--type=pdf", "woo!"]) + let cli = CommandLine(arguments: [ "CommandLineTests", "onefish", "twofish", "-b", "redfish", "-c", "green", "blue", "-xvvi", "9", "-w", "--who", "--formats=json", "xml", "binary", "--verbose", "fish", "--type=pdf", "woo!"]) let o1 = BoolOption(shortFlag: "b", longFlag: "bool", helpMessage: "Boolean option") let o2 = StringOption(shortFlag: "c", longFlag: "color", helpMessage: "String option") let o3 = BoolOption(shortFlag: "x", longFlag: "extract", helpMessage: "Combined bool option") @@ -737,34 +728,30 @@ internal class CommandLineTests: XCTestCase { do { try cli.parse() XCTAssertTrue(o1.value, "Failed to set bool option with stray values") - XCTAssertEqual(o2.value!, "green", "Incorrect value for string option with stray values") + XCTAssertEqual(o2.value, "green", "Incorrect value for string option with stray values") XCTAssertTrue(o3.value, "Failed to set combined bool option with stray values") XCTAssertEqual(o4.value, 3, "Incorrect value for combined counter option with stray values") - XCTAssertEqual(o5.value!, 9, "Incorrect value for combined int option with stray values") - XCTAssertEqual(o6.value!, ["json", "xml", "binary"], "Incorrect value for attached multistring option with stray values") - XCTAssertEqual(o7.value!, "pdf", "Incorrect value for attached string option with stray values") + XCTAssertEqual(o5.value, 9, "Incorrect value for combined int option with stray values") + XCTAssertEqual(o6.value ?? [], ["json", "xml", "binary"], "Incorrect value for attached multistring option with stray values") + XCTAssertEqual(o7.value, "pdf", "Incorrect value for attached string option with stray values") XCTAssertEqual(cli.unparsedArguments, ["onefish", "twofish", "redfish", "blue", "-w", "--who", "fish", "woo!"], "Incorrect unparsed values") } catch { XCTFail("Unexpected parse error: \(error)") } do { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "onefish", "twofish", "-b", "redfish", "-c", "green", "blue", "-xvvi", "9", "--formats=json", "xml", "binary", "--verbose", "fish", "--type=pdf", "woo!"]) + let cli = CommandLine(arguments: [ "CommandLineTests", "onefish", "twofish", "-b", "redfish", "-c", "green", "blue", "-xvvi", "9", "--formats=json", "xml", "binary", "--verbose", "fish", "--type=pdf", "woo!"]) o4.reset() cli.addOptions(o1, o2, o3, o4, o5, o6, o7) - #if swift(>=3.0) - try cli.parse(strict: true) - #else - try cli.parse(true) - #endif + try cli.parse(strict: true) XCTAssertTrue(o1.value, "Failed to set bool option with stray values") - XCTAssertEqual(o2.value!, "green", "Incorrect value for string option with stray values") + XCTAssertEqual(o2.value, "green", "Incorrect value for string option with stray values") XCTAssertTrue(o3.value, "Failed to set combined bool option with stray values") XCTAssertEqual(o4.value, 3, "Incorrect value for combined counter option with stray values") - XCTAssertEqual(o5.value!, 9, "Incorrect value for combined int option with stray values") - XCTAssertEqual(o6.value!, ["json", "xml", "binary"], "Incorrect value for attached multistring option with stray values") - XCTAssertEqual(o7.value!, "pdf", "Incorrect value for attached string option with stray values") + XCTAssertEqual(o5.value, 9, "Incorrect value for combined int option with stray values") + XCTAssertEqual(o6.value ?? [], ["json", "xml", "binary"], "Incorrect value for attached multistring option with stray values") + XCTAssertEqual(o7.value, "pdf", "Incorrect value for attached string option with stray values") XCTAssertEqual(cli.unparsedArguments, ["onefish", "twofish", "redfish", "blue", "fish", "woo!"], "Incorrect unparsed values") } catch { XCTFail("Stray values should not cause a throw in strict mode") @@ -772,7 +759,7 @@ internal class CommandLineTests: XCTestCase { } func testInvalidArgumentErrorDescription() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "--int", "invalid"]) + let cli = CommandLine(arguments: [ "CommandLineTests", "--int", "invalid"]) let o1 = IntOption(longFlag: "int", helpMessage: "Int flag.") cli.addOptions(o1) @@ -784,7 +771,7 @@ internal class CommandLineTests: XCTestCase { } func testMissingRequiredOptionsErrorDescription() { - let cli = CommandLineKit(arguments: [ "CommandLineTests"]) + let cli = CommandLine(arguments: [ "CommandLineTests"]) let o1 = IntOption(longFlag: "int", required: true, helpMessage: "Int flag.") cli.addOptions(o1) @@ -797,7 +784,7 @@ internal class CommandLineTests: XCTestCase { } func testPrintUsage() { - let cli = CommandLineKit(arguments: [ "CommandLineTests", "-dvvv", "--name", "John Q. Public", + let cli = CommandLine(arguments: [ "CommandLineTests", "-dvvv", "--name", "John Q. Public", "-f", "45", "-p", "0.05", "-x", "extra1", "extra2", "extra3" ]) let boolOpt = BoolOption(shortFlag: "d", longFlag: "debug", helpMessage: "Enables debug mode.") @@ -824,7 +811,7 @@ internal class CommandLineTests: XCTestCase { } func testPrintUsageError() { - let cli = CommandLineKit(arguments: [ "CommandLineTests" ]) + let cli = CommandLine(arguments: [ "CommandLineTests" ]) cli.addOption(StringOption(shortFlag: "n", longFlag: "name", required: true, helpMessage: "Your name")) @@ -841,7 +828,7 @@ internal class CommandLineTests: XCTestCase { } func testPrintUsageToStderr() { - let cli = CommandLineKit(arguments: [ "CommandLineTests" ]) + let cli = CommandLine(arguments: [ "CommandLineTests" ]) cli.addOption(StringOption(shortFlag: "n", longFlag: "name", required: true, helpMessage: "Your name")) @@ -857,7 +844,7 @@ internal class CommandLineTests: XCTestCase { fclose(null) } - let error = CommandLineKit.ParseError.InvalidArgument("ack") + let error = CommandLine.ParseError.invalidArgument("ack") /* Just make sure these doesn't crash or throw */ cli.printUsage() @@ -865,7 +852,7 @@ internal class CommandLineTests: XCTestCase { } func testCustomOutputFormatter() { - let cli = CommandLineKit(arguments: [ "CommandLineTests" ]) + let cli = CommandLine(arguments: [ "CommandLineTests" ]) cli.formatOutput = { s, type in switch type { case .about: @@ -905,11 +892,7 @@ internal class CommandLineTests: XCTestCase { XCTAssertTrue(o[0].hasPrefix("[ERROR]")) XCTAssertTrue(o[1].hasPrefix("[ABOUT]")) - #if swift(>=3.0) - let range = stride(from: 2, to: opts.count, by: 2) - #else - let range = 2.stride(to: opts.count, by: 2) - #endif + let range = stride(from: 2, to: opts.count, by: 2) for i in range { XCTAssertTrue(o[i].hasPrefix("[FLAG]")) XCTAssertTrue(o[i + 1].hasPrefix("[HELP]")) diff --git a/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/StringExtensionTests.swift b/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/StringExtensionTests.swift index 4e19e50..0e237b9 100644 --- a/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/StringExtensionTests.swift +++ b/Carthage/Checkouts/CommandLine/Tests/CommandLineKitTests/StringExtensionTests.swift @@ -15,13 +15,9 @@ * limitations under the License. */ +import Foundation import XCTest @testable import CommandLineKit -#if os(OSX) - import Darwin -#elseif os(Linux) - import Glibc -#endif class StringExtensionTests: XCTestCase { static var allTests : [(String, (StringExtensionTests) -> () throws -> Void)] { @@ -75,8 +71,8 @@ class StringExtensionTests: XCTestCase { /* Various extraneous chars */ - let k = "+42.3".toDouble() - XCTAssertNil(k, "Parsed double with extraneous +") + let k = "+42.3".toDouble() // 4 Jan 2017: leading + is valid language syntax + XCTAssertEqual(k, 42.3, "Failed to parse double with leading +") let l = " 827.2".toDouble() XCTAssertNil(l, "Parsed double with extraneous space") @@ -91,7 +87,7 @@ class StringExtensionTests: XCTestCase { setlocale(LC_NUMERIC, "sv_SE.UTF-8") let o = "888,8".toDouble() - XCTAssertEqual(o!, 888.8, "Failed to parse double in alternate locale") + XCTAssert(o == 888.8, "Failed to parse double in alternate locale") let p = "888.8".toDouble() XCTAssertNil(p, "Parsed double in alternate locale with wrong decimal point") @@ -128,19 +124,11 @@ class StringExtensionTests: XCTestCase { a.characters.count, "Bad padding with negative pad width") let b = a.padded(toWidth: 80) - #if swift(>=3.0) - let lastBCharIndex = b.index(before: b.endIndex) - #else - let lastBCharIndex = b.endIndex.advancedBy(-1) - #endif + let lastBCharIndex = b.index(before: b.endIndex) XCTAssertEqual(b[lastBCharIndex], " " as Character, "Failed to pad with default character") let c = a.padded(toWidth: 80, with: "+") - #if swift(>=3.0) - let lastCCharIndex = c.index(before: b.endIndex) - #else - let lastCCharIndex = c.endIndex.advancedBy(-1) - #endif + let lastCCharIndex = c.index(before: b.endIndex) XCTAssertEqual(c[lastCCharIndex], "+" as Character, "Failed to pad with specified character") } diff --git a/Carthage/Checkouts/CommandLine/install-linux-swift.sh b/Carthage/Checkouts/CommandLine/install-linux-swift.sh deleted file mode 100755 index 07a19d0..0000000 --- a/Carthage/Checkouts/CommandLine/install-linux-swift.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -set -ev -SWIFT_SNAPSHOT="swift-3.0-PREVIEW-6" -XCTEST_SNAPSHOT="swift-3.0-PREVIEW-6" - -echo "Installing ${SWIFT_SNAPSHOT}..." -if [ ! -f "${SWIFT_SNAPSHOT}-ubuntu14.04.tar.gz" ]; then - curl -s -L -O "https://swift.org/builds/$(echo $SWIFT_SNAPSHOT | tr A-Z a-z)/ubuntu1404/${SWIFT_SNAPSHOT}/${SWIFT_SNAPSHOT}-ubuntu14.04.tar.gz" -fi - -tar -zxf "${SWIFT_SNAPSHOT}-ubuntu14.04.tar.gz" -sudo rm -rf /swift -sudo mv "${SWIFT_SNAPSHOT}-ubuntu14.04" /swift - -# Force the use of the gold linker -# See https://bugs.swift.org/browse/SR-1023 and https://github.com/apple/swift/pull/2609 -sudo rm /usr/bin/ld -sudo ln -s /usr/bin/ld.gold /usr/bin/ld - -echo "Installing XCTest..." -if [ ! -f "${XCTEST_SNAPSHOT}.tar.gz" ]; then - curl -s -L -O "https://github.com/apple/swift-corelibs-xctest/archive/${XCTEST_SNAPSHOT}.tar.gz" -fi -tar -zxvf "${XCTEST_SNAPSHOT}.tar.gz" -cd "swift-corelibs-xctest-${XCTEST_SNAPSHOT}" -sudo ./build_script.py --swiftc="/swift/usr/bin/swiftc" --build-dir="/tmp/XCTest_build" --foundation-build-dir="/swift/usr/lib/swift/linux" --library-install-path="/swift/usr/lib/swift/linux" --module-install-path="/swift/usr/lib/swift/linux/x86_64" -cd .. -rm -rf "swift-corelibs-xctest-${XCTEST_SNAPSHOT}" diff --git a/Carthage/Checkouts/CommandLine/script/test b/Carthage/Checkouts/CommandLine/script/test new file mode 100755 index 0000000..dfcc0a8 --- /dev/null +++ b/Carthage/Checkouts/CommandLine/script/test @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +cd "$(dirname $0)/../" + +BUILD_PATH=".build" +if [ "$(uname)" != "Darwin" ]; then + BUILD_PATH=".build-linux" +fi + +locale-gen sv_SE.UTF-8 + +swift build -Xlinker -L/usr/local/lib --build-path $BUILD_PATH -v +swift test -Xlinker -L/usr/local/lib --build-path $BUILD_PATH diff --git a/Carthage/Checkouts/Handyswift/.swift-version b/Carthage/Checkouts/Handyswift/.swift-version index 9f55b2c..5186d07 100644 --- a/Carthage/Checkouts/Handyswift/.swift-version +++ b/Carthage/Checkouts/Handyswift/.swift-version @@ -1 +1 @@ -3.0 +4.0 diff --git a/Carthage/Checkouts/Handyswift/.swiftlint.yml b/Carthage/Checkouts/Handyswift/.swiftlint.yml index 960b5db..127c661 100644 --- a/Carthage/Checkouts/Handyswift/.swiftlint.yml +++ b/Carthage/Checkouts/Handyswift/.swiftlint.yml @@ -1,9 +1,29 @@ opt_in_rules: +- attributes +- closure_end_indentation +- closure_spacing - empty_count -# - missing_docs +- explicit_init +- file_header +- first_where +- let_var_whitespace +- nimble_operator +- no_extension_access_modifier +- number_separator +- object_literal +- operator_usage_whitespace +- overridden_super_call +- private_outlet +- prohibited_super_call +- redundant_nil_coalescing +- sorted_imports +- switch_case_on_newline +- trailing_closure +- unneeded_parentheses_in_closure_argument +- vertical_parameter_alignment_on_call disabled_rules: -- vertical_whitespace +- todo included: - Sources @@ -11,5 +31,114 @@ included: excluded: - Carthage +- Package.swift +- UsageExamples.playground -line_length: 150 +line_length: 160 + +file_header: + required_pattern: | + \/\/ + \/\/ .*?\.swift + \/\/ HandySwift + \/\/ + \/\/ Created by .*? on \S{8,10}\. + \/\/ Copyright © \d{4} Flinesoft\. All rights reserved\. + \/\/ +custom_rules: + closing_brace_whitespace: + included: ".*.swift" + regex: '(?:\n| {2,})\}\)? *\n *[^ \n\})\]]' + name: "Closing Brace Whitespace" + message: "Empty line required after closing curly braces if code with same indentation follows." + severity: warning + closure_params_parantheses: + included: ".*.swift" + regex: '\{\s*\([^):]+\)\s*in' + name: "Unnecessary Closure Params Parantheses" + message: "Don't use parantheses around non-typed parameters in a closure." + severity: warning + if_as_guard: + included: ".*.swift" + regex: '\n *if [^\{]+\{\s*return[^\n]*\n *\}(?! *else)' + name: "If as Guard" + message: "Don't use an if statement to just return – use guard for such cases instead." + severity: warning + late_force_unwrapping: + included: ".*.swift" + regex: '\(\S+\?\.\S+\)!' + name: "Late Force Unwrapping" + message: "Don't use ? first to force unwrap later – directly unwrap within the parantheses." + severity: warning + missing_docs: + included: ".*.swift" + regex: '\n *(?!\/\/\/)(\/\/)?[^\n\/]*\n *(?:@\S+ )*(?:public |open )' + name: "Missing Docs" + message: "Types, properties and methods with public or open access level should be documented." + severity: warning + multiple_closure_params: + included: ".*.swift" + regex: '\} *\) *\{' + name: "Multiple Closure Params" + message: "Don't use multiple in-line closures – save one or more of them to variables instead." + severity: warning + single_line_guard: + included: ".*.swift" + regex: 'guard[^\{]{2,80}else\s*\{\s*\n\s*return.{2,40}\}' + name: "Single Line Guard" + message: "Use a single line guard for simple checks." + severity: warning + too_much_indentation: + included: ".*.swift" + regex: '\n {0}[^\s\/][^\n]*[^,|&]\n+ {5,}\S|\n {4}[^\s\/][^\n]*[^,|&]\n+ {9,}\S|\n {8}[^\s\/][^\n]*[^,|&]\n+ {13,}\S|\n {12}[^\s\/][^\n]*[^,|&]\n+ {17,}\S|\n {16}[^\s\/][^\n]*[^,|&]\n+ {21,}\S|\n {20}[^\s\/][^\n]*[^,|&]\n+ {25,}\S' + name: "Too Much Indentation" + message: "Don't indent code by more than 4 whitespaces." + severity: warning + too_much_unindentation: + included: ".*.swift" + regex: ' {28}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,23}[^\s\/]| {24}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,19}[^\s\/]| {20}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,15}[^\s\/]| {16}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,11}[^\s\/]| {12}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,7}[^\s\/]| {8}[^\s\.](.|[^\n]*[^\)][^\ ][^\}])\n+ {0,3}[^\s\/]' + name: "Too Much Unindentation" + message: "Don't unindent code by more than 4 whitespaces." + severity: warning + unnecessary_case_break: + included: ".*.swift" + regex: '(case |default)(?:[^\n\}]+\n){2,}\s*break|\n *\n *break(?:\n *\n|\n *\})' + name: "Unnecessary Case Break" + message: "Don't use break in switch cases – Swift breaks by default." + severity: warning + unnecessary_nil_assignment: + included: ".*.swift" + regex: 'var \S+\s*:\s*[^\s]+\?\s*=\s*nil' + name: "Unnecessary Nil Assignment" + message: "Don't assign nil as a value when defining an optional type – it's nil by default." + severity: warning + vertical_whitespace_between_cases: + included: ".*.swift" + regex: '[^\n{][ \t]*\n[ \t]*(?:case[^\n]+|default):[ \t]*\n' + name: "Vertical Whitespace Between Cases" + message: "Include a vertical whitespace (empty line) between cases in switch statements." + severity: warning + vertical_whitespaces_around_mark: + included: ".*.swift" + regex: '\/\/\s*MARK:[^\n]*(\n\n)|(\n\n\n)[ \t]*\/\/\s*MARK:|[^\s{]\n[^\n\/]*\/\/\s*MARK:' + name: "Vertical Whitespaces Around MARK:" + message: "Include a single vertical whitespace (empty line) before and none after MARK: comments." + severity: warning + vertical_whitespace_opening_braces: + included: ".*.swift" + regex: '[{(\[][ \t]*\n[ \t]*\n' + name: "Vertical Whitespace after Opening Braces" + message: "Don't include vertical whitespace (empty line) after opening braces." + severity: warning + vertical_whitespace_closing_braces: + included: ".*.swift" + regex: '\n[ \t]*\n[ \t]*[)}\]]' + name: "Vertical Whitespace before Closing Braces" + message: "Don't include vertical whitespace (empty line) before closing braces." + severity: warning + whitespace_comment_start: + included: ".*.swift" + regex: '[^:]\/\/[^\s\/]' + name: "Whitespace Comment Start" + message: "A comment should always start with a whitespace." + severity: warning diff --git a/Carthage/Checkouts/Handyswift/HandySwift.podspec b/Carthage/Checkouts/Handyswift/HandySwift.podspec index 06772fa..a08e41b 100644 --- a/Carthage/Checkouts/Handyswift/HandySwift.podspec +++ b/Carthage/Checkouts/Handyswift/HandySwift.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "HandySwift" - s.version = "1.4.1" + s.version = "2.4.0" s.summary = "Handy Swift features that didn't make it into the Swift standard library" s.description = <<-DESC @@ -20,11 +20,8 @@ Pod::Spec.new do |s| s.osx.deployment_target = "10.10" s.tvos.deployment_target = "9.0" - s.source = { :git => "https://github.com/Flinesoft/HandySwift.git", :tag => "1.4.1" } - s.source_files = "Sources", "Sources/**/*.swift" - s.framework = "Foundation" - s.osx.framework = "AppKit" - s.ios.framework = "UIKit" - s.tvos.framework = "UIKit" + s.source = { :git => "https://github.com/Flinesoft/HandySwift.git", :tag => "#{s.version}" } + s.source_files = "Sources", "Sources/**/*.swift" + s.framework = "Foundation" end diff --git a/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/project.pbxproj b/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/project.pbxproj index b2dbfb8..692ca29 100644 --- a/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/project.pbxproj +++ b/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/project.pbxproj @@ -7,12 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 821F8D641CC40E6E00F9BCD0 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F8D631CC40E6E00F9BCD0 /* ColorExtension.swift */; }; - 821F8D651CC40E6E00F9BCD0 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F8D631CC40E6E00F9BCD0 /* ColorExtension.swift */; }; - 821F8D661CC40E6E00F9BCD0 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F8D631CC40E6E00F9BCD0 /* ColorExtension.swift */; }; - 821F8D6C1CC4222B00F9BCD0 /* ColorExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F8D6B1CC4222B00F9BCD0 /* ColorExtensionTests.swift */; }; - 821F8D6D1CC4222B00F9BCD0 /* ColorExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F8D6B1CC4222B00F9BCD0 /* ColorExtensionTests.swift */; }; - 821F8D6E1CC4222B00F9BCD0 /* ColorExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 821F8D6B1CC4222B00F9BCD0 /* ColorExtensionTests.swift */; }; 823B2B351C24AAB7007B3CDD /* HandySwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 823B2B341C24AAB7007B3CDD /* HandySwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; 823B2B3C1C24AAB7007B3CDD /* HandySwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 823B2B311C24AAB6007B3CDD /* HandySwift.framework */; }; 823B2B4D1C24ABA4007B3CDD /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 823B2B4C1C24ABA4007B3CDD /* IntExtension.swift */; }; @@ -57,12 +51,9 @@ 826F69B01C389DB800B2CC6B /* FrequencyTableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826F69AF1C389DB800B2CC6B /* FrequencyTableTests.swift */; }; 826F69B11C389DB800B2CC6B /* FrequencyTableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826F69AF1C389DB800B2CC6B /* FrequencyTableTests.swift */; }; 826F69B21C389DB800B2CC6B /* FrequencyTableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826F69AF1C389DB800B2CC6B /* FrequencyTableTests.swift */; }; - 827CE9931D07CDE2007A62A8 /* CoreGraphicsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827CE9921D07CDE2007A62A8 /* CoreGraphicsExtensions.swift */; }; - 827CE9941D07CDE2007A62A8 /* CoreGraphicsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827CE9921D07CDE2007A62A8 /* CoreGraphicsExtensions.swift */; }; - 827CE9951D07CDE2007A62A8 /* CoreGraphicsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827CE9921D07CDE2007A62A8 /* CoreGraphicsExtensions.swift */; }; - 827CE9971D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827CE9961D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift */; }; - 827CE9981D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827CE9961D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift */; }; - 827CE9991D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827CE9961D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift */; }; + 827599641E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827599631E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift */; }; + 827599651E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827599631E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift */; }; + 827599661E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827599631E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift */; }; 8280D7DC1C4A6EC9001172EF /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8280D7DB1C4A6EC9001172EF /* DictionaryExtension.swift */; }; 8280D7DD1C4A6EC9001172EF /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8280D7DB1C4A6EC9001172EF /* DictionaryExtension.swift */; }; 8280D7DE1C4A6EC9001172EF /* DictionaryExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8280D7DB1C4A6EC9001172EF /* DictionaryExtension.swift */; }; @@ -79,6 +70,15 @@ 82CAE2941C2ED5E000F934A7 /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAE2931C2ED5E000F934A7 /* StringExtensionTests.swift */; }; 82CAE2961C2EE64900F934A7 /* ArrayExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAE2951C2EE64900F934A7 /* ArrayExtension.swift */; }; 82CAE2981C2EE95200F934A7 /* ArrayExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82CAE2971C2EE95200F934A7 /* ArrayExtensionTests.swift */; }; + A11830D31E589F6700CBE087 /* TimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11830D21E589F6700CBE087 /* TimeIntervalExtension.swift */; }; + A11830D41E589F6700CBE087 /* TimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11830D21E589F6700CBE087 /* TimeIntervalExtension.swift */; }; + A11830D51E589F6700CBE087 /* TimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11830D21E589F6700CBE087 /* TimeIntervalExtension.swift */; }; + A11830D71E58A11D00CBE087 /* TimeIntervalExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11830D61E58A11D00CBE087 /* TimeIntervalExtensionTests.swift */; }; + A11830D81E58A11D00CBE087 /* TimeIntervalExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11830D61E58A11D00CBE087 /* TimeIntervalExtensionTests.swift */; }; + A11830D91E58A11D00CBE087 /* TimeIntervalExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11830D61E58A11D00CBE087 /* TimeIntervalExtensionTests.swift */; }; + A1F221641E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F221631E3CC05100419B06 /* DispatchTimeIntervalExtension.swift */; }; + A1F221651E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F221631E3CC05100419B06 /* DispatchTimeIntervalExtension.swift */; }; + A1F221661E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1F221631E3CC05100419B06 /* DispatchTimeIntervalExtension.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -106,8 +106,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 821F8D631CC40E6E00F9BCD0 /* ColorExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = ""; }; - 821F8D6B1CC4222B00F9BCD0 /* ColorExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorExtensionTests.swift; sourceTree = ""; }; 823B2B311C24AAB6007B3CDD /* HandySwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HandySwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 823B2B341C24AAB7007B3CDD /* HandySwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HandySwift.h; sourceTree = ""; }; 823B2B361C24AAB7007B3CDD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -127,8 +125,7 @@ 825EFDF21C33351300558497 /* HandySwift tvOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "HandySwift tvOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 826F69AB1C3895A300B2CC6B /* FrequencyTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FrequencyTable.swift; sourceTree = ""; }; 826F69AF1C389DB800B2CC6B /* FrequencyTableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FrequencyTableTests.swift; sourceTree = ""; }; - 827CE9921D07CDE2007A62A8 /* CoreGraphicsExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreGraphicsExtensions.swift; sourceTree = ""; }; - 827CE9961D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreGraphicsExtensionsTests.swift; sourceTree = ""; }; + 827599631E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchTimeIntervalExtensionTests.swift; sourceTree = ""; }; 8280D7DB1C4A6EC9001172EF /* DictionaryExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryExtension.swift; sourceTree = ""; }; 8280D7DF1C4A6FF3001172EF /* DictionaryExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryExtensionTests.swift; sourceTree = ""; }; 82812A9A1D06877B00CD5B6C /* Globals.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; }; @@ -138,9 +135,13 @@ 82CAE2951C2EE64900F934A7 /* ArrayExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = ""; }; 82CAE2971C2EE95200F934A7 /* ArrayExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtensionTests.swift; sourceTree = ""; }; 82F22E551C26434900E784A2 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; - 82F967F31C67A65E0003F12A /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; + A11830D21E589F6700CBE087 /* TimeIntervalExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeIntervalExtension.swift; sourceTree = ""; }; + A11830D61E58A11D00CBE087 /* TimeIntervalExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeIntervalExtensionTests.swift; sourceTree = ""; }; + A15C62221EE734F100A7CA38 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = ""; }; A16B85EB1D8EA9A200B39055 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; A19DD6921DE2B70F00C66584 /* HandySwift.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = HandySwift.podspec; sourceTree = ""; }; + A1F221631E3CC05100419B06 /* DispatchTimeIntervalExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchTimeIntervalExtension.swift; sourceTree = ""; }; + A1F221851E3FEE7C00419B06 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = ""; }; A1F5AEEB1E05702E003D6949 /* .swift-version */ = {isa = PBXFileReference; lastKnownFileType = text; path = ".swift-version"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -225,8 +226,8 @@ 82CAE2951C2EE64900F934A7 /* ArrayExtension.swift */, 825EFDBE1C3321B300558497 /* CharacterViewExtension.swift */, 8280D7DB1C4A6EC9001172EF /* DictionaryExtension.swift */, - 821F8D631CC40E6E00F9BCD0 /* ColorExtension.swift */, - 827CE9921D07CDE2007A62A8 /* CoreGraphicsExtensions.swift */, + A1F221631E3CC05100419B06 /* DispatchTimeIntervalExtension.swift */, + A11830D21E589F6700CBE087 /* TimeIntervalExtension.swift */, ); path = Extensions; sourceTree = ""; @@ -240,8 +241,8 @@ 82CAE2971C2EE95200F934A7 /* ArrayExtensionTests.swift */, 825EFDC21C332AD200558497 /* CharacterViewExtensionTests.swift */, 8280D7DF1C4A6FF3001172EF /* DictionaryExtensionTests.swift */, - 821F8D6B1CC4222B00F9BCD0 /* ColorExtensionTests.swift */, - 827CE9961D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift */, + 827599631E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift */, + A11830D61E58A11D00CBE087 /* TimeIntervalExtensionTests.swift */, ); path = Extensions; sourceTree = ""; @@ -307,10 +308,11 @@ isa = PBXGroup; children = ( A16B85EB1D8EA9A200B39055 /* README.md */, - 82F967F31C67A65E0003F12A /* .swiftlint.yml */, + A1F221851E3FEE7C00419B06 /* LICENSE.md */, 82F22E551C26434900E784A2 /* Package.swift */, A19DD6921DE2B70F00C66584 /* HandySwift.podspec */, A1F5AEEB1E05702E003D6949 /* .swift-version */, + A15C62221EE734F100A7CA38 /* .swiftlint.yml */, ); name = "Root Files"; sourceTree = ""; @@ -353,7 +355,7 @@ 823B2B2D1C24AAB6007B3CDD /* Frameworks */, 823B2B2E1C24AAB6007B3CDD /* Headers */, 823B2B2F1C24AAB6007B3CDD /* Resources */, - 82F967F41C67A68A0003F12A /* Run Swift Linter */, + 82F967F41C67A68A0003F12A /* SwiftLint */, ); buildRules = ( ); @@ -390,7 +392,7 @@ 825EFDC61C3333B000558497 /* Frameworks */, 825EFDC71C3333B000558497 /* Headers */, 825EFDC81C3333B000558497 /* Resources */, - 82F967F51C67A69A0003F12A /* Run Swift Linter */, + 82F967F51C67A69A0003F12A /* SwiftLint */, ); buildRules = ( ); @@ -427,7 +429,7 @@ 825EFDE51C33351200558497 /* Frameworks */, 825EFDE61C33351200558497 /* Headers */, 825EFDE71C33351200558497 /* Resources */, - 82F967F61C67A6A80003F12A /* Run Swift Linter */, + 82F967F61C67A6A80003F12A /* SwiftLint */, ); buildRules = ( ); @@ -463,32 +465,32 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = Flinesoft; TargetAttributes = { 823B2B301C24AAB6007B3CDD = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; }; 823B2B3A1C24AAB7007B3CDD = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; }; 825EFDC91C3333B000558497 = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; }; 825EFDD21C3333B000558497 = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; }; 825EFDE81C33351200558497 = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; }; 825EFDF11C33351300558497 = { CreatedOnToolsVersion = 7.2; - LastSwiftMigration = 0820; + LastSwiftMigration = 0900; }; }; }; @@ -560,47 +562,47 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 82F967F41C67A68A0003F12A /* Run Swift Linter */ = { + 82F967F41C67A68A0003F12A /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Run Swift Linter"; + name = SwiftLint; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"SwiftLint not installed, download it from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which swiftlint > /dev/null; then\n swiftlint\n else\n echo \"SwiftLint not installed, download it from https://github.com/realm/SwiftLint\"\n fi\nfi"; }; - 82F967F51C67A69A0003F12A /* Run Swift Linter */ = { + 82F967F51C67A69A0003F12A /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Run Swift Linter"; + name = SwiftLint; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"SwiftLint not installed, download it from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which swiftlint > /dev/null; then\n swiftlint\n else\n echo \"SwiftLint not installed, download it from https://github.com/realm/SwiftLint\"\n fi\nfi"; }; - 82F967F61C67A6A80003F12A /* Run Swift Linter */ = { + 82F967F61C67A6A80003F12A /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Run Swift Linter"; + name = SwiftLint; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint > /dev/null; then\n swiftlint\nelse\n echo \"SwiftLint not installed, download it from https://github.com/realm/SwiftLint\"\nfi"; + shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which swiftlint > /dev/null; then\n swiftlint\n else\n echo \"SwiftLint not installed, download it from https://github.com/realm/SwiftLint\"\n fi\nfi"; }; /* End PBXShellScriptBuildPhase section */ @@ -612,14 +614,14 @@ 8258E4561C2E0C140031CBFF /* SortedArray.swift in Sources */, 826F69AC1C3895A300B2CC6B /* FrequencyTable.swift in Sources */, 825EFDBD1C331EF000558497 /* IntegerTypeExtension.swift in Sources */, - 821F8D641CC40E6E00F9BCD0 /* ColorExtension.swift in Sources */, + A1F221641E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */, 825EFDBF1C3321B300558497 /* CharacterViewExtension.swift in Sources */, 823B2B4D1C24ABA4007B3CDD /* IntExtension.swift in Sources */, 82CAE2921C2ED1A200F934A7 /* StringExtension.swift in Sources */, 82CAE2961C2EE64900F934A7 /* ArrayExtension.swift in Sources */, 82812A9B1D06877B00CD5B6C /* Globals.swift in Sources */, - 827CE9931D07CDE2007A62A8 /* CoreGraphicsExtensions.swift in Sources */, 8280D7DC1C4A6EC9001172EF /* DictionaryExtension.swift in Sources */, + A11830D31E589F6700CBE087 /* TimeIntervalExtension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -627,11 +629,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 821F8D6C1CC4222B00F9BCD0 /* ColorExtensionTests.swift in Sources */, 826F69B01C389DB800B2CC6B /* FrequencyTableTests.swift in Sources */, + 827599641E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift in Sources */, 825EFDC31C332AD200558497 /* CharacterViewExtensionTests.swift in Sources */, - 827CE9971D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift in Sources */, 8258E4591C2E1ACE0031CBFF /* SortedArrayTests.swift in Sources */, + A11830D71E58A11D00CBE087 /* TimeIntervalExtensionTests.swift in Sources */, 825EFDC11C332ABB00558497 /* IntegerTypeExtensionTests.swift in Sources */, 823B2B501C24AC00007B3CDD /* IntExtensionTests.swift in Sources */, 82CAE2941C2ED5E000F934A7 /* StringExtensionTests.swift in Sources */, @@ -648,14 +650,14 @@ 825EFE061C33358400558497 /* ArrayExtension.swift in Sources */, 826F69AD1C3895A300B2CC6B /* FrequencyTable.swift in Sources */, 825EFE051C33358400558497 /* StringExtension.swift in Sources */, - 821F8D651CC40E6E00F9BCD0 /* ColorExtension.swift in Sources */, + A1F221651E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */, 825EFE071C33358400558497 /* CharacterViewExtension.swift in Sources */, 825EFE041C33358400558497 /* IntegerTypeExtension.swift in Sources */, 825EFE021C33358400558497 /* SortedArray.swift in Sources */, 825EFE031C33358400558497 /* IntExtension.swift in Sources */, 82812A9C1D06877B00CD5B6C /* Globals.swift in Sources */, - 827CE9941D07CDE2007A62A8 /* CoreGraphicsExtensions.swift in Sources */, 8280D7DD1C4A6EC9001172EF /* DictionaryExtension.swift in Sources */, + A11830D41E589F6700CBE087 /* TimeIntervalExtension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -663,11 +665,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 821F8D6D1CC4222B00F9BCD0 /* ColorExtensionTests.swift in Sources */, 826F69B11C389DB800B2CC6B /* FrequencyTableTests.swift in Sources */, + 827599651E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift in Sources */, 825EFE131C3335A400558497 /* CharacterViewExtensionTests.swift in Sources */, - 827CE9981D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift in Sources */, 825EFE111C3335A400558497 /* StringExtensionTests.swift in Sources */, + A11830D81E58A11D00CBE087 /* TimeIntervalExtensionTests.swift in Sources */, 825EFE0E1C3335A400558497 /* SortedArrayTests.swift in Sources */, 825EFE101C3335A400558497 /* IntegerTypeExtensionTests.swift in Sources */, 825EFE121C3335A400558497 /* ArrayExtensionTests.swift in Sources */, @@ -684,14 +686,14 @@ 825EFE0C1C33358500558497 /* ArrayExtension.swift in Sources */, 826F69AE1C3895A300B2CC6B /* FrequencyTable.swift in Sources */, 825EFE0B1C33358500558497 /* StringExtension.swift in Sources */, - 821F8D661CC40E6E00F9BCD0 /* ColorExtension.swift in Sources */, + A1F221661E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */, 825EFE0D1C33358500558497 /* CharacterViewExtension.swift in Sources */, 825EFE0A1C33358500558497 /* IntegerTypeExtension.swift in Sources */, 825EFE081C33358500558497 /* SortedArray.swift in Sources */, 825EFE091C33358500558497 /* IntExtension.swift in Sources */, 82812A9D1D06877B00CD5B6C /* Globals.swift in Sources */, - 827CE9951D07CDE2007A62A8 /* CoreGraphicsExtensions.swift in Sources */, 8280D7DE1C4A6EC9001172EF /* DictionaryExtension.swift in Sources */, + A11830D51E589F6700CBE087 /* TimeIntervalExtension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -699,11 +701,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 821F8D6E1CC4222B00F9BCD0 /* ColorExtensionTests.swift in Sources */, 826F69B21C389DB800B2CC6B /* FrequencyTableTests.swift in Sources */, + 827599661E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift in Sources */, 825EFE191C3335A500558497 /* CharacterViewExtensionTests.swift in Sources */, - 827CE9991D07D53F007A62A8 /* CoreGraphicsExtensionsTests.swift in Sources */, 825EFE171C3335A500558497 /* StringExtensionTests.swift in Sources */, + A11830D91E58A11D00CBE087 /* TimeIntervalExtensionTests.swift in Sources */, 825EFE141C3335A500558497 /* SortedArrayTests.swift in Sources */, 825EFE161C3335A500558497 /* IntegerTypeExtensionTests.swift in Sources */, 825EFE181C3335A500558497 /* ArrayExtensionTests.swift in Sources */, @@ -742,14 +744,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -778,6 +786,7 @@ PRODUCT_MODULE_NAME = HandySwift; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; TARGETED_DEVICE_FAMILY = "1,2"; TVOS_DEPLOYMENT_TARGET = 9.0; VERSIONING_SYSTEM = "apple-generic"; @@ -793,14 +802,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -822,6 +837,7 @@ PRODUCT_MODULE_NAME = HandySwift; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; TARGETED_DEVICE_FAMILY = "1,2"; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; @@ -849,7 +865,7 @@ PRODUCT_NAME = HandySwift; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -871,7 +887,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.flinesoft.HandySwift; PRODUCT_NAME = HandySwift; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -883,7 +899,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.flinesoft.HandySwift-iOS-Tests"; PRODUCT_MODULE_NAME = HandySwift_iOS_Tests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -895,7 +911,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "com.flinesoft.HandySwift-iOS-Tests"; PRODUCT_MODULE_NAME = HandySwift_iOS_Tests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -918,7 +934,7 @@ PRODUCT_NAME = HandySwift; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -941,7 +957,7 @@ PRODUCT_NAME = HandySwift; SDKROOT = macosx; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -958,7 +974,7 @@ PRODUCT_MODULE_NAME = HandySwift_OSX_Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -975,7 +991,7 @@ PRODUCT_MODULE_NAME = HandySwift_OSX_Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -995,7 +1011,7 @@ PRODUCT_NAME = HandySwift; SDKROOT = appletvos; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1017,7 +1033,7 @@ PRODUCT_NAME = HandySwift; SDKROOT = appletvos; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -1032,7 +1048,7 @@ PRODUCT_MODULE_NAME = HandySwift_tvOS_Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TVOS_DEPLOYMENT_TARGET = 9.1; }; name = Debug; @@ -1046,7 +1062,7 @@ PRODUCT_MODULE_NAME = HandySwift_tvOS_Tests; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = appletvos; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TVOS_DEPLOYMENT_TARGET = 9.1; }; name = Release; diff --git a/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/xcshareddata/xcschemes/HandySwift OSX.xcscheme b/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/xcshareddata/xcschemes/HandySwift OSX.xcscheme index a860288..a1a194c 100644 --- a/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/xcshareddata/xcschemes/HandySwift OSX.xcscheme +++ b/Carthage/Checkouts/Handyswift/HandySwift.xcodeproj/xcshareddata/xcschemes/HandySwift OSX.xcscheme @@ -1,6 +1,6 @@ - Version: 1.4.1 | 1.2.0 + Version: 2.4.0 - Swift: 3.0 | 2.3 | 2.2 + Swift: 4.0 Platforms: iOS | tvOS | OS X @@ -37,7 +37,11 @@ # HandySwift -The goal of this library is to provide handy features that didn't make it to the Swift standard library (yet) due to many different reasons. Those could be that the Swift community wants to keep the standard library clean and manageable or simply hasn't finished discussion on a specific feature yet. +The goal of this library is to **provide handy features** that didn't make it to the Swift standard library (yet) due to many different reasons. Those could be that the Swift community wants to keep the standard library clean and manageable or simply hasn't finished discussion on a specific feature yet. + +If you like this, please also checkout [HandyUIKit](https://github.com/Flinesoft/HandyUIKit) for handy UI features that we feel should have been part of the UIKit frameworks in the first place. + +> If you are **upgrading from a previous major version** of HandySwift (e.g. 1.x to 2.x) then checkout the [releases section on GitHub](https://github.com/Flinesoft/HandySwift/releases) and look out for the release notes of the last major releas(es) (e.g. 2.0.0) for an overview of the changes made. It'll save you time as hints are on how best to migrate are included there. ## Installation @@ -47,26 +51,14 @@ Currently the recommended way of installing this library is via [Carthage](https You can of course also just include this framework manually into your project by downloading it or by using git submodules. -### Carthage - -Depending on the Swift version of your project, place one of the following lines to your Cartfile: - -**Swift 3:** +*Note: This project is ready for Swift 4. Until Xcode 9 is officially released though, you need to use the branch "work/swift4".* -``` Swift -github "Flinesoft/HandySwift" -``` - -**Swift 2.3:** - -``` Swift -github "Flinesoft/HandySwift" "support/swift2.3" -``` +### Carthage -**Swift 2.2:** +Place the following line to your Cartfile: ``` Swift -github "Flinesoft/HandySwift" == 1.2.0 +github "Flinesoft/HandySwift" ~> 2.4 ``` Now run `carthage update`. Then drag & drop the HandySwift.framework in the Carthage/build folder to your project. Now you can `import HandySwift` in each class you want to use its features. Refer to the [Carthage README](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) for detailed / updated instructions. @@ -81,7 +73,7 @@ platform :ios, '8.0' use_frameworks! target 'MyAppTarget' do - pod 'HandySwift', '~> 1.0' + pod 'HandySwift', '~> 2.4' end ``` @@ -94,6 +86,23 @@ Refer to [CocoaPods.org](https://cocoapods.org) for detailed / updates instructi Please have a look at the UsageExamples.playground for a complete list of features provided. Open the Playground from within the `.xcworkspace` in order for it to work. +--- +#### Feature Overview + +- [Globals](#globals) +- Extensions + - [IntExtension](#intextension) + - [IntegerTypeExtension](#integertypeextension) + - [StringExtension](#stringextension) + - [ArrayExtension](#arrayextension) + - [DictionaryExtension](#dictionaryextension) + - [DispatchTimeIntervalExtension](#dispatchtimeintervalextension) +- New types + - [SortedArray](#sortedarray) + - [FrequencyTable](#frequencytable) + +--- + ### Globals Some global helpers. @@ -101,11 +110,10 @@ Some global helpers. Runs a given closure after a delay given in seconds. Dispatch queue can be set optionally, defaults to Main thread. ``` Swift -var date = NSDate() // Without delay: 2016-06-07 05:38:03 +0000 -delay(bySeconds: 1.5) { // Runs in Main thread by default +delay(by: .milliseconds(1_500)) { // Runs in Main thread by default date = NSDate() // Delayed by 1.5 seconds: 2016-06-07 05:38:05 +0000 } -delay(bySeconds: 5, dispatchLevel: .userInteractive) { +delay(by: .seconds(5), dispatchLevel: .userInteractive) { date = NSDate() // Delayed by 5 seconds: 2016-06-07 05:38:08 +0000 } ``` @@ -117,8 +125,8 @@ delay(bySeconds: 5, dispatchLevel: .userInteractive) { Initialize random Int value below given positive value. ``` Swift -Int(randomBelow: 50) // => 26 -Int(randomBelow: 1_000_000) // => 208041 +Int(randomBelow: 50)! // => 26 +Int(randomBelow: 1_000_000)! // => 208041 ``` ### IntegerTypeExtension @@ -132,7 +140,7 @@ Repeat some code block a given number of times. // => ["Hello World!", "Hello World!", "Hello World!"] 5.times { - let randomInt = Int(randomBelow: 1_000) + let randomInt = Int(randomBelow: 1_000)! intArray.append(randomInt) } // => [481, 16, 680, 87, 912] @@ -140,12 +148,12 @@ Repeat some code block a given number of times. ### StringExtension -#### .strip +#### .stripped() Returns string with whitespace characters stripped from start and end. ``` Swift -" \n\t BB-8 likes Rey \t\n ".strip +" \n\t BB-8 likes Rey \t\n ".stripped() // => "BB-8 likes Rey" ``` @@ -177,8 +185,8 @@ String(randomWithLength: 10, allowedCharactersType: .allCharactersIn("?!🐲🍏 Returns a random element within the array or nil if array empty. ``` Swift -[1, 2, 3, 4, 5].sample() // => 4 -([] as [Int]).sample() // => nil +[1, 2, 3, 4, 5].sample // => 4 +([] as [Int]).sample // => nil ``` #### .sample(size:) @@ -191,7 +199,6 @@ Returns an array with `size` random elements or nil if array empty. ([] as [Int]).sample(size: 3) // => nil ``` - #### .combinations(with:) Combines each element with each element of a given other array. @@ -201,6 +208,7 @@ Combines each element with each element of a given other array. // => [(1, "A"), (1, "B"), (2, "A"), (2, "B"), (3, "A"), (3, "B")] ``` + ### DictionaryExtension #### init?(keys:values:) @@ -227,103 +235,53 @@ dict.merge(["B": "New B value", "C": "C value"]) dict // => ["A": "A value", "B": "New B value", "C": "C value"] ``` -#### .mergedWith(Dictionary) +#### .merged(with: Dictionary) Create new merged `Dictionary` with the given `Dictionary` merged into a `Dictionary` overriding existing values for matching keys. ``` Swift let immutableDict = ["A": "A value", "B": "Old B value"] -immutableDict.mergedWith(["B": "New B value", "C": "C value"]) +immutableDict.merged(with: ["B": "New B value", "C": "C value"]) // => ["A": "A value", "B": "New B value", "C": "C value"] ``` -### ColorExtension (iOS & tvOS only) +### DispatchTimeIntervalExtension +#### .timeInterval -#### .rgba -Returns a tuple with named RGBA parameters for easy access. +Returns a `TimeInterval` object from a `DispatchTimeInterval`. ``` Swift -let rgbaColor = UIColor(red: 0.1, green: 0.2, blue: 0.3, alpha: 0.4) -rgbaColor.rgba.red // => 0.1 -rgbaColor.rgba.green // => 0.2 -rgbaColor.rgba.blue // => 0.3 -rgbaColor.rgba.alpha // => 0.4 +DispatchTimeInterval.milliseconds(500).timeInterval // => 0.5 ``` -#### .hsba -Returns a tuple with named HSBA parameters for easy access. +### TimeIntervalExtension +#### Unit based pseudo-initializers +Returns a `TimeInterval` object with a given value in a the specified unit. ``` Swift -let hsbaColor = UIColor(hue: 0.1, saturation: 0.2, brightness: 0.3, alpha: 0.4) -hsbaColor.hsba.hue // => 0.1 -hsbaColor.hsba.saturation // => 0.2 -hsbaColor.hsba.brightness // => 0.3 -hsbaColor.hsba.alpha // => 0.4 +TimeInterval.days(1.5) // => 129600 +TimeInterval.hours(1.5) // => 5400 +TimeInterval.minutes(1.5) // => 90 +TimeInterval.seconds(1.5) // => 1.5 +TimeInterval.milliseconds(1.5) // => 0.0015 +TimeInterval.microseconds(1.5) // => 1.5e-06 +TimeInterval.nanoseconds(1.5) // => 1.5e-09 ``` -#### .change(ChangeableAttribute, by:) -Creates a new `UIColor` object with a single attribute changed by a given difference using addition. +#### Unit based getters +Returns a double value with the time interval converted to the specified unit. ``` Swift -rgbaColor.rgba.blue // => 0.3 -let newRgbaColor = rgbaColor.change(.blue, by: 0.2) -newRgbaColor.rgba.blue // => 0.5 +let timeInterval: TimeInterval = 60 * 60 * 6 + +timeInterval.days // => 0.25 +timeInterval.hours // => 6 +timeInterval.minutes // => 360 +timeInterval.seconds // => 21600 +timeInterval.milliseconds // => 21600000 +timeInterval.microseconds // => 21600000000 +timeInterval.nanoseconds // => 21600000000000 ``` -#### .change(ChangeableAttribute, to:) -Creates a new `UIColor` object with the value of a single attribute set to a given value. - -``` Swift -hsbaColor.hsba.brightness // => 0.3 -let newHsbaColor = hsbaColor.change(.brightness, to: 0.8) -newHsbaColor.hsba.brightness // => 0.8 -``` - -### CoreGraphicsExtensions (partly iOS & tvOS only) - -#### CGSize.inPixels / CGSize.inPixels(screen:) -Returns a new CGSize object with the width and height converted to true pixels on screen. - -``` Swift -let size = CGSize(width: 100, height: 50) -size.inPixels // test this with a Retina screen target -// => {w 200 h 100} -size.inPixels(UIScreen.screens.last!) // pass a different screen -// => {w 50 h 25} -``` - -#### CGPoint.inPixels / CGPoint.inPixels(screen:) -Returns a new CGPoint object with the x and y converted to true pixels on screen. - -``` Swift -let point = CGPoint(x: 100, y: 50) -point.inPixels // test this with a Retina screen target -// => {x 200 y 100} -let someScreen = UIScreen.screens.last! -point.inPixels(someScreen) // pass a different screen -// => {x 50 y 25} -``` - -#### CGRect.inPixels / CGRect.inPixels(screen:) -Returns a new CGRect object with the origin and size converted to true pixels on screen. - -``` Swift -let rect = CGRect(x: 10, y: 20, width: 100, height: 50) -rect.inPixels // test this with a Retina screen target -// => {x 20 y 40 w 200 h 100} -let someScreen = UIScreen.screens.last! -rect.inPixels(someScreen) // pass a different screen -// => {x 5 y 10 w 50 h 25} -``` - -#### CGRect.init(size:) / CGRect.init(width:height:) -Creates a new CGRect object from origin zero with given size. - -``` Swift -let someSize = CGSize(width: 100, height: 50) - -let originZeroRect1 = CGRect(size: someSize) -let originZeroRect2 = CGRect(width: 100, height: 50) -``` ### SortedArray @@ -333,30 +291,30 @@ The main purpose of this wrapper is to provide speed improvements for specific a ``` Swift let unsortedArray = [5, 2, 1, 3, 0, 4] -let sortedArray = SortedArray(array: unsortedArray) +let sortedArray = SortedArray(unsortedArray) sortedArray.array // => [0, 1, 2, 3, 4, 5] ``` -#### .firstMatchingIndex +#### .index Finds the lowest index matching the given predicate using binary search for an improved performance (`O(log n)`). ``` Swift -SortedArray(array: [5, 2, 1, 3, 0, 4]).firstMatchingIndex{ $0 > 1 } +SortedArray([5, 2, 1, 3, 0, 4]).index { $0 > 1 } // => 2 ``` -#### .subArray(toIndex:) +#### .prefix(upTo:) / .prefix(through:) ``` Swift -SortedArray(array: [5, 2, 1, 3, 0, 4]).subArray(toIndex: Array.Index(2)) +SortedArray([5, 2, 1, 3, 0, 4]).prefix(upTo: 2) // => [0, 1] ``` -#### .subArray(fromIndex:) +#### .suffix(from:) ``` Swift -SortedArray(array: [5, 2, 1, 3, 0, 4]).subArray(fromIndex: Array.Index(2)) +SortedArray([5, 2, 1, 3, 0, 4]).suffix(from: 2) // => [2, 3, 4, 5] ``` @@ -381,14 +339,13 @@ let frequencyTable = FrequencyTable(values: wordFrequencies) { $0.frequency } // => HandySwift.FrequencyTable ``` - #### .sample Returns a random element with frequency-based probability within the array or nil if array empty. ``` Swift -frequencyTable.sample() -let randomWord = frequencyTable.sample().map{ $0.word } +frequencyTable.sample +let randomWord = frequencyTable.sample.map{ $0.word } // => "Harry" ``` diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/ArrayExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/ArrayExtension.swift index f13ef25..f3656e6 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/ArrayExtension.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/ArrayExtension.swift @@ -8,16 +8,13 @@ import Foundation -public extension Array { +extension Array { /// Returns a random element from the `Array`. /// /// - Returns: A random element from the array or `nil` if empty. - public func sample() -> Element? { - if !self.isEmpty { - let randomIndex = startIndex.advanced(by: Int(randomBelow: self.count)) - return self[randomIndex] - } - return nil + public var sample: Element? { + guard let randomIndex = Int(randomBelow: count) else { return nil } + return self[randomIndex] } /// Returns a given number of random elements from the `Array`. @@ -26,12 +23,12 @@ public extension Array { /// - size: The number of random elements wanted. /// - Returns: An array with the given number of random elements or `nil` if empty. public func sample(size: Int) -> [Element]? { - if !isEmpty { - var sampleElements: [Element] = [] - size.times { sampleElements.append(self.sample()!) } - return sampleElements - } - return nil + if isEmpty { return nil } + + var sampleElements: [Element] = [] + size.times { sampleElements.append(sample!) } + + return sampleElements } /// Combines each element with each element of a given array. @@ -43,11 +40,96 @@ public extension Array { /// - Returns: An array of tuples with the elements of both arrays combined. public func combinations(with other: [T]) -> [(Element, T)] { var combinations = [(Element, T)]() - self.forEach { elem in - other.forEach { otherElem in - combinations.append((elem, otherElem)) + forEach { elem in other.forEach { otherElem in combinations.append((elem, otherElem)) } } + + return combinations + } + + /// Sorts the collection in place by the order specified in the closure. + /// + /// NOTE: The default `sort` method is not stable, this one allows to explicitly specify it to be stable. + /// + /// - Parameters: + /// - stable: Speifies if the sorting algorithm should be stable. + /// - areInIncreasingOrder: The closure to specify the order of the elements to be sorted by. + public mutating func sort(by areInIncreasingOrder: @escaping (Element, Element) -> Bool, stable: Bool) { + guard stable else { sort(by: areInIncreasingOrder); return } + stableMergeSort(by: areInIncreasingOrder) + } + + /// Returns the elements of the sequence, sorted. + /// + /// NOTE: The default `sorted` method is not stable, this one allows to explicitly specify it to be stable. + /// + /// - Parameters: + /// - stable: Speifies if the sorting algorithm should be stable. + /// - areInIncreasingOrder: The closure to specify the order of the elements to be sorted by. + public func sorted(by areInIncreasingOrder: @escaping (Element, Element) -> Bool, stable: Bool) -> [Element] { + guard stable else { return sorted(by: areInIncreasingOrder) } + + var copy = [Element](self) + copy.stableMergeSort(by: areInIncreasingOrder) + + return copy + } + + /// Sorts the array in-place using a stable merge sort algorithm. + mutating func stableMergeSort(by areInIncreasingOrder: @escaping (Element, Element) -> Bool) { + var tmp = [Element]() + tmp.reserveCapacity(numericCast(count)) + + func merge(low: Int, mid: Int, high: Int) { + tmp.removeAll(keepingCapacity: true) + tmp.append(contentsOf: self[low.. [Element] { + return sorted(by: { lhs, rhs in lhs < rhs }, stable: stable) } } diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/CharacterViewExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/CharacterViewExtension.swift index 64e55d1..8a02fba 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/CharacterViewExtension.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/CharacterViewExtension.swift @@ -8,17 +8,12 @@ import Foundation -public extension String.CharacterView { +extension String.CharacterView { /// Returns a random character from the `ChracterView`. /// /// - Returns: A random character from the `CharacterView` or `nil` if empty. - public func sample() -> Character? { - if !self.isEmpty { - let randomIndex = index(startIndex, offsetBy: Int(randomBelow: count)) - return self[randomIndex] - } - - return nil + public var sample: Character? { + return isEmpty ? nil : self[index(startIndex, offsetBy: Int(randomBelow: count)!)] } /// Returns a given number of random characters from the `CharacterView`. @@ -27,11 +22,11 @@ public extension String.CharacterView { /// - size: The number of random characters wanted. /// - Returns: A `CharacterView` with the given number of random characters or `nil` if empty. public func sample(size: Int) -> String.CharacterView? { - if !isEmpty { - var sampleElements = String.CharacterView() - size.times { sampleElements.append(sample()!) } - return sampleElements - } - return String.CharacterView() + if isEmpty { return nil } + + var sampleElements = String.CharacterView() + size.times { sampleElements.append(sample!) } + + return sampleElements } } diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/ColorExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/ColorExtension.swift deleted file mode 100644 index c786fe2..0000000 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/ColorExtension.swift +++ /dev/null @@ -1,127 +0,0 @@ -// -// ColorExtension.swift -// HandySwift -// -// Created by Cihat Gündüz on 17.04.16. -// Copyright © 2016 Flinesoft. All rights reserved. -// - -#if !os(OSX) - import UIKit - - extension UIColor { - /// A list of changeable attributes of the UIColor. - /// - /// - Red: The red color part of RGB & alpha. - /// - Green: The green color part of RGB & alpha. - /// - Blue: The blue color part of RGB & alpha. - /// - Alpha: The alpha color part of RGB & alpha / HSB & alpha. - /// - Hue: The hue color part of HSB & alpha. - /// - Saturation: The saturation color part of HSB & alpha. - /// - Brightness: The brightness color part of HSB & alpha. - /// - public enum ChangeableAttribute { - case red, green, blue, hue, saturation, brightness, alpha - } - - // MARK: - Computed Properties - - /// The HSB & alpha attributes of the `UIColor` instance. - public var hsba: (hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat) { - var hsba: (hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat) = (0, 0, 0, 0) - getHue(&(hsba.hue), saturation: &(hsba.saturation), brightness: &(hsba.brightness), alpha: &(hsba.alpha)) - return hsba - } - - /// The RGB & alpha attributes of the `UIColor` instance. - public var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { - var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) = (0, 0, 0, 0) - getRed(&rgba.red, green: &rgba.green, blue: &rgba.blue, alpha: &rgba.alpha) - return rgba - } - - - // MARK: - Methods - - /// Creates a new `UIColor` object with a single attribute changed by a given difference using addition. - /// - /// - Parameters: - /// - attribute: The attribute to change. - /// - by: The addition to be added to the current value of the attribute. - /// - Returns: The resulting new `UIColor` with the specified change applied. - public func change(_ attribute: ChangeableAttribute, by addition: CGFloat) -> UIColor { - - switch attribute { - case .red: - return change(attribute, to: rgba.red + addition) - - case .green: - return change(attribute, to: rgba.green + addition) - - case .blue: - return change(attribute, to: rgba.blue + addition) - - case .alpha: - return change(attribute, to: rgba.alpha + addition) - - case .hue: - return change(attribute, to: hsba.hue + addition) - - case .saturation: - return change(attribute, to: hsba.saturation + addition) - - case .brightness: - return change(attribute, to: hsba.brightness + addition) - } - } - - /// Creates a new `UIColor` object with the value of a single attribute set to a given value. - /// - /// - Parameters: - /// - attribute: The attribute to change. - /// - to: The new value to be set for the attribute. - /// - Returns: The resulting new `UIColor` with the specified change applied. - public func change(_ attribute: ChangeableAttribute, to newValue: CGFloat) -> UIColor { // swiftlint:disable:this cyclomatic_complexity - switch attribute { - case .red, .green, .blue, .alpha: - var newRgba = self.rgba - - switch attribute { - case .red: - newRgba.red = newValue - - case .green: - newRgba.green = newValue - - case .blue: - newRgba.blue = newValue - - case .alpha: - newRgba.alpha = newValue - - default: break - } - - return UIColor(red: newRgba.red, green: newRgba.green, blue: newRgba.blue, alpha: newRgba.alpha) - - case .hue, .saturation, .brightness: - var newHsba = self.hsba - - switch attribute { - case .hue: - newHsba.hue = newValue - - case .saturation: - newHsba.saturation = newValue - - case .brightness: - newHsba.brightness = newValue - - default: break - } - - return UIColor(hue: newHsba.hue, saturation: newHsba.saturation, brightness: newHsba.brightness, alpha: newHsba.alpha) - } - } - } -#endif diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/CoreGraphicsExtensions.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/CoreGraphicsExtensions.swift deleted file mode 100644 index cadb8cb..0000000 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/CoreGraphicsExtensions.swift +++ /dev/null @@ -1,87 +0,0 @@ -// -// CoreGraphicsExtensions.swift -// HandySwift -// -// Created by Cihat Gündüz on 08.06.16. -// Copyright © 2016 Flinesoft. All rights reserved. -// - -import Foundation - -#if !os(OSX) - import UIKit - // MARK: - iOS/tvOS CGSize Extension - - extension CGSize { - /// Returns a new CGSize object with the width and height converted to true pixels on the main screen. - public var inPixels: CGSize { - return inPixels(UIScreen.main) - } - - /// Returns a new CGSize object with the width and height converted to true pixels on the given screen. - /// - /// - Parameters: - /// - screen: The target screen to convert to pixels for. - public func inPixels(_ screen: UIScreen) -> CGSize { - return CGSize(width: width * screen.scale, height: height * screen.scale) - } - } - - - // MARK: - iOS/tvOS CGPoint Extension - - extension CGPoint { - /// Returns a new CGPoint object with the x and y converted to true pixels on the main screen. - public var inPixels: CGPoint { - return inPixels(UIScreen.main) - } - - /// Returns a new CGPoint object with the x and y converted to true pixels on the given screen. - /// - /// - Parameters: - /// - screen: The target screen to convert to pixels for. - public func inPixels(_ screen: UIScreen) -> CGPoint { - return CGPoint(x: x * screen.scale, y: y * screen.scale) - } - } - - - // MARK: - iOS/tvOS CGRect Extension - - extension CGRect { - /// Returns a new CGRect object with the origin and size converted to true pixels on the main screen. - public var inPixels: CGRect { - return inPixels(UIScreen.main) - } - - /// Returns a new CGRect object with the origin and size converted to true pixels on the given screen. - /// - /// - Parameters: - /// - screen: The target screen to convert to pixels for. - public func inPixels(_ screen: UIScreen) -> CGRect { - return CGRect(origin: origin.inPixels(screen), size: size.inPixels(screen)) - } - } -#endif - - -// MARK: - Shared CGRect Extension - -extension CGRect { - /// Creates a new CGRect object from origin zero with given size. - /// - /// - Parameters: - /// - size: The size of the new rect. - public init(size: CGSize) { - self.init(origin: CGPoint.zero, size: size) - } - - /// Creates a new CGRect object from origin zero with given size. - /// - /// - Parameters: - /// - width: The width of the new rect. - /// - height: The height of the new rect. - public init(width: CGFloat, height: CGFloat) { - self.init(origin: CGPoint.zero, size: CGSize(width: width, height: height)) - } -} diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/DictionaryExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/DictionaryExtension.swift index a15bdba..dbe02dd 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/DictionaryExtension.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/DictionaryExtension.swift @@ -17,20 +17,15 @@ extension Dictionary { public init?(keys: [Key], values: [Value]) { guard keys.count == values.count else { return nil } self.init() - - for (index, key) in keys.enumerated() { - self[key] = values[index] - } + for (index, key) in keys.enumerated() { self[key] = values[index] } } /// Merge given `Dictionary` into this `Dictionary` overriding existing values for matching keys. /// /// - Parameters: /// - otherDictionary: The other `Dictionary` to merge into this `Dictionary`. - public mutating func merge(_ otherDictionary: [Key: Value]) { - for (key, value) in otherDictionary { - self[key] = value - } + public mutating func merge(_ other: [Key: Value]) { + for (key, value) in other { self[key] = value } } /// Create new merged `Dictionary` with the given `Dictionary` merged into this `Dictionary` @@ -39,13 +34,10 @@ extension Dictionary { /// - Parameters: /// - otherDictionary: The other `Dictionary` to merge into this `Dictionary`. /// - Returns: The new Dictionary with merged keys and values from this and the other `Dictionary`. - public func mergedWith(_ otherDictionary: [Key: Value]) -> [Key: Value] { - var mergedDict: [Key: Value] = [:] - [self, otherDictionary].forEach { dict in - for (key, value) in dict { - mergedDict[key] = value - } - } - return mergedDict + public func merged(with other: [Key: Value]) -> [Key: Value] { + var newDict: [Key: Value] = [:] + [self, other].forEach { dict in for (key, value) in dict { newDict[key] = value } } + + return newDict } } diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/DispatchTimeIntervalExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/DispatchTimeIntervalExtension.swift new file mode 100644 index 0000000..e8ad131 --- /dev/null +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/DispatchTimeIntervalExtension.swift @@ -0,0 +1,31 @@ +// +// DispatchTimeIntervalExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 28.01.17. +// Copyright © 2017 Flinesoft. All rights reserved. +// + +import Foundation + +extension DispatchTimeInterval { + /// - Returns: The time in seconds using the`TimeInterval` type. + public var timeInterval: TimeInterval { + switch self { + case .seconds(let seconds): + return Double(seconds) + + case .milliseconds(let milliseconds): + return Double(milliseconds) / Timespan.millisecondsPerSecond + + case .microseconds(let microseconds): + return Double(microseconds) / Timespan.microsecondsPerSecond + + case .nanoseconds(let nanoseconds): + return Double(nanoseconds) / Timespan.nanosecondsPerSecond + + case .never: + return TimeInterval.infinity + } + } +} diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/IntExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/IntExtension.swift index 449c520..804baa9 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/IntExtension.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/IntExtension.swift @@ -8,18 +8,13 @@ import Foundation -public extension Int { +extension Int { /// Initializes a new `Int ` instance with a random value below a given `Int`. /// /// - Parameters: /// - randomBelow: The upper bound value to create a random value with. - public init(randomBelow upperLimit: Int) { - guard upperLimit > 0 else { - self.init(0) - return - } - - let randomUInt32 = arc4random_uniform(UInt32(upperLimit)) - self.init(randomUInt32) + public init?(randomBelow upperLimit: Int) { + guard upperLimit > 0 else { return nil } + self.init(arc4random_uniform(UInt32(upperLimit))) } } diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/IntegerTypeExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/IntegerTypeExtension.swift index 0681e0b..ee4ec04 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Extensions/IntegerTypeExtension.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/IntegerTypeExtension.swift @@ -15,6 +15,6 @@ extension Int { /// - closure: The code to be run multiple times. public func times(_ closure: () -> Void) { guard self > 0 else { return } - for _ in 1...self { closure() } + for _ in 0.. String { return trimmingCharacters(in: .whitespacesAndNewlines) } +} + +extension String { + /// The type of allowed characters. + /// + /// - Numeric: Allow all numbers from 0 to 9. + /// - Alphabetic: Allow all alphabetic characters ignoring case. + /// - AlphaNumeric: Allow both numbers and alphabetic characters ignoring case. + /// - AllCharactersIn: Allow all characters appearing within the specified String. + public enum AllowedCharacters { + case numeric + case alphabetic + case alphaNumeric + case allCharactersIn(String) + } } diff --git a/Carthage/Checkouts/Handyswift/Sources/Extensions/TimeIntervalExtension.swift b/Carthage/Checkouts/Handyswift/Sources/Extensions/TimeIntervalExtension.swift new file mode 100644 index 0000000..0ff1d7b --- /dev/null +++ b/Carthage/Checkouts/Handyswift/Sources/Extensions/TimeIntervalExtension.swift @@ -0,0 +1,94 @@ +// +// TimeIntervalExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 18.02.17. +// Copyright © 2017 Flinesoft. All rights reserved. +// + +import Foundation + +/// A typealias to keep backwards compatibility with version 2.0.x and 2.1.x. +public typealias Timespan = TimeInterval + +extension TimeInterval { + // MARK: - Computed Type Properties + internal static var secondsPerDay: Double { return 24 * 60 * 60 } + internal static var secondsPerHour: Double { return 60 * 60 } + internal static var secondsPerMinute: Double { return 60 } + internal static var millisecondsPerSecond: Double { return 1_000 } + internal static var microsecondsPerSecond: Double { return 1_000 * 1_000 } + internal static var nanosecondsPerSecond: Double { return 1_000 * 1_000 * 1_000 } + + // MARK: - Computed Instance Properties + /// - Returns: The `TimeInterval` in days. + public var days: Double { + return self / TimeInterval.secondsPerDay + } + + /// - Returns: The `TimeInterval` in hours. + public var hours: Double { + return self / TimeInterval.secondsPerHour + } + + /// - Returns: The `TimeInterval` in minutes. + public var minutes: Double { + return self / TimeInterval.secondsPerMinute + } + + /// - Returns: The `TimeInterval` in seconds. + public var seconds: Double { + return self + } + + /// - Returns: The `TimeInterval` in milliseconds. + public var milliseconds: Double { + return self * TimeInterval.millisecondsPerSecond + } + + /// - Returns: The `TimeInterval` in microseconds. + public var microseconds: Double { + return self * TimeInterval.microsecondsPerSecond + } + + /// - Returns: The `TimeInterval` in nanoseconds. + public var nanoseconds: Double { + return self * TimeInterval.nanosecondsPerSecond + } + + // MARK: - Type Methods + /// - Returns: The time in days using the `TimeInterval` type. + public static func days(_ value: Double) -> TimeInterval { + return value * secondsPerDay + } + + /// - Returns: The time in hours using the `TimeInterval` type. + public static func hours(_ value: Double) -> TimeInterval { + return value * secondsPerHour + } + + /// - Returns: The time in minutes using the `TimeInterval` type. + public static func minutes(_ value: Double) -> TimeInterval { + return value * secondsPerMinute + } + + /// - Returns: The time in seconds using the `TimeInterval` type. + public static func seconds(_ value: Double) -> TimeInterval { + return value + } + + /// - Returns: The time in milliseconds using the `TimeInterval` type. + public static func milliseconds(_ value: Double) -> TimeInterval { + return value / millisecondsPerSecond + } + + /// - Returns: The time in microseconds using the `TimeInterval` type. + public static func microseconds(_ value: Double) -> TimeInterval { + return value / microsecondsPerSecond + } + + /// - Returns: The time in nanoseconds using the `TimeInterval` type. + public static func nanoseconds(_ value: Double) -> TimeInterval { + return value / nanosecondsPerSecond + } +} diff --git a/Carthage/Checkouts/Handyswift/Sources/Globals.swift b/Carthage/Checkouts/Handyswift/Sources/Globals.swift index 8b39fff..81ebbc3 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Globals.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Globals.swift @@ -8,41 +8,13 @@ import Foundation -/// The Main thread level or QOS classes as an enum. -public enum DispatchLevel { - case main - case userInteractive - case userInitiated - case utility - case background - - var dispatchQueue: DispatchQueue { - switch self { - case .main: - return DispatchQueue.main - - case .userInteractive: - return DispatchQueue.global(qos: .userInteractive) - - case .userInitiated: - return DispatchQueue.global(qos: .userInitiated) - - case .utility: - return DispatchQueue.global(qos: .utility) - - case .background: - return DispatchQueue.global(qos: .background) - } - } -} - -/// Runs code with delay given in seconds. +/// Runs code with delay given in seconds. Uses the main thread if not otherwise specified. /// /// - Parameters: -/// - bySeconds: The delay in seconds. -/// - dispatchLevel: The level that defines the thread type. -/// - closure: The closure to run with delay. -public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) { - let dispatchTime = DispatchTime.now() + seconds - dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure) +/// - delayTime: The duration of the delay. E.g. `.seconds(1)` or `.milliseconds(200)`. +/// - qosClass: The global QOS class to be used or `nil` to use the main thread. Defaults to `nil`. +/// - closure: The code to run with a delay. +public func delay(by delayTime: Timespan, qosClass: DispatchQoS.QoSClass? = nil, _ closure: @escaping () -> Void) { + let dispatchQueue = qosClass != nil ? DispatchQueue.global(qos: qosClass!) : DispatchQueue.main + dispatchQueue.asyncAfter(deadline: DispatchTime.now() + delayTime, execute: closure) } diff --git a/Carthage/Checkouts/Handyswift/Sources/Structs/FrequencyTable.swift b/Carthage/Checkouts/Handyswift/Sources/Structs/FrequencyTable.swift index d2b994a..b14d99c 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Structs/FrequencyTable.swift +++ b/Carthage/Checkouts/Handyswift/Sources/Structs/FrequencyTable.swift @@ -10,33 +10,33 @@ import Foundation /// Data structure to retrieve random values with their frequency taken into account. public struct FrequencyTable { + // MARK: - Sub Types + typealias Entry = (value: T, frequency: Int) + // MARK: - Stored Instance Properties + private let valuesWithFrequencies: [Entry] - private let valuesWithFrequencies: [(T, Int)] + /// Contains all values the amount of time of their frequencies. private let frequentValues: [T] - // MARK: - Initializers - /// Creates a new FrequencyTable instance with values and their frequencies provided. /// /// - Parameters: - /// - values: An array full of values to be saved into the frequency table. - /// - frequencyClosure: The closure to specify the frequency for a specific value. + /// - values: An array full of values to be saved into the frequency table. + /// - frequencyClosure: The closure to specify the frequency for a specific value. public init(values: [T], frequencyClosure: (T) -> Int) { - self.valuesWithFrequencies = values.map { ($0, frequencyClosure($0)) } - self.frequentValues = Array(self.valuesWithFrequencies.map { (value, frequency) -> [T] in - return (0.. T? { - return frequentValues.sample() - } + public var sample: T? { return frequentValues.sample } + // MARK: - Instance Methods /// Returns an array of random values taking frequencies into account or nil if values empty. /// /// - Parameters: @@ -44,11 +44,7 @@ public struct FrequencyTable { /// /// - Returns: An array of random values or nil if values empty. public func sample(size: Int) -> [T]? { - if !self.frequentValues.isEmpty { - var sampleElements: [T] = [] - size.times { sampleElements.append(self.sample()!) } - return sampleElements - } - return nil + guard size > 0 && !frequentValues.isEmpty else { return nil } + return Array(0.. { - // MARK: - Stored Instance Properties - - fileprivate var internalArray: [Element] = [] + private var internalArray: [Element] /// Returns the sorted array of elements. - public var array: [Element] { - return self.internalArray - } - + public var array: [Element] { return self.internalArray } // MARK: - Initializers + /// Creates a new, empty array. + /// + /// For example: + /// + /// var emptyArray = SortedArray() + public init() { + internalArray = [] + } - /// Creates a new SortedArray with a given array of elements and sorts the elements. + /// Creates a new SortedArray with a given sequence of elements and sorts its elements. /// - /// - Complexity: Probably O(n * log(n)) -- complexity of `sort()` on an Array. + /// - Complexity: The same as `sort()` on an Array –- probably O(n * log(n)). /// /// - Parameters: /// - array: The array to be initially sorted and saved. - public init(array: [Element]) { - self.init(array: array, preSorted: false) + public init(_ sequence: S) where S.Iterator.Element == Element { + self.init(sequence: sequence, preSorted: false) } - fileprivate init(array: [Element], preSorted: Bool) { - if preSorted { - self.internalArray = array - } else { - self.internalArray = array.sorted() - } + private init(sequence: S, preSorted: Bool) where S.Iterator.Element == Element { + internalArray = preSorted ? Array(sequence) : Array(sequence).sorted() } - // MARK: - Instance Methods - - /// Returns the index of the left most matching element. Matching is done via binary search. + /// Returns the first index in which an element of the array satisfies the given predicate. + /// Matching is done using binary search to minimize complexity. /// /// - Complexity: O(log(n)) /// /// - Parameters: - /// - predicate: The boolean predicate to match the elements with. - /// - Returns: The index of the left most matching element. - public func firstMatchingIndex(_ predicate: (Element) -> Bool) -> Int? { - - // check if all elements match - if let firstElement = self.array.first { - if predicate(firstElement) { - return self.array.startIndex - } - } - - // check if no element matches - if let lastElement = self.array.last { - if !predicate(lastElement) { - return nil - } - } + /// - predicate: The predicate to match the elements against. + /// - Returns: The index of the first matching element or `nil` if none of them matches. + public func index(where predicate: (Element) -> Bool) -> Int? { + // cover trivial cases + guard !array.isEmpty else { return nil } + if let first = array.first, predicate(first) { return array.startIndex } + if let last = array.last, !predicate(last) { return nil } // binary search for first matching element - var predicateMatched = false - - var lowerIndex = self.array.startIndex - var upperIndex = self.array.endIndex + var foundMatch = false + var lowerIndex = array.startIndex + var upperIndex = array.endIndex while lowerIndex != upperIndex { + let middleIndex = lowerIndex + (upperIndex - lowerIndex) / 2 + guard predicate(array[middleIndex]) else { lowerIndex = middleIndex + 1; continue } - let middleIndex = lowerIndex.advanced(by: lowerIndex.distance(to: upperIndex) / 2) - - if predicate(self.array[middleIndex]) { - upperIndex = middleIndex - predicateMatched = true - } else { - lowerIndex = middleIndex.advanced(by: 1) - } - - } - - if !predicateMatched { - return nil + upperIndex = middleIndex + foundMatch = true } + guard foundMatch else { return nil } return lowerIndex } - /// Returns a sub array of a SortedArray to a given index without resorting. + /// Returns a sub array of a SortedArray up to a given index (excluding it) without resorting. /// /// - Complexity: O(1) /// /// - Parameters: - /// - toIndex: The upper bound index until which to include elements. - /// - Returns: A new SortedArray instance including all elements until the specified index. - public func subArray(toIndex endIndex: Int) -> SortedArray { - - let range = self.array.startIndex.. SortedArray { + let subarray = Array(array[array.indices.prefix(upTo: index)]) + return SortedArray(sequence: subarray, preSorted: true) + } + /// Returns a sub array of a SortedArray up to a given index (including it) without resorting. + /// + /// - Complexity: O(1) + /// + /// - Parameters: + /// - index: The upper bound index until which to include elements. + /// - Returns: A new SortedArray instance including all elements until the specified index (including it). + public func prefix(through index: Int) -> SortedArray { + let subarray = Array(array[array.indices.prefix(through: index)]) + return SortedArray(sequence: subarray, preSorted: true) } /// Returns a sub array of a SortedArray starting at a given index without resorting. @@ -114,15 +101,41 @@ public struct SortedArray { /// - Complexity: O(1) /// /// - Parameters: - /// - toIndex: The lower bound index from which to start including elements. + /// - index: The lower bound index from which to start including elements. /// - Returns: A new SortedArray instance including all elements starting at the specified index. - public func subArray(fromIndex startIndex: Int) -> SortedArray { + public func suffix(from index: Int) -> SortedArray { + let subarray = Array(array[array.indices.suffix(from: index)]) + return SortedArray(sequence: subarray, preSorted: true) + } - let range = self.array.indices.suffix(from: startIndex) - let subArray = Array(self.array[range]) + /// Accesses a contiguous subrange of the SortedArray's elements. + /// + /// - Parameter + /// - bounds: A range of the SortedArray's indices. The bounds of the range must be valid indices. + public subscript(bounds: Range) -> SortedArray { + return SortedArray(sequence: array[bounds], preSorted: true) + } - return SortedArray(array: subArray, preSorted: true) + // MARK: - Mutating Methods + /// Adds a new item to the sorted array. + /// + /// - Complexity: O(log(n)) + /// + /// - Parameters: + /// - newElement: The new element to be inserted into the array. + public mutating func insert(newElement: Element) { + let insertIndex = internalArray.index { $0 >= newElement } ?? internalArray.endIndex + internalArray.insert(newElement, at: insertIndex) + } + /// Adds the contents of a sequence to the SortedArray. + /// + /// - Complexity: O(n * log(n)) + /// + /// - Parameters: + /// - sequence + public mutating func insert(contentsOf sequence: S) where S.Iterator.Element == Element { + sequence.forEach { insert(newElement: $0) } } /// Removes an item from the sorted array. @@ -130,9 +143,8 @@ public struct SortedArray { /// - Complexity: O(1) /// /// - Parameters: - /// - atIndex: The index of the element to remove from the sorted array. - public mutating func remove(atIndex index: Int) { - self.internalArray.remove(at: index) + /// - index: The index of the element to remove from the sorted array. + public mutating func remove(at index: Int) { + internalArray.remove(at: index) } - } diff --git a/Carthage/Checkouts/Handyswift/Sources/Supporting Files/Info.plist b/Carthage/Checkouts/Handyswift/Sources/Supporting Files/Info.plist index 8bce5c7..b6cbd28 100644 --- a/Carthage/Checkouts/Handyswift/Sources/Supporting Files/Info.plist +++ b/Carthage/Checkouts/Handyswift/Sources/Supporting Files/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.4.0 + 2.4.0 CFBundleSignature ???? CFBundleVersion diff --git a/Carthage/Checkouts/Handyswift/Tests/Extensions/ArrayExtensionTests.swift b/Carthage/Checkouts/Handyswift/Tests/Extensions/ArrayExtensionTests.swift index 3746a21..1e6f89a 100644 --- a/Carthage/Checkouts/Handyswift/Tests/Extensions/ArrayExtensionTests.swift +++ b/Carthage/Checkouts/Handyswift/Tests/Extensions/ArrayExtensionTests.swift @@ -6,15 +6,14 @@ // Copyright © 2015 Flinesoft. All rights reserved. // -import XCTest - @testable import HandySwift +import XCTest class ArrayExtensionTests: XCTestCase { func testSample() { - XCTAssertNil([].sample()) - XCTAssertNotNil([1, 2, 3].sample()) - XCTAssertTrue([1, 2, 3].contains([1, 2, 3].sample()!)) + XCTAssertNil([].sample) + XCTAssertNotNil([1, 2, 3].sample) + XCTAssertTrue([1, 2, 3].contains([1, 2, 3].sample!)) } func testSampleWithSize() { @@ -51,4 +50,30 @@ class ArrayExtensionTests: XCTestCase { XCTAssertEqual(combinations[4].1, "A") XCTAssertEqual(combinations[5].1, "B") } + + struct T: Equatable { // swiftlint:disable:this type_name + let a: Int, b: Int // swiftlint:disable:this identifier_name + + static func == (lhs: T, rhs: T) -> Bool { + return lhs.a == rhs.a && lhs.b == rhs.b + } + } + + let unsortedArray = [T(a: 0, b: 2), T(a: 1, b: 2), T(a: 2, b: 2), T(a: 3, b: 1), T(a: 4, b: 1), T(a: 5, b: 0)] + let sortedArray = [T(a: 5, b: 0), T(a: 3, b: 1), T(a: 4, b: 1), T(a: 0, b: 2), T(a: 1, b: 2), T(a: 2, b: 2)] + + func testSortByStable() { + var testArray = [T](unsortedArray) + testArray.sort(by: { lhs, rhs in lhs.b < rhs.b }, stable: true) + for index in 0..= 0) - XCTAssertTrue(Int(randomBelow: 0) == 0) - XCTAssertTrue(Int(randomBelow: -1) == 0) + XCTAssertTrue(Int(randomBelow: 15)! < 15) + XCTAssertTrue(Int(randomBelow: 15)! >= 0) + XCTAssertNil(Int(randomBelow: 0)) + XCTAssertNil(Int(randomBelow: -1)) } } } diff --git a/Carthage/Checkouts/Handyswift/Tests/Extensions/IntegerTypeExtensionTests.swift b/Carthage/Checkouts/Handyswift/Tests/Extensions/IntegerTypeExtensionTests.swift index c9f9259..f3ccbc3 100644 --- a/Carthage/Checkouts/Handyswift/Tests/Extensions/IntegerTypeExtensionTests.swift +++ b/Carthage/Checkouts/Handyswift/Tests/Extensions/IntegerTypeExtensionTests.swift @@ -6,9 +6,8 @@ // Copyright © 2015 Flinesoft. All rights reserved. // -import XCTest - @testable import HandySwift +import XCTest class IntegerTypeExtensionTests: XCTestCase { func testTimesMethod() { diff --git a/Carthage/Checkouts/Handyswift/Tests/Extensions/StringExtensionTests.swift b/Carthage/Checkouts/Handyswift/Tests/Extensions/StringExtensionTests.swift index 9e574dd..be9e50f 100644 --- a/Carthage/Checkouts/Handyswift/Tests/Extensions/StringExtensionTests.swift +++ b/Carthage/Checkouts/Handyswift/Tests/Extensions/StringExtensionTests.swift @@ -6,17 +6,16 @@ // Copyright © 2015 Flinesoft. All rights reserved. // -import XCTest - @testable import HandySwift +import XCTest class StringExtensionTests: XCTestCase { func testStrip() { let whitespaceString = " \n\t BB-8 likes Rey \t\n " - XCTAssertEqual(whitespaceString.strip, "BB-8 likes Rey") + XCTAssertEqual(whitespaceString.stripped(), "BB-8 likes Rey") let nonWhitespaceString = "Luke Skywalker lives." - XCTAssertEqual(nonWhitespaceString.strip, nonWhitespaceString) + XCTAssertEqual(nonWhitespaceString.stripped(), nonWhitespaceString) } func testIsBlank() { diff --git a/Carthage/Checkouts/Handyswift/Tests/Extensions/TimeIntervalExtensionTests.swift b/Carthage/Checkouts/Handyswift/Tests/Extensions/TimeIntervalExtensionTests.swift new file mode 100644 index 0000000..bd6c629 --- /dev/null +++ b/Carthage/Checkouts/Handyswift/Tests/Extensions/TimeIntervalExtensionTests.swift @@ -0,0 +1,35 @@ +// +// TimeIntervalExtensionTests.swift +// HandySwift +// +// Created by Cihat Gündüz on 18.02.17. +// Copyright © 2017 Flinesoft. All rights reserved. +// + +@testable import HandySwift +import XCTest + +class TimeIntervalExtensionTests: XCTestCase { + func testUnitInitialization() { + XCTAssertEqual(Timespan.days(0.5), 12 * 60 * 60, accuracy: 0.001) + XCTAssertEqual(Timespan.hours(0.5), 30 * 60, accuracy: 0.001) + XCTAssertEqual(Timespan.minutes(0.5), 30, accuracy: 0.001) + XCTAssertEqual(Timespan.seconds(0.5), 0.5, accuracy: 0.001) + XCTAssertEqual(Timespan.milliseconds(0.5), 0.5 / 1_000, accuracy: 0.001) + XCTAssertEqual(Timespan.microseconds(0.5), 0.5 / 1_000_000, accuracy: 0.001) + XCTAssertEqual(Timespan.nanoseconds(0.5), 0.5 / 1_000_000_000, accuracy: 0.001) + } + + func testUnitConversion() { + let timespan = Timespan.hours(4) + let multipledTimespan = timespan * 3 + + XCTAssertEqual(multipledTimespan.days, 0.5, accuracy: 0.001) + XCTAssertEqual(multipledTimespan.hours, 12, accuracy: 0.001) + XCTAssertEqual(multipledTimespan.minutes, 12 * 60, accuracy: 0.001) + XCTAssertEqual(multipledTimespan.seconds, 12 * 60 * 60, accuracy: 0.001) + XCTAssertEqual(multipledTimespan.milliseconds, 12 * 60 * 60 * 1_000, accuracy: 0.001) + XCTAssertEqual(multipledTimespan.microseconds, 12 * 60 * 60 * 1_000_000, accuracy: 0.001) + XCTAssertEqual(multipledTimespan.nanoseconds, 12 * 60 * 60 * 1_000_000_000, accuracy: 0.001) + } +} diff --git a/Carthage/Checkouts/Handyswift/Tests/GlobalsTests.swift b/Carthage/Checkouts/Handyswift/Tests/GlobalsTests.swift index 25c7a41..c6cea97 100644 --- a/Carthage/Checkouts/Handyswift/Tests/GlobalsTests.swift +++ b/Carthage/Checkouts/Handyswift/Tests/GlobalsTests.swift @@ -6,21 +6,20 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import HandySwift +import XCTest class GlobalsTests: XCTestCase { func testDelayed() { let expectation = self.expectation(description: "Wait for delay.") let callDate = Date() - let delaySeconds = 1.5 - delay(bySeconds: delaySeconds) { - XCTAssertEqualWithAccuracy(callDate.timeIntervalSince1970 + delaySeconds, NSDate().timeIntervalSince1970, accuracy: 0.25) + let delayTime = Timespan.milliseconds(1_500) + delay(by: .milliseconds(1_500)) { + XCTAssertEqual(callDate.timeIntervalSince1970 + delayTime, NSDate().timeIntervalSince1970, accuracy: 0.25) expectation.fulfill() } - waitForExpectations(timeout: delaySeconds + 1.0, handler: nil) + waitForExpectations(timeout: delayTime + 1.0, handler: nil) } } diff --git a/Carthage/Checkouts/Handyswift/Tests/Structs/FrequencyTableTests.swift b/Carthage/Checkouts/Handyswift/Tests/Structs/FrequencyTableTests.swift index a2f8ab9..0c74baf 100644 --- a/Carthage/Checkouts/Handyswift/Tests/Structs/FrequencyTableTests.swift +++ b/Carthage/Checkouts/Handyswift/Tests/Structs/FrequencyTableTests.swift @@ -6,9 +6,8 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import HandySwift +import XCTest class FrequencyTableTests: XCTestCase { func testSample() { @@ -17,7 +16,7 @@ class FrequencyTableTests: XCTestCase { var allSamples: [String] = [] - 16_000.times { allSamples.append(frequencyTable.sample()!) } + 16_000.times { allSamples.append(frequencyTable.sample!) } let harryCount = allSamples.filter { $0 == "Harry" }.count XCTAssertGreaterThan(harryCount, 4_000) @@ -30,7 +29,6 @@ class FrequencyTableTests: XCTestCase { let ronaldCount = allSamples.filter { $0 == "Ronald" }.count XCTAssertGreaterThan(ronaldCount, 0) XCTAssertLessThan(ronaldCount, 2_000) - } func testSampleWithSize() { diff --git a/Carthage/Checkouts/Handyswift/Tests/Structs/SortedArrayTests.swift b/Carthage/Checkouts/Handyswift/Tests/Structs/SortedArrayTests.swift index 21df757..890b8ae 100644 --- a/Carthage/Checkouts/Handyswift/Tests/Structs/SortedArrayTests.swift +++ b/Carthage/Checkouts/Handyswift/Tests/Structs/SortedArrayTests.swift @@ -6,49 +6,48 @@ // Copyright © 2015 Flinesoft. All rights reserved. // -import XCTest - @testable import HandySwift +import XCTest class SortedArrayTests: XCTestCase { func testInitialization() { let intArray: [Int] = [9, 1, 3, 2, 5, 4, 6, 0, 8, 7] - let sortedIntArray = SortedArray(array: intArray) + let sortedIntArray = SortedArray(intArray) XCTAssertEqual(sortedIntArray.array, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) } func testFirstMatchingIndex() { let emptyArray: [Int] = [] - let sortedEmptyArray = SortedArray(array: emptyArray) + let sortedEmptyArray = SortedArray(emptyArray) - XCTAssertNil(sortedEmptyArray.firstMatchingIndex { _ in true }) + XCTAssertNil(sortedEmptyArray.index { _ in true }) let intArray: [Int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - let sortedIntArray = SortedArray(array: intArray) + let sortedIntArray = SortedArray(intArray) let expectedIndex = 3 - let resultingIndex = sortedIntArray.firstMatchingIndex { $0 >= 3 } + let resultingIndex = sortedIntArray.index { $0 >= 3 } XCTAssertEqual(resultingIndex, expectedIndex) } func testSubArrayToIndex() { let intArray: [Int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - let sortedIntArray = SortedArray(array: intArray) + let sortedIntArray = SortedArray(intArray) - let index = sortedIntArray.firstMatchingIndex { $0 > 5 }! - let sortedSubArray = sortedIntArray.subArray(toIndex: index) + let index = sortedIntArray.index { $0 > 5 }! + let sortedSubArray = sortedIntArray.prefix(upTo: index) XCTAssertEqual(sortedSubArray.array, [0, 1, 2, 3, 4, 5]) } func testSubArrayFromIndex() { let intArray: [Int] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - let sortedIntArray = SortedArray(array: intArray) + let sortedIntArray = SortedArray(intArray) - let index = sortedIntArray.firstMatchingIndex { $0 > 5 }! - let sortedSubArray = sortedIntArray.subArray(fromIndex: index) + let index = sortedIntArray.index { $0 > 5 }! + let sortedSubArray = sortedIntArray.suffix(from: index) XCTAssertEqual(sortedSubArray.array, [6, 7, 8, 9]) } diff --git a/Carthage/Checkouts/Handyswift/UsageExamples.playground/Contents.swift b/Carthage/Checkouts/Handyswift/UsageExamples.playground/Contents.swift index 6d91bf6..9033fcf 100644 --- a/Carthage/Checkouts/Handyswift/UsageExamples.playground/Contents.swift +++ b/Carthage/Checkouts/Handyswift/UsageExamples.playground/Contents.swift @@ -14,12 +14,12 @@ PlaygroundPage.current.needsIndefiniteExecution = true var date = NSDate() print("Without delay: \(date)") -delay(bySeconds: 1.5) { +delay(by: .milliseconds(1_500)) { date = NSDate() print("Delayed by 1.5 seconds: \(date)") } -delay(bySeconds: 5, dispatchLevel: .userInteractive) { +delay(by: .seconds(5), qosClass: .userInteractive) { date = NSDate() print("Delayed by 5 seconds: \(date)") @@ -49,7 +49,7 @@ stringArray var intArray: [Int] = [] 5.times { - let randomInt = Int(randomBelow: 1_000) + let randomInt = Int(randomBelow: 1_000)! intArray.append(randomInt) } intArray @@ -59,7 +59,7 @@ intArray //: ### string.strip //: Returns string with whitespace characters stripped from start and end. -" \n\t BB-8 likes Rey \t\n ".strip +" \n\t BB-8 likes Rey \t\n ".stripped() //: ### string.isBlank //: Checks if String contains any characters other than whitespace characters. @@ -68,7 +68,7 @@ intArray "".isBlank " \t ".isEmpty -" \t ".isBlank +" \t\n ".isBlank //: ### init(randomWithLength:allowedCharactersType:) //: Get random numeric/alphabetic/alphanumeric String of given length. @@ -102,15 +102,15 @@ dict.merge(["B": "New B value", "C": "C value"]) //: Create new merged `Dictionary` with the given `Dictionary` merged into a `Dictionary` overriding existing values for matching keys. let immutableDict = ["A": "A value", "B": "Old B value"] -let mergedDict = immutableDict.mergedWith(["B": "New B value", "C": "C value"]) +let mergedDict = immutableDict.merged(with: ["B": "New B value", "C": "C value"]) mergedDict //: ## ArrayExtension //: ### .sample //: Returns a random element within the array or nil if array empty. -[1, 2, 3, 4, 5].sample() -([] as [Int]).sample() +[1, 2, 3, 4, 5].sample +([] as [Int]).sample //: ### .sample(size:) //: Returns an array with `size` random elements or nil if array empty. @@ -123,70 +123,59 @@ mergedDict //: Combines each element with each element of a given other array. [1, 2, 3].combinations(with: ["A", "B"]) +//: ### .sort(stable:) / .sorted(stable:) / .sort(by:stable:) / .sorted(by:stable:) +//: Stable sorting methods to sort arrays without destroying pre-existing ordering for equal cases. -//: ## ColorExtension (iOS & tvOS only) -//: ### .rgba -//: Returns a tuple with named RGBA parameters for easy access. +// Build an example class to demo two factors of ordering (a and b). +struct T: Equatable { + let a: Int, b: Int -let rgbaColor = UIColor(red: 0.1, green: 0.2, blue: 0.3, alpha: 0.4) -rgbaColor.rgba.red -rgbaColor.rgba.green -rgbaColor.rgba.blue -rgbaColor.rgba.alpha - - -//: ### .hsba -//: Returns a tuple with named HSBA parameters for easy access. - -let hsbaColor = UIColor(hue: 0.1, saturation: 0.2, brightness: 0.3, alpha: 0.4) -hsbaColor.hsba.hue -hsbaColor.hsba.saturation -hsbaColor.hsba.brightness -hsbaColor.hsba.alpha - -//: ### .change(ChangeableAttribute, by:) -//: Creates a new `UIColor` object with a single attribute changed by a given difference using addition. - -rgbaColor.rgba.blue -let newRgbaColor = rgbaColor.change(.blue, by: 0.2) -newRgbaColor.rgba.blue + static func == (lhs: T, rhs: T) -> Bool { + return lhs.a == rhs.a && lhs.b == rhs.b + } +} -//: ### .change(ChangeableAttribute, to:) -//: Creates a new `UIColor` object with the value of a single attribute set to a given value. +var unsortedArray = [T(a: 0, b: 2), T(a: 1, b: 2), T(a: 2, b: 2), T(a: 3, b: 1), T(a: 4, b: 1), T(a: 5, b: 0)] -hsbaColor.hsba.brightness -let newHsbaColor = hsbaColor.change(.brightness, to: 0.8) -newHsbaColor.hsba.brightness +//: Get sorted copy of array (not touching the original array). +unsortedArray.sorted(by: { lhs, rhs in lhs.b < rhs.b }, stable: true) +unsortedArray -//: ## CoreGraphicsExtensions -//: ### CGSize.inPixels / CGSize.inPixels(screen:) -//: Returns a new CGSize object with the width and height converted to true pixels on screen. +//: Sort in place (mutating). +unsortedArray.sort(by: { lhs, rhs in lhs.b < rhs.b }, stable: true) +unsortedArray // now sorted -let size = CGSize(width: 100, height: 50) -size.inPixels // test this with a Retina screen target -size.inPixels(UIScreen.screens.last!) // pass a different screen +//: ## DispatchTimeIntervalExtension +//: ### .timeInterval +//: Returns a `TimeInterval` object from a `DispatchTimeInterval`. -//: ### CGPoint.inPixels / CGPoint.inPixels(screen:) -//: Returns a new CGPoint object with the x and y converted to true pixels on screen. +DispatchTimeInterval.milliseconds(500).timeInterval -let point = CGPoint(x: 100, y: 50) -point.inPixels // test this with a Retina screen target -point.inPixels(UIScreen.screens.last!) // pass a different screen +//: ## TimeIntervalExtension +//: ### Unit based pseudo-initializers +//: Returns a `TimeInterval` object with a given value in a the specified unit. -//: ### CGRect.inPixels / CGRect.inPixels(screen:) -//: Returns a new CGRect object with the origin and size converted to true pixels on screen. +TimeInterval.days(1.5) +TimeInterval.hours(1.5) +TimeInterval.minutes(1.5) +TimeInterval.seconds(1.5) +TimeInterval.milliseconds(1.5) +TimeInterval.microseconds(1.5) +TimeInterval.nanoseconds(1.5) -let rect = CGRect(x: 10, y: 20, width: 100, height: 50) -rect.inPixels // test this with a Retina screen target -rect.inPixels(UIScreen.screens.last!) // pass a different screen +//: ### Unit based getters +//: Returns a double value with the time interval converted to the specified unit. -//: ### CGRect.init(size:) / CGRect.init(width:height:) -//: Creates a new CGRect object from origin zero with given size. +let timeInterval: TimeInterval = 60 * 60 * 6 -let someSize = CGSize(width: 100, height: 50) +timeInterval.days +timeInterval.hours +timeInterval.minutes +timeInterval.seconds +timeInterval.milliseconds +timeInterval.microseconds +timeInterval.nanoseconds -let originZeroRect1 = CGRect(size: someSize) -let originZeroRect2 = CGRect(width: 100, height: 50) //: # Added Structures //: New structures added to extend the Swift standard library. @@ -194,7 +183,7 @@ let originZeroRect2 = CGRect(width: 100, height: 50) //: ### SortedArray(array: unsortedArray) //: Initializes with unsorted array. -let sortedArray = SortedArray(array: [5, 2, 1, 3, 0, 4]) +let sortedArray = SortedArray([5, 2, 1, 3, 0, 4]) //: ### sortedArray.array //: Gives access to internal sorted array. @@ -204,19 +193,19 @@ sortedArray.array //: ### sortedArray.firstMatchingIndex{ predicate } //: Binary search with predicate. -let index = sortedArray.firstMatchingIndex{ $0 > 1 } +let index = sortedArray.index { $0 > 1 } index //: ### sortedArray.subArray(toIndex: index) //: Returns beginning part as sorted subarray. -let nonMatchingSubArray = sortedArray.subArray(toIndex: index!) +let nonMatchingSubArray = sortedArray.prefix(upTo: index!) nonMatchingSubArray.array //: ### sortedArray.subArray(fromIndex: index) //: Returns ending part as sorted subarray. -let matchingSubArray = sortedArray.subArray(fromIndex: index!) +let matchingSubArray = sortedArray.suffix(from: index!) matchingSubArray.array @@ -240,8 +229,8 @@ frequencyTable //: ### .sample //: Returns a random element with frequency-based probability within the array or nil if array empty. -frequencyTable.sample() -let randomWord = frequencyTable.sample().map{ $0.word } +frequencyTable.sample +let randomWord = frequencyTable.sample.map{ $0.word } randomWord //: ### .sample(size:) diff --git a/Carthage/Checkouts/Polyglot/Polyglot/StringExtensionPolyglot.swift b/Carthage/Checkouts/Polyglot/Polyglot/StringExtensionPolyglot.swift index fbd6424..7b43bbe 100644 --- a/Carthage/Checkouts/Polyglot/Polyglot/StringExtensionPolyglot.swift +++ b/Carthage/Checkouts/Polyglot/Polyglot/StringExtensionPolyglot.swift @@ -32,10 +32,10 @@ extension String { public var language: Language? { if characters.count > 0 { // Prevent Index Out of Bounds in NSLinguisticTagger - let tagger = NSLinguisticTagger(tagSchemes: [NSLinguisticTagSchemeLanguage], options: 0) + let tagger = NSLinguisticTagger(tagSchemes: [NSLinguisticTagScheme.language], options: 0) tagger.string = self - if let result = tagger.tag(at: 0, scheme: NSLinguisticTagSchemeLanguage, tokenRange: nil, sentenceRange: nil) { - return Language(rawValue: result) + if let result = tagger.tag(at: 0, scheme: NSLinguisticTagScheme.language, tokenRange: nil, sentenceRange: nil) { + return Language(rawValue: result.rawValue) } } return nil diff --git a/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/project.pbxproj b/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/project.pbxproj index 0516092..ff29e0d 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/project.pbxproj +++ b/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/project.pbxproj @@ -7,8 +7,10 @@ objects = { /* Begin PBXBuildFile section */ - 6BF86B27E801452077EAF608 /* Pods_PolyglotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 925AA115444C33786930F106 /* Pods_PolyglotTests.framework */; }; - 76E093B31C869D9803863B0A /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB9A4E55DA20E420F9D1A394 /* Pods.framework */; }; + 00CAD5FE1F7A6CDA0090DD38 /* Polyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD5FB1F7A6CC40090DD38 /* Polyglot.swift */; }; + 00CAD5FF1F7A6CDA0090DD38 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD5FC1F7A6CC40090DD38 /* Session.swift */; }; + 00CAD6001F7A6CDA0090DD38 /* StringExtensionPolyglot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CAD5FD1F7A6CC40090DD38 /* StringExtensionPolyglot.swift */; }; + 1FE3B86C180B8FB88CB9DA70 /* Pods_PolyglotTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E862700FF2DDDC6E779C805A /* Pods_PolyglotTests.framework */; }; B60F875D1985F1C200ABB94A /* PolyglotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B60F875C1985F1C200ABB94A /* PolyglotTests.swift */; }; B6156E3F1999D93B002CE52F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B67FC7841985F20B0030ABF8 /* Main.storyboard */; }; B6682231199C68AE00DFA909 /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6682230199C68AE00DFA909 /* StringExtensionTests.swift */; }; @@ -18,11 +20,13 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 169250360E8B162C09FEC696 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; - 18EAC8F54FC94B5025FBB495 /* Pods-PolyglotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PolyglotTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests.debug.xcconfig"; sourceTree = ""; }; - 7B2717494CE9EFC17436B68F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; - 906A23634E280AEDC1BA250B /* Pods-PolyglotTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PolyglotTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests.release.xcconfig"; sourceTree = ""; }; - 925AA115444C33786930F106 /* Pods_PolyglotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PolyglotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 00CAD5F31F7A6BE90090DD38 /* Polyglot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Polyglot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 00CAD5F71F7A6C470090DD38 /* Nocilla.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Nocilla.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 00CAD5FB1F7A6CC40090DD38 /* Polyglot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Polyglot.swift; path = Polyglot/Polyglot.swift; sourceTree = SOURCE_ROOT; }; + 00CAD5FC1F7A6CC40090DD38 /* Session.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Session.swift; path = Polyglot/Session.swift; sourceTree = SOURCE_ROOT; }; + 00CAD5FD1F7A6CC40090DD38 /* StringExtensionPolyglot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StringExtensionPolyglot.swift; path = Polyglot/StringExtensionPolyglot.swift; sourceTree = SOURCE_ROOT; }; + 12D767DA42F475C66CF8F400 /* Pods-PolyglotTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PolyglotTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests.release.xcconfig"; sourceTree = ""; }; + B0A0353E6F1D00A71C35119B /* Pods-PolyglotTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PolyglotTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests.debug.xcconfig"; sourceTree = ""; }; B60F87441985F1C200ABB94A /* PolyglotSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PolyglotSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; B60F87561985F1C200ABB94A /* PolyglotTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PolyglotTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B60F875B1985F1C200ABB94A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -36,6 +40,7 @@ B67FC7881985F20B0030ABF8 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; B67FC7951985F2F20030ABF8 /* Polyglot-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Polyglot-Bridging-Header.h"; sourceTree = ""; }; DB9A4E55DA20E420F9D1A394 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E862700FF2DDDC6E779C805A /* Pods_PolyglotTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PolyglotTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -43,7 +48,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 76E093B31C869D9803863B0A /* Pods.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -51,20 +55,29 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6BF86B27E801452077EAF608 /* Pods_PolyglotTests.framework in Frameworks */, + 1FE3B86C180B8FB88CB9DA70 /* Pods_PolyglotTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 1BC459906112AA6B922B0A50 /* Pods */ = { + 00CAD5FA1F7A6CB40090DD38 /* Polyglot */ = { isa = PBXGroup; children = ( - 169250360E8B162C09FEC696 /* Pods.debug.xcconfig */, - 7B2717494CE9EFC17436B68F /* Pods.release.xcconfig */, - 18EAC8F54FC94B5025FBB495 /* Pods-PolyglotTests.debug.xcconfig */, - 906A23634E280AEDC1BA250B /* Pods-PolyglotTests.release.xcconfig */, + 00CAD5FB1F7A6CC40090DD38 /* Polyglot.swift */, + 00CAD5FC1F7A6CC40090DD38 /* Session.swift */, + 00CAD5FD1F7A6CC40090DD38 /* StringExtensionPolyglot.swift */, + ); + name = Polyglot; + path = "New Group"; + sourceTree = ""; + }; + 02E4E4E277C02F05F31865E5 /* Pods */ = { + isa = PBXGroup; + children = ( + B0A0353E6F1D00A71C35119B /* Pods-PolyglotTests.debug.xcconfig */, + 12D767DA42F475C66CF8F400 /* Pods-PolyglotTests.release.xcconfig */, ); name = Pods; sourceTree = ""; @@ -73,7 +86,7 @@ isa = PBXGroup; children = ( DB9A4E55DA20E420F9D1A394 /* Pods.framework */, - 925AA115444C33786930F106 /* Pods_PolyglotTests.framework */, + E862700FF2DDDC6E779C805A /* Pods_PolyglotTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -81,11 +94,14 @@ B60F873B1985F1C200ABB94A = { isa = PBXGroup; children = ( + 00CAD5FA1F7A6CB40090DD38 /* Polyglot */, + 00CAD5F71F7A6C470090DD38 /* Nocilla.framework */, + 00CAD5F31F7A6BE90090DD38 /* Polyglot.framework */, B67FC7821985F20B0030ABF8 /* PolyglotSample */, B60F87591985F1C200ABB94A /* PolyglotTests */, B60F87451985F1C200ABB94A /* Products */, AD05005C88874F61B93358E3 /* Frameworks */, - 1BC459906112AA6B922B0A50 /* Pods */, + 02E4E4E277C02F05F31865E5 /* Pods */, ); sourceTree = ""; }; @@ -140,7 +156,6 @@ B60F87401985F1C200ABB94A /* Sources */, B60F87411985F1C200ABB94A /* Frameworks */, B60F87421985F1C200ABB94A /* Resources */, - 2C89B4C9E4725608B65AFC36 /* Embed Pods Frameworks */, ); buildRules = ( ); @@ -155,12 +170,12 @@ isa = PBXNativeTarget; buildConfigurationList = B60F87631985F1C200ABB94A /* Build configuration list for PBXNativeTarget "PolyglotTests" */; buildPhases = ( - 408E75F29D9B38C4B9827AB7 /* Check Pods Manifest.lock */, + 7F91ED9EDFC53CF81FF9D7BE /* [CP] Check Pods Manifest.lock */, B60F87521985F1C200ABB94A /* Sources */, B60F87531985F1C200ABB94A /* Frameworks */, B60F87541985F1C200ABB94A /* Resources */, - 9C872251D11A74FF863B9D27 /* Embed Pods Frameworks */, - CEE1C2C59E9D00E35BF90D16 /* Copy Pods Resources */, + EC7E49862C514AB5DB4B90DF /* [CP] Embed Pods Frameworks */, + 1B62D634051E7C5C83362E0B /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -179,14 +194,17 @@ attributes = { LastSwiftMigration = 0710; LastSwiftUpdateCheck = 0710; - LastUpgradeCheck = 0600; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Ayaka Nonaka"; TargetAttributes = { B60F87431985F1C200ABB94A = { CreatedOnToolsVersion = 6.0; + DevelopmentTeam = DB7EUU9D79; + LastSwiftMigration = 0900; }; B60F87551985F1C200ABB94A = { CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0900; TestTargetID = B60F87431985F1C200ABB94A; }; }; @@ -230,66 +248,59 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 2C89B4C9E4725608B65AFC36 /* Embed Pods Frameworks */ = { + 1B62D634051E7C5C83362E0B /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 408E75F29D9B38C4B9827AB7 /* Check Pods Manifest.lock */ = { + 7F91ED9EDFC53CF81FF9D7BE /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); - name = "Check Pods Manifest.lock"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PolyglotTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 9C872251D11A74FF863B9D27 /* Embed Pods Frameworks */ = { + EC7E49862C514AB5DB4B90DF /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/Nocilla/Nocilla.framework", + "${BUILT_PRODUCTS_DIR}/Polyglot/Polyglot.framework", ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Nocilla.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Polyglot.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - CEE1C2C59E9D00E35BF90D16 /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PolyglotTests/Pods-PolyglotTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -297,8 +308,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 00CAD5FF1F7A6CDA0090DD38 /* Session.swift in Sources */, + 00CAD5FE1F7A6CDA0090DD38 /* Polyglot.swift in Sources */, B67FC7891985F20B0030ABF8 /* AppDelegate.swift in Sources */, B67FC78D1985F20B0030ABF8 /* ViewController.swift in Sources */, + 00CAD6001F7A6CDA0090DD38 /* StringExtensionPolyglot.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -333,20 +347,30 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -375,13 +399,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -389,6 +421,7 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -398,42 +431,49 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; }; B60F87611985F1C200ABB94A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 169250360E8B162C09FEC696 /* Pods.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = DB7EUU9D79; INFOPLIST_FILE = PolyglotSample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.ayakanonaka.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = PolyglotSample; SWIFT_OBJC_BRIDGING_HEADER = "PolyglotSample/Polyglot-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; }; name = Debug; }; B60F87621985F1C200ABB94A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7B2717494CE9EFC17436B68F /* Pods.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = DB7EUU9D79; INFOPLIST_FILE = PolyglotSample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.ayakanonaka.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = PolyglotSample; SWIFT_OBJC_BRIDGING_HEADER = "PolyglotSample/Polyglot-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 4.0; }; name = Release; }; B60F87641985F1C200ABB94A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 18EAC8F54FC94B5025FBB495 /* Pods-PolyglotTests.debug.xcconfig */; + baseConfigurationReference = B0A0353E6F1D00A71C35119B /* Pods-PolyglotTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/PolyglotSample.app/PolyglotSample"; CLANG_ENABLE_MODULES = YES; @@ -447,16 +487,19 @@ ); INFOPLIST_FILE = PolyglotTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.ayakanonaka.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PolyglotTests/PolyglotTests-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUNDLE_LOADER)"; }; name = Debug; }; B60F87651985F1C200ABB94A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 906A23634E280AEDC1BA250B /* Pods-PolyglotTests.release.xcconfig */; + baseConfigurationReference = 12D767DA42F475C66CF8F400 /* Pods-PolyglotTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/PolyglotSample.app/PolyglotSample"; CLANG_ENABLE_MODULES = YES; @@ -466,8 +509,11 @@ ); INFOPLIST_FILE = PolyglotTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.ayakanonaka.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PolyglotTests/PolyglotTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUNDLE_LOADER)"; }; name = Release; diff --git a/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/xcshareddata/xcschemes/PolyglotSample.xcscheme b/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/xcshareddata/xcschemes/PolyglotSample.xcscheme index 2f479dc..0b7f278 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/xcshareddata/xcschemes/PolyglotSample.xcscheme +++ b/Carthage/Checkouts/Polyglot/PolyglotSample.xcodeproj/xcshareddata/xcschemes/PolyglotSample.xcscheme @@ -1,6 +1,6 @@ Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { return true } } diff --git a/Carthage/Checkouts/Polyglot/PolyglotSample/Info.plist b/Carthage/Checkouts/Polyglot/PolyglotSample/Info.plist index 300cad6..2ca21ce 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotSample/Info.plist +++ b/Carthage/Checkouts/Polyglot/PolyglotSample/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.ayakanonaka.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Carthage/Checkouts/Polyglot/PolyglotSample/ViewController.swift b/Carthage/Checkouts/Polyglot/PolyglotSample/ViewController.swift index 3615f59..dac5ac9 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotSample/ViewController.swift +++ b/Carthage/Checkouts/Polyglot/PolyglotSample/ViewController.swift @@ -7,7 +7,6 @@ // import UIKit -import Polyglot /** @@ -41,18 +40,18 @@ class ViewController: UIViewController { @IBOutlet weak var inputTextField: UITextField! @IBOutlet weak var translationLabel: UILabel! - @IBAction func didTapTranslateButton(sender: AnyObject) { + @IBAction func didTapTranslateButton(_ sender: AnyObject) { guard let text = inputTextField.text else { return } - UIApplication.sharedApplication().networkActivityIndicatorVisible = true + UIApplication.shared.isNetworkActivityIndicatorVisible = true translator.translate(text) { translation in if let language = self.translator.fromLanguage?.rawValue { - self.translationLabel.text = "Translated from \(language.capitalizedString): \(translation)" + self.translationLabel.text = "Translated from \(language.capitalized): \(translation)" } else { self.translationLabel.text = translation } - UIApplication.sharedApplication().networkActivityIndicatorVisible = false + UIApplication.shared.isNetworkActivityIndicatorVisible = false } } } diff --git a/Carthage/Checkouts/Polyglot/PolyglotTests/Info.plist b/Carthage/Checkouts/Polyglot/PolyglotTests/Info.plist index 5293720..6d32c15 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotTests/Info.plist +++ b/Carthage/Checkouts/Polyglot/PolyglotTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.ayakanonaka.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/Carthage/Checkouts/Polyglot/PolyglotTests/PolyglotTests.swift b/Carthage/Checkouts/Polyglot/PolyglotTests/PolyglotTests.swift index 3b37ff9..5467bda 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotTests/PolyglotTests.swift +++ b/Carthage/Checkouts/Polyglot/PolyglotTests/PolyglotTests.swift @@ -74,11 +74,11 @@ class PolyglotTests: XCTestCase { } func testTranslate() { - let expectation = expectationWithDescription("translation done") + let expectation = self.expectation(description: "translation done") // Stub POST access token stubRequest("POST", "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13") - .withBody("client_id=myClientId&client_secret=myClientSecret&scope=http://api.microsofttranslator.com&grant_type=client_credentials".dataUsingEncoding(NSUTF8StringEncoding)) + .withBody("client_id=myClientId&client_secret=myClientSecret&scope=http://api.microsofttranslator.com&grant_type=client_credentials".dataUsingEncoding(String.Encoding.utf8)) .andReturn(200) .withHeaders(["Content-Type": "application/json"]) .withBody("{\"access_token\":\"octocatsruleeverythingaroundme\", \"expires_in\":\"600\"}") @@ -91,12 +91,12 @@ class PolyglotTests: XCTestCase { let polyglot: Polyglot = Polyglot(clientId: "myClientId", clientSecret: "myClientSecret") polyglot.translate("Ik weet het niet") { translation in - dispatch_async(dispatch_get_main_queue(), { () -> Void in + DispatchQueue.main.async(execute: { () -> Void in XCTAssertEqual(translation, "I don't know") expectation.fulfill() }) } - waitForExpectationsWithTimeout(1, handler: nil) + waitForExpectations(timeout: 1, handler: nil) } } diff --git a/Carthage/Checkouts/Polyglot/PolyglotTests/StringExtensionTests.swift b/Carthage/Checkouts/Polyglot/PolyglotTests/StringExtensionTests.swift index a77892e..bbf2e72 100644 --- a/Carthage/Checkouts/Polyglot/PolyglotTests/StringExtensionTests.swift +++ b/Carthage/Checkouts/Polyglot/PolyglotTests/StringExtensionTests.swift @@ -39,14 +39,14 @@ class StringExtensionTests: XCTestCase { XCTAssertNil("".language?.rawValue, "Empty strings should return nil.") } - func AssertEqualOptional(@autoclosure optional: () -> T?, @autoclosure _ expected: () -> T, file: String = #file, line: UInt = #line) { + func AssertEqualOptional(_ optional: @autoclosure () -> T?, _ expected: @autoclosure () -> T, file: String = #file, line: UInt = #line) { if let nonOptional = optional() { if nonOptional != expected() { - self.recordFailureWithDescription("Optional (\(nonOptional)) is not equal to (\(expected()))", inFile: file, atLine: line, expected: true) + self.recordFailure(withDescription: "Optional (\(nonOptional)) is not equal to (\(expected()))", inFile: file, atLine: line, expected: true) } } else { - self.recordFailureWithDescription("Optional value is empty", inFile: file, atLine: line, expected: true) + self.recordFailure(withDescription: "Optional value is empty", inFile: file, atLine: line, expected: true) } } diff --git a/Carthage/Checkouts/CommandLine/CommandLineKit/CommandLineKit.swift b/Carthage/CommandLine/CommandLineKit.swift similarity index 98% rename from Carthage/Checkouts/CommandLine/CommandLineKit/CommandLineKit.swift rename to Carthage/CommandLine/CommandLineKit.swift index 9c73d35..dda3415 100644 --- a/Carthage/Checkouts/CommandLine/CommandLineKit/CommandLineKit.swift +++ b/Carthage/CommandLine/CommandLineKit.swift @@ -467,12 +467,12 @@ open class CommandLineKit { } /* Remove attached argument from flag */ - let splitFlag = flagWithArg.split(by: ArgumentAttacher, maxSplits: 1) + let splitFlag = flagWithArg.split(separator: ArgumentAttacher, maxSplits: 1) let flag = splitFlag[0] - let attachedArg: String? = splitFlag.count == 2 ? splitFlag[1] : nil + let attachedArg: String? = splitFlag.count == 2 ? String(splitFlag[1]) : nil var flagMatched = false - for option in _options where option.flagMatch(flag) { + for option in _options where option.flagMatch(String(flag)) { let vals = self._getFlagValues(idx, attachedArg) guard option.setValue(vals) else { throw ParseError.InvalidValueForOption(option, vals) diff --git a/Carthage/CommandLine/Info.plist b/Carthage/CommandLine/Info.plist new file mode 100644 index 0000000..e095737 --- /dev/null +++ b/Carthage/CommandLine/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSHumanReadableCopyright + Copyright © 2014 Ben Gollmer. Licensed under the Apache License, Version 2.0. + NSPrincipalClass + + + diff --git a/Carthage/CommandLine/Option.swift b/Carthage/CommandLine/Option.swift new file mode 100644 index 0000000..82b8efd --- /dev/null +++ b/Carthage/CommandLine/Option.swift @@ -0,0 +1,450 @@ +/* + * Option.swift + * Copyright (c) 2014 Ben Gollmer. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * The base class for a command-line option. + */ +open class Option { + open let shortFlag: String? + open let longFlag: String? + open let required: Bool + open let helpMessage: String + + /** True if the option was set when parsing command-line arguments */ + open var wasSet: Bool { + return false + } + + open var claimedValues: Int { return 0 } + + open var flagDescription: String { + switch (shortFlag, longFlag) { + case let (sf?, lf?): + return "\(ShortOptionPrefix)\(sf), \(LongOptionPrefix)\(lf)" + case (nil, let lf?): + return "\(LongOptionPrefix)\(lf)" + case (let sf?, nil): + return "\(ShortOptionPrefix)\(sf)" + default: + return "" + } + } + + internal init(_ shortFlag: String?, _ longFlag: String?, _ required: Bool, _ helpMessage: String) { + if let sf = shortFlag { + assert(sf.characters.count == 1, "Short flag must be a single character") + assert(Int(sf) == nil && sf.toDouble() == nil, "Short flag cannot be a numeric value") + } + + if let lf = longFlag { + assert(Int(lf) == nil && lf.toDouble() == nil, "Long flag cannot be a numeric value") + } + + self.shortFlag = shortFlag + self.longFlag = longFlag + self.helpMessage = helpMessage + self.required = required + } + + /* The optional casts in these initalizers force them to call the private initializer. Without + * the casts, they recursively call themselves. + */ + + /** Initializes a new Option that has both long and short flags. */ + public convenience init(shortFlag: String, longFlag: String, required: Bool = false, helpMessage: String) { + self.init(shortFlag as String?, longFlag, required, helpMessage) + } + + /** Initializes a new Option that has only a short flag. */ + public convenience init(shortFlag: String, required: Bool = false, helpMessage: String) { + self.init(shortFlag as String?, nil, required, helpMessage) + } + + /** Initializes a new Option that has only a long flag. */ + public convenience init(longFlag: String, required: Bool = false, helpMessage: String) { + self.init(nil, longFlag as String?, required, helpMessage) + } + + #if swift(>=3.0) + func flagMatch(_ flag: String) -> Bool { + return flag == shortFlag || flag == longFlag + } + + func setValue(_ values: [String]) -> Bool { + return false + } + #else + func flagMatch(_ flag: String) -> Bool { + return flag == shortFlag || flag == longFlag + } + + func setValue(_ values: [String]) -> Bool { + return false + } + #endif +} + +/** + * A boolean option. The presence of either the short or long flag will set the value to true; + * absence of the flag(s) is equivalent to false. + */ +open class BoolOption: Option { + fileprivate var _value: Bool = false + + open var value: Bool { + return _value + } + + override open var wasSet: Bool { + return _value + } + + #if swift(>=3.0) + override func setValue(_ values: [String]) -> Bool { + _value = true + return true + } + #else + override func setValue(_ values: [String]) -> Bool { + _value = true + return true + } + #endif +} + +/** An option that accepts a positive or negative integer value. */ +open class IntOption: Option { + fileprivate var _value: Int? + + open var value: Int? { + return _value + } + + override open var wasSet: Bool { + return _value != nil + } + + override open var claimedValues: Int { + return _value != nil ? 1 : 0 + } + + #if swift(>=3.0) + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + if let val = Int(values[0]) { + _value = val + return true + } + + return false + } + #else + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + if let val = Int(values[0]) { + _value = val + return true + } + + return false + } + #endif +} + +/** + * An option that represents an integer counter. Each time the short or long flag is found + * on the command-line, the counter will be incremented. + */ +open class CounterOption: Option { + fileprivate var _value: Int = 0 + + open var value: Int { + return _value + } + + override open var wasSet: Bool { + return _value > 0 + } + + open func reset() { + _value = 0 + } + + #if swift(>=3.0) + override func setValue(_ values: [String]) -> Bool { + _value += 1 + return true + } + #else + override func setValue(_ values: [String]) -> Bool { + _value += 1 + return true + } + #endif +} + +/** An option that accepts a positive or negative floating-point value. */ +open class DoubleOption: Option { + fileprivate var _value: Double? + + open var value: Double? { + return _value + } + + override open var wasSet: Bool { + return _value != nil + } + + override open var claimedValues: Int { + return _value != nil ? 1 : 0 + } + + #if swift(>=3.0) + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + if let val = values[0].toDouble() { + _value = val + return true + } + + return false + } + + #else + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + if let val = values[0].toDouble() { + _value = val + return true + } + + return false + } + + #endif +} + +/** An option that accepts a string value. */ +open class StringOption: Option { + fileprivate var _value: String? = nil + + open var value: String? { + return _value + } + + override open var wasSet: Bool { + return _value != nil + } + + override open var claimedValues: Int { + return _value != nil ? 1 : 0 + } + + #if swift(>=3.0) + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + _value = values[0] + return true + } + + #else + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + _value = values[0] + return true + } + + #endif +} + +/** An option that accepts one or more string values. */ +open class MultiStringOption: Option { + fileprivate var _value: [String]? + + open var value: [String]? { + return _value + } + + override open var wasSet: Bool { + return _value != nil + } + + override open var claimedValues: Int { + if let v = _value { + return v.count + } + + return 0 + } + + #if swift(>=3.0) + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + _value = values + return true + } + + #else + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + _value = values + return true + } + + #endif +} + +#if swift(>=3.0) + +/** An option that represents an enum value. */ +public class EnumOption: Option where T.RawValue == String { + private var _value: T? + public var value: T? { + return _value + } + + override public var wasSet: Bool { + return _value != nil + } + + override public var claimedValues: Int { + return _value != nil ? 1 : 0 + } + + /* Re-defining the intializers is necessary to make the Swift 2 compiler happy, as + * of Xcode 7 beta 2. + */ + + internal override init(_ shortFlag: String?, _ longFlag: String?, _ required: Bool, _ helpMessage: String) { + super.init(shortFlag, longFlag, required, helpMessage) + } + + /** Initializes a new Option that has both long and short flags. */ + public convenience init(shortFlag: String, longFlag: String, required: Bool = false, helpMessage: String) { + self.init(shortFlag as String?, longFlag, required, helpMessage) + } + + /** Initializes a new Option that has only a short flag. */ + public convenience init(shortFlag: String, required: Bool = false, helpMessage: String) { + self.init(shortFlag as String?, nil, required, helpMessage) + } + + /** Initializes a new Option that has only a long flag. */ + public convenience init(longFlag: String, required: Bool = false, helpMessage: String) { + self.init(nil, longFlag as String?, required, helpMessage) + } + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + if let v = T(rawValue: values[0]) { + _value = v + return true + } + + return false + } + +} + +#else + +open class EnumOption: Option { + fileprivate var _value: T? + open var value: T? { + return _value + } + + override open var wasSet: Bool { + return _value != nil + } + + override open var claimedValues: Int { + return _value != nil ? 1 : 0 + } + + /* Re-defining the intializers is necessary to make the Swift 2 compiler happy, as + * of Xcode 7 beta 2. + */ + + fileprivate override init(_ shortFlag: String?, _ longFlag: String?, _ required: Bool, _ helpMessage: String) { + super.init(shortFlag, longFlag, required, helpMessage) + } + + /** Initializes a new Option that has both long and short flags. */ + public convenience init(shortFlag: String, longFlag: String, required: Bool = false, helpMessage: String) { + self.init(shortFlag as String?, longFlag, required, helpMessage) + } + + /** Initializes a new Option that has only a short flag. */ + public convenience init(shortFlag: String, required: Bool = false, helpMessage: String) { + self.init(shortFlag as String?, nil, required, helpMessage) + } + + /** Initializes a new Option that has only a long flag. */ + public convenience init(longFlag: String, required: Bool = false, helpMessage: String) { + self.init(nil, longFlag as String?, required, helpMessage) + } + + override func setValue(_ values: [String]) -> Bool { + if values.count == 0 { + return false + } + + if let v = T(rawValue: values[0]) { + _value = v + return true + } + + return false + } + +} + +#endif diff --git a/Carthage/CommandLine/StringExtensions.swift b/Carthage/CommandLine/StringExtensions.swift new file mode 100644 index 0000000..b8f703c --- /dev/null +++ b/Carthage/CommandLine/StringExtensions.swift @@ -0,0 +1,213 @@ +/* + * StringExtensions.swift + * Copyright (c) 2014 Ben Gollmer. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Required for localeconv(3) */ +#if os(OSX) + import Darwin +#elseif os(Linux) + import Glibc +#endif + +internal extension String { + /* Retrieves locale-specified decimal separator from the environment + * using localeconv(3). + */ + fileprivate func _localDecimalPoint() -> Character { + let locale = localeconv() + if locale != nil { + #if swift(>=3.0) + if let decimalPoint = locale?.pointee.decimal_point { + return Character(UnicodeScalar(UInt32(decimalPoint.pointee))!) + } + #else + let decimalPoint = locale.pointee.decimal_point + if decimalPoint != nil { + return Character(UnicodeScalar(UInt32(decimalPoint.pointee))) + } + #endif + } + + return "." + } + + /** + * Attempts to parse the string value into a Double. + * + * - returns: A Double if the string can be parsed, nil otherwise. + */ + func toDouble() -> Double? { + var characteristic: String = "0" + var mantissa: String = "0" + var inMantissa: Bool = false + var isNegative: Bool = false + let decimalPoint = self._localDecimalPoint() + + #if swift(>=3.0) + let charactersEnumerator = self.characters.enumerated() + #else + let charactersEnumerator = self.characters.enumerated() + #endif + for (i, c) in charactersEnumerator { + if i == 0 && c == "-" { + isNegative = true + continue + } + + if c == decimalPoint { + inMantissa = true + continue + } + + if Int(String(c)) != nil { + if !inMantissa { + characteristic.append(c) + } else { + mantissa.append(c) + } + } else { + /* Non-numeric character found, bail */ + return nil + } + } + + let doubleCharacteristic = Double(Int(characteristic)!) + return (doubleCharacteristic + + Double(Int(mantissa)!) / pow(Double(10), Double(mantissa.characters.count - 1))) * + (isNegative ? -1 : 1) + } + + #if swift(>=3.0) + /** + * Splits a string into an array of string components. + * + * - parameter by: The character to split on. + * - parameter maxSplits: The maximum number of splits to perform. If 0, all possible splits are made. + * + * - returns: An array of string components. + */ + func split(by: Character, maxSplits: Int = 0) -> [String] { + var s = [String]() + var numSplits = 0 + + var curIdx = self.startIndex + for i in self.characters.indices { + let c = self[i] + if c == by && (maxSplits == 0 || numSplits < maxSplits) { + s.append(String(self[curIdx.. [String] { + var s = [String]() + var numSplits = 0 + + var curIdx = self.startIndex + for i in self.characters.indices { + let c = self[i] + if c == by && (maxSplits == 0 || numSplits < maxSplits) { + s.append(self[curIdx...index(after: i) + numSplits += 1 + } + } + + if curIdx != self.endIndex { + s.append(self[curIdx.. String { + var s = self + var currentLength = self.characters.count + + while currentLength < width { + s.append(padChar) + currentLength += 1 + } + + return s + } + + /** + * Wraps a string to the specified width. + * + * This just does simple greedy word-packing, it doesn't go full Knuth-Plass. + * If a single word is longer than the line width, it will be placed (unsplit) + * on a line by itself. + * + * - parameter atWidth: The maximum length of a line. + * - parameter wrapBy: The line break character to use. + * - parameter splitBy: The character to use when splitting the string into words. + * + * - returns: A new string, wrapped at the given width. + */ + func wrapped(atWidth width: Int, wrapBy: Character = "\n", splitBy: Character = " ") -> String { + var s = "" + var currentLineWidth = 0 + + for word in self.split(by: splitBy) { + let wordLength = word.characters.count + + if currentLineWidth + wordLength + 1 > width { + /* Word length is greater than line length, can't wrap */ + if wordLength >= width { + s += word + } + + s.append(wrapBy) + currentLineWidth = 0 + } + + currentLineWidth += wordLength + 1 + s += word + s.append(splitBy) + } + + return s + } +} diff --git a/Carthage/HandySwift/Extensions/ArrayExtension.swift b/Carthage/HandySwift/Extensions/ArrayExtension.swift new file mode 100644 index 0000000..f3656e6 --- /dev/null +++ b/Carthage/HandySwift/Extensions/ArrayExtension.swift @@ -0,0 +1,135 @@ +// +// ArrayExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 26.12.15. +// Copyright © 2015 Flinesoft. All rights reserved. +// + +import Foundation + +extension Array { + /// Returns a random element from the `Array`. + /// + /// - Returns: A random element from the array or `nil` if empty. + public var sample: Element? { + guard let randomIndex = Int(randomBelow: count) else { return nil } + return self[randomIndex] + } + + /// Returns a given number of random elements from the `Array`. + /// + /// - Parameters: + /// - size: The number of random elements wanted. + /// - Returns: An array with the given number of random elements or `nil` if empty. + public func sample(size: Int) -> [Element]? { + if isEmpty { return nil } + + var sampleElements: [Element] = [] + size.times { sampleElements.append(sample!) } + + return sampleElements + } + + /// Combines each element with each element of a given array. + /// + /// Also known as: Cartesian product. + /// + /// - Parameters: + /// - other: Other array to combine the elements with. + /// - Returns: An array of tuples with the elements of both arrays combined. + public func combinations(with other: [T]) -> [(Element, T)] { + var combinations = [(Element, T)]() + forEach { elem in other.forEach { otherElem in combinations.append((elem, otherElem)) } } + + return combinations + } + + /// Sorts the collection in place by the order specified in the closure. + /// + /// NOTE: The default `sort` method is not stable, this one allows to explicitly specify it to be stable. + /// + /// - Parameters: + /// - stable: Speifies if the sorting algorithm should be stable. + /// - areInIncreasingOrder: The closure to specify the order of the elements to be sorted by. + public mutating func sort(by areInIncreasingOrder: @escaping (Element, Element) -> Bool, stable: Bool) { + guard stable else { sort(by: areInIncreasingOrder); return } + stableMergeSort(by: areInIncreasingOrder) + } + + /// Returns the elements of the sequence, sorted. + /// + /// NOTE: The default `sorted` method is not stable, this one allows to explicitly specify it to be stable. + /// + /// - Parameters: + /// - stable: Speifies if the sorting algorithm should be stable. + /// - areInIncreasingOrder: The closure to specify the order of the elements to be sorted by. + public func sorted(by areInIncreasingOrder: @escaping (Element, Element) -> Bool, stable: Bool) -> [Element] { + guard stable else { return sorted(by: areInIncreasingOrder) } + + var copy = [Element](self) + copy.stableMergeSort(by: areInIncreasingOrder) + + return copy + } + + /// Sorts the array in-place using a stable merge sort algorithm. + mutating func stableMergeSort(by areInIncreasingOrder: @escaping (Element, Element) -> Bool) { + var tmp = [Element]() + tmp.reserveCapacity(numericCast(count)) + + func merge(low: Int, mid: Int, high: Int) { + tmp.removeAll(keepingCapacity: true) + tmp.append(contentsOf: self[low.. [Element] { + return sorted(by: { lhs, rhs in lhs < rhs }, stable: stable) + } +} diff --git a/Carthage/HandySwift/Extensions/CharacterViewExtension.swift b/Carthage/HandySwift/Extensions/CharacterViewExtension.swift new file mode 100644 index 0000000..8a02fba --- /dev/null +++ b/Carthage/HandySwift/Extensions/CharacterViewExtension.swift @@ -0,0 +1,32 @@ +// +// CharacterViewExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 29.12.15. +// Copyright © 2015 Flinesoft. All rights reserved. +// + +import Foundation + +extension String.CharacterView { + /// Returns a random character from the `ChracterView`. + /// + /// - Returns: A random character from the `CharacterView` or `nil` if empty. + public var sample: Character? { + return isEmpty ? nil : self[index(startIndex, offsetBy: Int(randomBelow: count)!)] + } + + /// Returns a given number of random characters from the `CharacterView`. + /// + /// - Parameters: + /// - size: The number of random characters wanted. + /// - Returns: A `CharacterView` with the given number of random characters or `nil` if empty. + public func sample(size: Int) -> String.CharacterView? { + if isEmpty { return nil } + + var sampleElements = String.CharacterView() + size.times { sampleElements.append(sample!) } + + return sampleElements + } +} diff --git a/Carthage/HandySwift/Extensions/DictionaryExtension.swift b/Carthage/HandySwift/Extensions/DictionaryExtension.swift new file mode 100644 index 0000000..dbe02dd --- /dev/null +++ b/Carthage/HandySwift/Extensions/DictionaryExtension.swift @@ -0,0 +1,43 @@ +// +// DictionaryExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 16.01.16. +// Copyright © 2016 Flinesoft. All rights reserved. +// + +import Foundation + +extension Dictionary { + /// Initializes a new `Dictionary` and fills it with keys and values arrays. + /// + /// - Parameters: + /// - keys: The `Array` of keys. + /// - values: The `Array` of values. + public init?(keys: [Key], values: [Value]) { + guard keys.count == values.count else { return nil } + self.init() + for (index, key) in keys.enumerated() { self[key] = values[index] } + } + + /// Merge given `Dictionary` into this `Dictionary` overriding existing values for matching keys. + /// + /// - Parameters: + /// - otherDictionary: The other `Dictionary` to merge into this `Dictionary`. + public mutating func merge(_ other: [Key: Value]) { + for (key, value) in other { self[key] = value } + } + + /// Create new merged `Dictionary` with the given `Dictionary` merged into this `Dictionary` + /// overriding existing values for matching keys. + /// + /// - Parameters: + /// - otherDictionary: The other `Dictionary` to merge into this `Dictionary`. + /// - Returns: The new Dictionary with merged keys and values from this and the other `Dictionary`. + public func merged(with other: [Key: Value]) -> [Key: Value] { + var newDict: [Key: Value] = [:] + [self, other].forEach { dict in for (key, value) in dict { newDict[key] = value } } + + return newDict + } +} diff --git a/Carthage/HandySwift/Extensions/DispatchTimeIntervalExtension.swift b/Carthage/HandySwift/Extensions/DispatchTimeIntervalExtension.swift new file mode 100644 index 0000000..e8ad131 --- /dev/null +++ b/Carthage/HandySwift/Extensions/DispatchTimeIntervalExtension.swift @@ -0,0 +1,31 @@ +// +// DispatchTimeIntervalExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 28.01.17. +// Copyright © 2017 Flinesoft. All rights reserved. +// + +import Foundation + +extension DispatchTimeInterval { + /// - Returns: The time in seconds using the`TimeInterval` type. + public var timeInterval: TimeInterval { + switch self { + case .seconds(let seconds): + return Double(seconds) + + case .milliseconds(let milliseconds): + return Double(milliseconds) / Timespan.millisecondsPerSecond + + case .microseconds(let microseconds): + return Double(microseconds) / Timespan.microsecondsPerSecond + + case .nanoseconds(let nanoseconds): + return Double(nanoseconds) / Timespan.nanosecondsPerSecond + + case .never: + return TimeInterval.infinity + } + } +} diff --git a/Carthage/HandySwift/Extensions/IntExtension.swift b/Carthage/HandySwift/Extensions/IntExtension.swift new file mode 100644 index 0000000..804baa9 --- /dev/null +++ b/Carthage/HandySwift/Extensions/IntExtension.swift @@ -0,0 +1,20 @@ +// +// IntegerTypeExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 18.12.15. +// Copyright © 2015 Flinesoft. All rights reserved. +// + +import Foundation + +extension Int { + /// Initializes a new `Int ` instance with a random value below a given `Int`. + /// + /// - Parameters: + /// - randomBelow: The upper bound value to create a random value with. + public init?(randomBelow upperLimit: Int) { + guard upperLimit > 0 else { return nil } + self.init(arc4random_uniform(UInt32(upperLimit))) + } +} diff --git a/Carthage/HandySwift/Extensions/IntegerTypeExtension.swift b/Carthage/HandySwift/Extensions/IntegerTypeExtension.swift new file mode 100644 index 0000000..ee4ec04 --- /dev/null +++ b/Carthage/HandySwift/Extensions/IntegerTypeExtension.swift @@ -0,0 +1,20 @@ +// +// IntegerTypeExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 29.12.15. +// Copyright © 2015 Flinesoft. All rights reserved. +// + +import Foundation + +extension Int { + /// Runs the code passed as a closure the specified number of times. + /// + /// - Parameters: + /// - closure: The code to be run multiple times. + public func times(_ closure: () -> Void) { + guard self > 0 else { return } + for _ in 0.. String { return trimmingCharacters(in: .whitespacesAndNewlines) } +} + +extension String { + /// The type of allowed characters. + /// + /// - Numeric: Allow all numbers from 0 to 9. + /// - Alphabetic: Allow all alphabetic characters ignoring case. + /// - AlphaNumeric: Allow both numbers and alphabetic characters ignoring case. + /// - AllCharactersIn: Allow all characters appearing within the specified String. + public enum AllowedCharacters { + case numeric + case alphabetic + case alphaNumeric + case allCharactersIn(String) + } +} diff --git a/Carthage/HandySwift/Extensions/TimeIntervalExtension.swift b/Carthage/HandySwift/Extensions/TimeIntervalExtension.swift new file mode 100644 index 0000000..0ff1d7b --- /dev/null +++ b/Carthage/HandySwift/Extensions/TimeIntervalExtension.swift @@ -0,0 +1,94 @@ +// +// TimeIntervalExtension.swift +// HandySwift +// +// Created by Cihat Gündüz on 18.02.17. +// Copyright © 2017 Flinesoft. All rights reserved. +// + +import Foundation + +/// A typealias to keep backwards compatibility with version 2.0.x and 2.1.x. +public typealias Timespan = TimeInterval + +extension TimeInterval { + // MARK: - Computed Type Properties + internal static var secondsPerDay: Double { return 24 * 60 * 60 } + internal static var secondsPerHour: Double { return 60 * 60 } + internal static var secondsPerMinute: Double { return 60 } + internal static var millisecondsPerSecond: Double { return 1_000 } + internal static var microsecondsPerSecond: Double { return 1_000 * 1_000 } + internal static var nanosecondsPerSecond: Double { return 1_000 * 1_000 * 1_000 } + + // MARK: - Computed Instance Properties + /// - Returns: The `TimeInterval` in days. + public var days: Double { + return self / TimeInterval.secondsPerDay + } + + /// - Returns: The `TimeInterval` in hours. + public var hours: Double { + return self / TimeInterval.secondsPerHour + } + + /// - Returns: The `TimeInterval` in minutes. + public var minutes: Double { + return self / TimeInterval.secondsPerMinute + } + + /// - Returns: The `TimeInterval` in seconds. + public var seconds: Double { + return self + } + + /// - Returns: The `TimeInterval` in milliseconds. + public var milliseconds: Double { + return self * TimeInterval.millisecondsPerSecond + } + + /// - Returns: The `TimeInterval` in microseconds. + public var microseconds: Double { + return self * TimeInterval.microsecondsPerSecond + } + + /// - Returns: The `TimeInterval` in nanoseconds. + public var nanoseconds: Double { + return self * TimeInterval.nanosecondsPerSecond + } + + // MARK: - Type Methods + /// - Returns: The time in days using the `TimeInterval` type. + public static func days(_ value: Double) -> TimeInterval { + return value * secondsPerDay + } + + /// - Returns: The time in hours using the `TimeInterval` type. + public static func hours(_ value: Double) -> TimeInterval { + return value * secondsPerHour + } + + /// - Returns: The time in minutes using the `TimeInterval` type. + public static func minutes(_ value: Double) -> TimeInterval { + return value * secondsPerMinute + } + + /// - Returns: The time in seconds using the `TimeInterval` type. + public static func seconds(_ value: Double) -> TimeInterval { + return value + } + + /// - Returns: The time in milliseconds using the `TimeInterval` type. + public static func milliseconds(_ value: Double) -> TimeInterval { + return value / millisecondsPerSecond + } + + /// - Returns: The time in microseconds using the `TimeInterval` type. + public static func microseconds(_ value: Double) -> TimeInterval { + return value / microsecondsPerSecond + } + + /// - Returns: The time in nanoseconds using the `TimeInterval` type. + public static func nanoseconds(_ value: Double) -> TimeInterval { + return value / nanosecondsPerSecond + } +} diff --git a/Carthage/HandySwift/Globals.swift b/Carthage/HandySwift/Globals.swift new file mode 100644 index 0000000..81ebbc3 --- /dev/null +++ b/Carthage/HandySwift/Globals.swift @@ -0,0 +1,20 @@ +// +// Globals.swift +// HandySwift +// +// Created by Cihat Gündüz on 07.06.16. +// Copyright © 2016 Flinesoft. All rights reserved. +// + +import Foundation + +/// Runs code with delay given in seconds. Uses the main thread if not otherwise specified. +/// +/// - Parameters: +/// - delayTime: The duration of the delay. E.g. `.seconds(1)` or `.milliseconds(200)`. +/// - qosClass: The global QOS class to be used or `nil` to use the main thread. Defaults to `nil`. +/// - closure: The code to run with a delay. +public func delay(by delayTime: Timespan, qosClass: DispatchQoS.QoSClass? = nil, _ closure: @escaping () -> Void) { + let dispatchQueue = qosClass != nil ? DispatchQueue.global(qos: qosClass!) : DispatchQueue.main + dispatchQueue.asyncAfter(deadline: DispatchTime.now() + delayTime, execute: closure) +} diff --git a/Carthage/HandySwift/Structs/FrequencyTable.swift b/Carthage/HandySwift/Structs/FrequencyTable.swift new file mode 100644 index 0000000..b14d99c --- /dev/null +++ b/Carthage/HandySwift/Structs/FrequencyTable.swift @@ -0,0 +1,50 @@ +// +// FrequencyTable.swift +// HandySwift +// +// Created by Cihat Gündüz on 03.01.16. +// Copyright © 2016 Flinesoft. All rights reserved. +// + +import Foundation + +/// Data structure to retrieve random values with their frequency taken into account. +public struct FrequencyTable { + // MARK: - Sub Types + typealias Entry = (value: T, frequency: Int) + + // MARK: - Stored Instance Properties + private let valuesWithFrequencies: [Entry] + + /// Contains all values the amount of time of their frequencies. + private let frequentValues: [T] + + // MARK: - Initializers + /// Creates a new FrequencyTable instance with values and their frequencies provided. + /// + /// - Parameters: + /// - values: An array full of values to be saved into the frequency table. + /// - frequencyClosure: The closure to specify the frequency for a specific value. + public init(values: [T], frequencyClosure: (T) -> Int) { + valuesWithFrequencies = values.map { ($0, frequencyClosure($0)) } + frequentValues = valuesWithFrequencies.reduce([]) { memo, entry in + return memo + Array(repeating: entry.value, count: entry.frequency) + } + } + + // MARK: - Computed Instance Properties + /// - Returns: A random value taking frequencies into account or nil if values empty. + public var sample: T? { return frequentValues.sample } + + // MARK: - Instance Methods + /// Returns an array of random values taking frequencies into account or nil if values empty. + /// + /// - Parameters: + /// - size: The size of the resulting array of random values. + /// + /// - Returns: An array of random values or nil if values empty. + public func sample(size: Int) -> [T]? { + guard size > 0 && !frequentValues.isEmpty else { return nil } + return Array(0.. { + // MARK: - Stored Instance Properties + private var internalArray: [Element] + + /// Returns the sorted array of elements. + public var array: [Element] { return self.internalArray } + + // MARK: - Initializers + /// Creates a new, empty array. + /// + /// For example: + /// + /// var emptyArray = SortedArray() + public init() { + internalArray = [] + } + + /// Creates a new SortedArray with a given sequence of elements and sorts its elements. + /// + /// - Complexity: The same as `sort()` on an Array –- probably O(n * log(n)). + /// + /// - Parameters: + /// - array: The array to be initially sorted and saved. + public init(_ sequence: S) where S.Iterator.Element == Element { + self.init(sequence: sequence, preSorted: false) + } + + private init(sequence: S, preSorted: Bool) where S.Iterator.Element == Element { + internalArray = preSorted ? Array(sequence) : Array(sequence).sorted() + } + + // MARK: - Instance Methods + /// Returns the first index in which an element of the array satisfies the given predicate. + /// Matching is done using binary search to minimize complexity. + /// + /// - Complexity: O(log(n)) + /// + /// - Parameters: + /// - predicate: The predicate to match the elements against. + /// - Returns: The index of the first matching element or `nil` if none of them matches. + public func index(where predicate: (Element) -> Bool) -> Int? { + // cover trivial cases + guard !array.isEmpty else { return nil } + if let first = array.first, predicate(first) { return array.startIndex } + if let last = array.last, !predicate(last) { return nil } + + // binary search for first matching element + var foundMatch = false + var lowerIndex = array.startIndex + var upperIndex = array.endIndex + + while lowerIndex != upperIndex { + let middleIndex = lowerIndex + (upperIndex - lowerIndex) / 2 + guard predicate(array[middleIndex]) else { lowerIndex = middleIndex + 1; continue } + + upperIndex = middleIndex + foundMatch = true + } + + guard foundMatch else { return nil } + return lowerIndex + } + + /// Returns a sub array of a SortedArray up to a given index (excluding it) without resorting. + /// + /// - Complexity: O(1) + /// + /// - Parameters: + /// - index: The upper bound index until which to include elements. + /// - Returns: A new SortedArray instance including all elements until the specified index (exluding it). + public func prefix(upTo index: Int) -> SortedArray { + let subarray = Array(array[array.indices.prefix(upTo: index)]) + return SortedArray(sequence: subarray, preSorted: true) + } + + /// Returns a sub array of a SortedArray up to a given index (including it) without resorting. + /// + /// - Complexity: O(1) + /// + /// - Parameters: + /// - index: The upper bound index until which to include elements. + /// - Returns: A new SortedArray instance including all elements until the specified index (including it). + public func prefix(through index: Int) -> SortedArray { + let subarray = Array(array[array.indices.prefix(through: index)]) + return SortedArray(sequence: subarray, preSorted: true) + } + + /// Returns a sub array of a SortedArray starting at a given index without resorting. + /// + /// - Complexity: O(1) + /// + /// - Parameters: + /// - index: The lower bound index from which to start including elements. + /// - Returns: A new SortedArray instance including all elements starting at the specified index. + public func suffix(from index: Int) -> SortedArray { + let subarray = Array(array[array.indices.suffix(from: index)]) + return SortedArray(sequence: subarray, preSorted: true) + } + + /// Accesses a contiguous subrange of the SortedArray's elements. + /// + /// - Parameter + /// - bounds: A range of the SortedArray's indices. The bounds of the range must be valid indices. + public subscript(bounds: Range) -> SortedArray { + return SortedArray(sequence: array[bounds], preSorted: true) + } + + // MARK: - Mutating Methods + /// Adds a new item to the sorted array. + /// + /// - Complexity: O(log(n)) + /// + /// - Parameters: + /// - newElement: The new element to be inserted into the array. + public mutating func insert(newElement: Element) { + let insertIndex = internalArray.index { $0 >= newElement } ?? internalArray.endIndex + internalArray.insert(newElement, at: insertIndex) + } + + /// Adds the contents of a sequence to the SortedArray. + /// + /// - Complexity: O(n * log(n)) + /// + /// - Parameters: + /// - sequence + public mutating func insert(contentsOf sequence: S) where S.Iterator.Element == Element { + sequence.forEach { insert(newElement: $0) } + } + + /// Removes an item from the sorted array. + /// + /// - Complexity: O(1) + /// + /// - Parameters: + /// - index: The index of the element to remove from the sorted array. + public mutating func remove(at index: Int) { + internalArray.remove(at: index) + } +} diff --git a/Carthage/HandySwift/Supporting Files/HandySwift.h b/Carthage/HandySwift/Supporting Files/HandySwift.h new file mode 100644 index 0000000..f6a7768 --- /dev/null +++ b/Carthage/HandySwift/Supporting Files/HandySwift.h @@ -0,0 +1,17 @@ +// +// HandySwift.h +// HandySwift +// +// Created by Cihat Gündüz on 18.12.15. +// Copyright © 2015 Flinesoft. All rights reserved. +// + +#import + +//! Project version number for HandySwift. +FOUNDATION_EXPORT double HandySwiftVersionNumber; + +//! Project version string for HandySwift. +FOUNDATION_EXPORT const unsigned char HandySwiftVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import \ No newline at end of file diff --git a/Carthage/HandySwift/Supporting Files/Info.plist b/Carthage/HandySwift/Supporting Files/Info.plist new file mode 100644 index 0000000..b6cbd28 --- /dev/null +++ b/Carthage/HandySwift/Supporting Files/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.4.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Carthage/Polyglot/Polyglot.swift b/Carthage/Polyglot/Polyglot.swift new file mode 100644 index 0000000..702ce7f --- /dev/null +++ b/Carthage/Polyglot/Polyglot.swift @@ -0,0 +1,184 @@ +// Polyglot.swift +// +// Copyright (c) 2014 Ayaka Nonaka +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/** + Supported languages. +*/ +public enum Language: String { + case Arabic = "ar" + case Bosnian = "bs" + case BosnianLatin = "bs-Latn" + case Bulgarian = "bg" + case Catalan = "ca" + case ChineseSimplified = "zh-CHS" + case ChineseTraditional = "zh-CHT" + case Croation = "hr" + case Czech = "cs" + case Danish = "da" + case Dutch = "nl" + case English = "en" + case Estonian = "et" + case Finnish = "fi" + case French = "fr" + case German = "de" + case Greek = "el" + case HaitianCreole = "ht" + case Hebrew = "he" + case Hindi = "hi" + case HmongDaw = "mww" + case Hungarian = "hu" + case Indonesian = "id" + case Italian = "it" + case Japanese = "ja" + case Kiswahili = "sw" + case Klingon = "tlh" + case KlingonPiqad = "tlh-Qaak" + case Korean = "ko" + case Latvian = "lv" + case Lithuanian = "lt" + case Malay = "ms" + case Maltese = "mt" + case Norwegian = "no" + case Persian = "fa" + case Polish = "pl" + case Portuguese = "pt" + case QueretaroOtomi = "otq" + case Romanian = "ro" + case Russian = "ru" + case Serbian = "sr" + case SerbianCyrillic = "sr-Cyrl" + case SerbianLatin = "sr-Latn" + case Slovak = "sk" + case Slovenian = "sl" + case Spanish = "es" + case Swedish = "sv" + case Thai = "th" + case Turkish = "tr" + case Ukrainian = "uk" + case Urdu = "ur" + case Vietnamese = "vi" + case Welsh = "cy" + case YucatecMaya = "yua" + + + /** Allows mapping between NSLocale identifiers and the Microsoft Translator identifiers. + + - parameter lang: The language code, e.g. 'en' or 'zh'. + - parameter region: The region, e.g. 'GB' or 'Hans'. + - returns: The Microsoft Translator API language defined in Polyglot via an enumeration. + */ + public static func languageForLocale(languageCode langCode: String, region: String?) -> Language? { + + if let region = region { + + switch (langCode, region) { + case ("zh", "Hans"): + return Language.ChineseSimplified + case ("zh", "Hant"): + return Language.ChineseTraditional + default: + if let language = Language(rawValue: "\(langCode)-\(region)") { + return language + } + } + } + + switch langCode { + case "nb": + return Language.Norwegian + default: + return Language(rawValue: langCode) + } + + } +} + +/** + Responsible for translating text. +*/ +open class Polyglot { + + let session: Session + + /// The language to be translated from. It will automatically detect the language if you do not set this. + open var fromLanguage: Language? + + /// The language to translate to. + open var toLanguage: Language + + + /** + - parameter clientId: Microsoft Translator client ID. + - parameter clientSecret: Microsoft Translator client secret. + */ + public init(clientId: String, clientSecret: String) { + session = Session(clientId: clientId, clientSecret: clientSecret) + toLanguage = Language.English + } + + /** + Translates a given piece of text asynchronously. Switch to the main thread within the callback + if you want to update your UI by using `dispatch_async(dispatch_get_main_queue()) { /* code */ }`. + + - parameter text: The text to translate. + - parameter callback: The code to be executed once the translation has completed. + */ + open func translate(_ text: String, callback: @escaping ((_ translation: String) -> (Void))) { + session.getAccessToken { token in + if self.fromLanguage == nil { + self.fromLanguage = text.language + } + let toLanguageComponent = "&to=\(self.toLanguage.rawValue.urlEncoded!)" + let fromLanguageComponent = (self.fromLanguage != nil) ? "&from=\(self.fromLanguage!.rawValue.urlEncoded!)" : "" + let urlString = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=\(text.urlEncoded!)\(toLanguageComponent)\(fromLanguageComponent)" + + var request = URLRequest(url: URL(string: urlString)!) + request.httpMethod = "GET" + request.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") + + let task = URLSession.shared.dataTask(with: request, completionHandler: {(data, response, error) in + let translation: String + guard + let data = data, + let xmlString = NSString(data: data, encoding: String.Encoding.utf8.rawValue) as String? + else { + translation = "" + return + } + + translation = self.translationFromXML(xmlString) + + defer { + callback(translation) + } + }) + task.resume() + } + } + + fileprivate func translationFromXML(_ XML: String) -> String { + let translation = XML.replacingOccurrences(of: "", with: "") + return translation.replacingOccurrences(of: "", with: "") + } +} diff --git a/Carthage/Polyglot/Session.swift b/Carthage/Polyglot/Session.swift new file mode 100644 index 0000000..01a1fd6 --- /dev/null +++ b/Carthage/Polyglot/Session.swift @@ -0,0 +1,74 @@ +// Session.swift +// +// Copyright (c) 2014 Ayaka Nonaka +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +class Session { + + let clientId: String + let clientSecret: String + + var accessToken: String? + var expirationTime: Date? + + init(clientId: String, clientSecret: String) { + self.clientId = clientId + self.clientSecret = clientSecret + } + + func getAccessToken(_ callback: @escaping ((_ token: String) -> (Void))) { + if (accessToken == nil || isExpired) { + let url = URL(string: "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13") + + var request = URLRequest(url: url!) + request.httpMethod = "POST" + + let bodyString = "client_id=\(clientId.urlEncoded!)&client_secret=\(clientSecret.urlEncoded!)&scope=http://api.microsofttranslator.com&grant_type=client_credentials" + request.httpBody = bodyString.data(using: String.Encoding.utf8) + + let task = URLSession.shared.dataTask(with: request, completionHandler: {(data, response, error) in + guard + let data = data, + let resultsDict = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any], + let expiresIn = resultsDict?["expires_in"] as? NSString + else { + callback("") + return + } + self.expirationTime = Date(timeIntervalSinceNow: expiresIn.doubleValue) + + let token = resultsDict?["access_token"] as! String + self.accessToken = token + + callback(token) + }) + + task.resume() + } else { + callback(accessToken!) + } + } + + fileprivate var isExpired: Bool { + return (expirationTime as NSDate?)?.earlierDate(Date()) == self.expirationTime + } +} diff --git a/Carthage/Polyglot/StringExtensionPolyglot.swift b/Carthage/Polyglot/StringExtensionPolyglot.swift new file mode 100644 index 0000000..7b43bbe --- /dev/null +++ b/Carthage/Polyglot/StringExtensionPolyglot.swift @@ -0,0 +1,44 @@ +// StringExtension.swift +// +// Copyright (c) 2014 Ayaka Nonaka +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +extension String { + + public var urlEncoded: String? { + let urlQueryAllowedCharacterSet: NSMutableCharacterSet = (CharacterSet.urlQueryAllowed as NSCharacterSet).mutableCopy() as! NSMutableCharacterSet + urlQueryAllowedCharacterSet.removeCharacters(in: "&=?+") + return self.addingPercentEncoding(withAllowedCharacters: urlQueryAllowedCharacterSet as CharacterSet) + } + + public var language: Language? { + if characters.count > 0 { // Prevent Index Out of Bounds in NSLinguisticTagger + let tagger = NSLinguisticTagger(tagSchemes: [NSLinguisticTagScheme.language], options: 0) + tagger.string = self + if let result = tagger.tag(at: 0, scheme: NSLinguisticTagScheme.language, tokenRange: nil, sentenceRange: nil) { + return Language(rawValue: result.rawValue) + } + } + return nil + } + +} diff --git a/Sources/Code/CodeCommander.swift b/Sources/Code/CodeCommander.swift index 6ecd6f1..a306d15 100644 --- a/Sources/Code/CodeCommander.swift +++ b/Sources/Code/CodeCommander.swift @@ -1,5 +1,5 @@ // -// BaseCodeCommander.swift +// CodeCommander.swift // BartyCrouch // // Created by Fyodor Volchyok on 12/9/16. @@ -14,7 +14,9 @@ protocol CodeCommander { extension CodeCommander { func findFiles(in codeDirectoryPath: String) -> Commander.CommandLineResult { - return Commander.shared.run(command: "/usr/bin/find", arguments: - [codeDirectoryPath, "-name", "*.[hm]", "-o", "-name", "*.mm", "-o", "-name", "*.swift"]) + return Commander.shared.run( + command: "/usr/bin/find", + arguments: [codeDirectoryPath, "-name", "*.[hm]", "-o", "-name", "*.mm", "-o", "-name", "*.swift"] + ) } } diff --git a/Sources/Code/CommandLineActor.swift b/Sources/Code/CommandLineActor.swift index d9f0943..b56dcba 100644 --- a/Sources/Code/CommandLineActor.swift +++ b/Sources/Code/CommandLineActor.swift @@ -17,7 +17,6 @@ public enum CommandLineAction { public class CommandLineActor { // MARK: - Instance Methods - public func act(commonOptions: CommandLineParser.CommonOptions, subCommandOptions: CommandLineParser.SubCommandOptions) { guard let path = commonOptions.path.value else { printError("Path option `-p` is missing.") @@ -28,7 +27,7 @@ public class CommandLineActor { let verbose = commonOptions.verbose.value switch subCommandOptions { - case let .codeOptions(localizableOption, defaultToKeysOption, additiveOption, overrideComments, useExtractLocStrings, sortByKeys, unstripped, customFunction): + case let .codeOptions(localizableOption, defaultToKeysOption, additiveOption, overrideComments, useExtractLocStrings, sortByKeys, unstripped, customFunction): // swiftlint:disable:this line_length guard let localizable = localizableOption.value else { printError("Localizable option `-l` is missing.") exit(EX_USAGE) @@ -79,9 +78,11 @@ public class CommandLineActor { } } - self.incrementalCodeUpdate(inputDirectoryPath: path, allLocalizableStringsFilePaths, override: override, verbose: verbose, defaultToKeys: defaultToKeys, - additive: additive, overrideComments: overrideComments, useExtractLocStrings: useExtractLocStrings, sortByKeys: sortByKeys, - unstripped: unstripped, customFunction: customFunction) + self.incrementalCodeUpdate( + inputDirectoryPath: path, allLocalizableStringsFilePaths, override: override, verbose: verbose, defaultToKeys: defaultToKeys, + additive: additive, overrideComments: overrideComments, useExtractLocStrings: useExtractLocStrings, sortByKeys: sortByKeys, + unstripped: unstripped, customFunction: customFunction + ) } private func actOnInterfaces(path: String, override: Bool, verbose: Bool, defaultToBase: Bool, unstripped: Bool) { @@ -107,7 +108,9 @@ public class CommandLineActor { } } - self.incrementalInterfacesUpdate(inputFilePath, outputStringsFilePaths, override: override, verbose: verbose, defaultToBase: defaultToBase, unstripped: unstripped) + self.incrementalInterfacesUpdate( + inputFilePath, outputStringsFilePaths, override: override, verbose: verbose, defaultToBase: defaultToBase, unstripped: unstripped + ) } } @@ -138,8 +141,10 @@ public class CommandLineActor { } } - private func incrementalCodeUpdate(inputDirectoryPath: String, _ outputStringsFilePaths: [String], override: Bool, verbose: Bool, defaultToKeys: Bool, - additive: Bool, overrideComments: Bool, useExtractLocStrings: Bool, sortByKeys: Bool, unstripped: Bool, customFunction: String?) { + private func incrementalCodeUpdate( + inputDirectoryPath: String, _ outputStringsFilePaths: [String], override: Bool, verbose: Bool, defaultToKeys: Bool, + additive: Bool, overrideComments: Bool, useExtractLocStrings: Bool, sortByKeys: Bool, unstripped: Bool, customFunction: String? + ) { let extractedStringsFileDirectory = inputDirectoryPath + "/tmpstrings/" do { @@ -151,7 +156,9 @@ public class CommandLineActor { let codeCommander: CodeCommander = useExtractLocStrings ? ExtractLocStringsCommander.shared : GenStringsCommander.shared - guard codeCommander.export(stringsFilesToPath: extractedStringsFileDirectory, fromCodeInDirectoryPath: inputDirectoryPath, customFunction: customFunction) else { + guard codeCommander.export( + stringsFilesToPath: extractedStringsFileDirectory, fromCodeInDirectoryPath: inputDirectoryPath, customFunction: customFunction + ) else { printError("Could not extract strings from Code in directory '\(inputDirectoryPath)'.") exit(EX_UNAVAILABLE) } @@ -168,9 +175,11 @@ public class CommandLineActor { exit(EX_CONFIG) } - stringsFileUpdater.incrementallyUpdateKeys(withStringsFileAtPath: extractedLocalizableStringsFilePath, addNewValuesAsEmpty: !defaultToKeys, - override: override, keepExistingKeys: additive, overrideComments: overrideComments, sortByKeys: sortByKeys, - keepWhitespaceSurroundings: unstripped) + stringsFileUpdater.incrementallyUpdateKeys( + withStringsFileAtPath: extractedLocalizableStringsFilePath, addNewValuesAsEmpty: !defaultToKeys, + override: override, keepExistingKeys: additive, overrideComments: overrideComments, sortByKeys: sortByKeys, + keepWhitespaceSurroundings: unstripped + ) if verbose { print("Incrementally updated keys of file '\(outputStringsFilePath)'.") } } @@ -185,7 +194,9 @@ public class CommandLineActor { print("BartyCrouch: Successfully updated strings file(s) of Code files.") } - private func incrementalInterfacesUpdate(_ inputFilePath: String, _ outputStringsFilePaths: [String], override: Bool, verbose: Bool, defaultToBase: Bool, unstripped: Bool) { + private func incrementalInterfacesUpdate( + _ inputFilePath: String, _ outputStringsFilePaths: [String], override: Bool, verbose: Bool, defaultToBase: Bool, unstripped: Bool + ) { let extractedStringsFilePath = inputFilePath + ".tmpstrings" guard IBToolCommander.shared.export(stringsFileToPath: extractedStringsFilePath, fromIbFileAtPath: inputFilePath) else { @@ -199,8 +210,12 @@ public class CommandLineActor { exit(EX_CONFIG) } - stringsFileUpdater.incrementallyUpdateKeys(withStringsFileAtPath: extractedStringsFilePath, addNewValuesAsEmpty: !defaultToBase, override: override, - keepWhitespaceSurroundings: unstripped) + stringsFileUpdater.incrementallyUpdateKeys( + withStringsFileAtPath: extractedStringsFilePath, + addNewValuesAsEmpty: !defaultToBase, + override: override, + keepWhitespaceSurroundings: unstripped + ) if verbose { print("Incrementally updated keys of file '\(outputStringsFilePath)'.") @@ -227,7 +242,9 @@ public class CommandLineActor { exit(EX_CONFIG) } - let translationsCount = stringsFileUpdater.translateEmptyValues(usingValuesFromStringsFile: inputFilePath, clientId: id, clientSecret: secret, override: override) + let translationsCount = stringsFileUpdater.translateEmptyValues( + usingValuesFromStringsFile: inputFilePath, clientId: id, clientSecret: secret, override: override + ) if verbose { print("Translated file '\(outputStringsFilePath)' with \(translationsCount) changes.") } @@ -240,9 +257,7 @@ public class CommandLineActor { print("BartyCrouch: Successfully translated \(overallTranslatedValuesCount) values in \(filesWithTranslatedValuesCount) files.") } - // MARK: - Helper Methods - private func printError(_ message: String) { print("Error! \(message)") } diff --git a/Sources/Code/CommandLineParser.swift b/Sources/Code/CommandLineParser.swift index 7b5bd85..84cfccf 100644 --- a/Sources/Code/CommandLineParser.swift +++ b/Sources/Code/CommandLineParser.swift @@ -10,7 +10,6 @@ import Foundation public class CommandLineParser { // MARK: - Sub Types - public enum SubCommand: String { case code case interfaces @@ -33,24 +32,68 @@ public class CommandLineParser { case translateOptions(id: StringOption, secret: StringOption, locale: StringOption) } - // MARK: - Stored Instance Properties - private var commonOptions: CommonOptions? private var subCommandOptions: SubCommandOptions? let arguments: [String] + // MARK: Options + private let defaultToKeys = BoolOption( + shortFlag: "k", + longFlag: "default-to-keys", + required: false, + helpMessage: "Uses the keys as values when adding new keys from code." + ) + + private let additive = BoolOption( + shortFlag: "a", + longFlag: "additive", + required: false, + helpMessage: "Only adds new keys keeping all existing keys even when seemingly unused." + ) + + private let overrideComments = BoolOption( + shortFlag: "c", + longFlag: "override-comments", + required: false, + helpMessage: "Overrides existing translation comments." + ) + + private let useExtractLocStrings = BoolOption( + shortFlag: "e", + longFlag: "extract-loc-strings", + required: false, + helpMessage: "Uses the extractLocStrings tool instead of genstrings." + ) + + private let sortByKeys = BoolOption( + shortFlag: "s", + longFlag: "sort-by-keys", + required: false, + helpMessage: "Sorts the entries in the resulting Strings file by keys." + ) + + private let unstripped = BoolOption( + shortFlag: "u", + longFlag: "unstripped", + required: false, + helpMessage: "Keep newlines at beginning/end of Strings files." + ) + + private let customFunction = StringOption( + shortFlag: "f", + longFlag: "custom-function", + required: false, + helpMessage: "Specifies a custom function to be searched for instead of NSLocalizedString." + ) // MARK: - Initializers - public init(arguments: [String] = CommandLine.arguments) { self.arguments = arguments } - // MARK: - Instance Methods - public func parse(completion: (_ commonOptions: CommonOptions, _ subCommandOptions: SubCommandOptions) -> Void) { let subCommander = self.setupSubCommander() var commandLine: CommandLineKit! @@ -87,6 +130,7 @@ public class CommandLineParser { self.subCommandOptions = subCommandOptions return commandLine } + subCommander.addCommandLineBlock(commandLineBlock: commandLineBlock, forSubCommand: subCommand) } @@ -97,8 +141,10 @@ public class CommandLineParser { switch subCommand { case .code: return self.setupCodeCLI() + case .interfaces: return self.setupInterfacesCLI() + case .translate: return self.setupTranslateCLI() } @@ -117,21 +163,17 @@ public class CommandLineParser { let override = self.overrideOption(helpMessage: "Overrides existing translation values and comments. Use carefully.") let verbose = self.verboseOption() - let defaultToKeys = BoolOption(shortFlag: "k", longFlag: "default-to-keys", required: false, helpMessage: "Uses the keys as values when adding new keys from code.") - let additive = BoolOption(shortFlag: "a", longFlag: "additive", required: false, helpMessage: "Only adds new keys keeping all existing keys even when seemingly unused.") - let overrideComments = BoolOption(shortFlag: "c", longFlag: "override-comments", required: false, helpMessage: "Overrides existing translation comments.") - let useExtractLocStrings = BoolOption(shortFlag: "e", longFlag: "extract-loc-strings", required: false, helpMessage: "Uses the extractLocStrings tool instead of genstrings.") - let sortByKeys = BoolOption(shortFlag: "s", longFlag: "sort-by-keys", required: false, helpMessage: "Sorts the entries in the resulting Strings file by keys.") - let unstripped = BoolOption(shortFlag: "u", longFlag: "unstripped", required: false, helpMessage: "Keep newlines at beginning/end of Strings files.") - let customFunction = StringOption(shortFlag: "f", longFlag: "custom-function", required: false, helpMessage: "Specifies a custom function to be searched for instead of NSLocalizedString.") - let commonOptions: CommonOptions = (path: path, override: override, verbose: verbose) let subCommandOptions = SubCommandOptions.codeOptions( localizable: localizable, defaultToKeys: defaultToKeys, additive: additive, overrideComments: overrideComments, useExtractLocStrings: useExtractLocStrings, sortByKeys: sortByKeys, unstripped: unstripped, customFunction: customFunction ) - commandLine.addOptions(path, localizable, override, verbose, defaultToKeys, additive, overrideComments, useExtractLocStrings, sortByKeys, unstripped, customFunction) + commandLine.addOptions( + path, localizable, override, verbose, defaultToKeys, additive, overrideComments, + useExtractLocStrings, sortByKeys, unstripped, customFunction + ) + return (commandLine, commonOptions, subCommandOptions) } @@ -145,10 +187,14 @@ public class CommandLineParser { let override = self.overrideOption(helpMessage: "Overrides existing translation values and comments. Use carefully.") let verbose = self.verboseOption() - let defaultToBase = BoolOption(shortFlag: "b", longFlag: "default-to-base", required: false, - helpMessage: "Uses the values from the Base localized Interface Builder files when adding new keys.") - let unstripped = BoolOption(shortFlag: "u", longFlag: "unstripped", required: false, helpMessage: "Keep newlines at beginning/end of Strings files.") - + let defaultToBase = BoolOption( + shortFlag: "b", longFlag: "default-to-base", required: false, + helpMessage: "Uses the values from the Base localized Interface Builder files when adding new keys." + ) + let unstripped = BoolOption( + shortFlag: "u", longFlag: "unstripped", required: false, + helpMessage: "Keep newlines at beginning/end of Strings files." + ) let commonOptions: CommonOptions = (path: path, override: override, verbose: verbose) let subCommandOptions = SubCommandOptions.interfacesOptions(defaultToBase: defaultToBase, unstripped: unstripped) @@ -178,9 +224,7 @@ public class CommandLineParser { return (commandLine, commonOptions, subCommandOptions) } - // MARK: - Option Creator Methods - private func pathOption(helpMessage: String) -> StringOption { return StringOption(shortFlag: "p", longFlag: "path", required: true, helpMessage: helpMessage) } diff --git a/Sources/Code/Commander.swift b/Sources/Code/Commander.swift index 90c0321..6347c72 100644 --- a/Sources/Code/Commander.swift +++ b/Sources/Code/Commander.swift @@ -10,17 +10,12 @@ import Foundation class Commander { // MARK: - Define Sub Structures - typealias CommandLineResult = (outputs: [String], errors: [String], exitCode: Int32) - // MARK: - Stored Type Properties - static let shared = Commander() - // MARK: - Instance Methods - func run(command: String, arguments: [String]?) -> CommandLineResult { let task = Process() task.launchPath = command @@ -32,15 +27,15 @@ class Commander { task.standardError = errpipe task.launch() - + var errors: [String] = [] let errdata = errpipe.fileHandleForReading.readDataToEndOfFile() - + if var string = String(data: errdata, encoding: .utf8) { string = string.trimmingCharacters(in: .newlines) errors = string.components(separatedBy: "\n") } - + var outputs: [String] = [] let outdata = outpipe.fileHandleForReading.readDataToEndOfFile() diff --git a/Sources/Code/ExtractLocStringsCommander.swift b/Sources/Code/ExtractLocStringsCommander.swift index a5f4797..1d39136 100644 --- a/Sources/Code/ExtractLocStringsCommander.swift +++ b/Sources/Code/ExtractLocStringsCommander.swift @@ -11,17 +11,16 @@ import Foundation /// Sends `xcrun extractLocStrings` commands with specified input/output paths to bash. public class ExtractLocStringsCommander: CodeCommander { // MARK: - Stored Type Properties - public static let shared = ExtractLocStringsCommander() - // MARK: - Instance Methods - public func export(stringsFilesToPath stringsFilePath: String, fromCodeInDirectoryPath codeDirectoryPath: String, customFunction: String?) -> Bool { let findFilesResult = findFiles(in: codeDirectoryPath) let customFunctionArgs = customFunction != nil ? ["-s", "\(customFunction!)"] : [] - let exportFileResult = Commander.shared.run(command: "/usr/bin/xcrun", - arguments: ["extractLocStrings"] + findFilesResult.outputs + ["-o", stringsFilePath] + customFunctionArgs) + let exportFileResult = Commander.shared.run( + command: "/usr/bin/xcrun", + arguments: ["extractLocStrings"] + findFilesResult.outputs + ["-o", stringsFilePath] + customFunctionArgs + ) return findFilesResult.exitCode == 0 && exportFileResult.exitCode == 0 } } diff --git a/Sources/Code/GenStringsCommander.swift b/Sources/Code/GenStringsCommander.swift index 77c285c..a76de3c 100644 --- a/Sources/Code/GenStringsCommander.swift +++ b/Sources/Code/GenStringsCommander.swift @@ -11,16 +11,16 @@ import Foundation /// Sends `genstrings` commands with specified input/output paths to bash. public class GenStringsCommander: CodeCommander { // MARK: - Stored Type Properties - public static let shared = GenStringsCommander() - // MARK: - Instance Methods - public func export(stringsFilesToPath stringsFilePath: String, fromCodeInDirectoryPath codeDirectoryPath: String, customFunction: String?) -> Bool { let findFilesResult = findFiles(in: codeDirectoryPath) let customFunctionArgs = customFunction != nil ? ["-s", "\(customFunction!)"] : [] - let exportFileResult = Commander.shared.run(command: "/usr/bin/genstrings", arguments: findFilesResult.outputs + ["-o", stringsFilePath] + customFunctionArgs) + let exportFileResult = Commander.shared.run( + command: "/usr/bin/genstrings", + arguments: findFilesResult.outputs + ["-o", stringsFilePath] + customFunctionArgs + ) return findFilesResult.exitCode == 0 && exportFileResult.exitCode == 0 } } diff --git a/Sources/Code/IBToolCommander.swift b/Sources/Code/IBToolCommander.swift index 877f783..da2280b 100644 --- a/Sources/Code/IBToolCommander.swift +++ b/Sources/Code/IBToolCommander.swift @@ -11,12 +11,9 @@ import Foundation /// Sends `ibtool` commands with specified input/output paths to bash. public class IBToolCommander { // MARK: - Stored Type Properties - public static let shared = IBToolCommander() - // MARK: - Instance Methods - public func export(stringsFileToPath stringsFilePath: String, fromIbFileAtPath ibFilePath: String) -> Bool { let exportResult = Commander.shared.run(command: "/usr/bin/ibtool", arguments: ["--export-strings-file", stringsFilePath, ibFilePath]) @@ -26,5 +23,4 @@ public class IBToolCommander { return false } } - } diff --git a/Sources/Code/StringsFileUpdater.swift b/Sources/Code/StringsFileUpdater.swift index f9ba576..7db2f6d 100644 --- a/Sources/Code/StringsFileUpdater.swift +++ b/Sources/Code/StringsFileUpdater.swift @@ -12,23 +12,16 @@ import Foundation public class StringsFileUpdater { // MARK: - Sub Types - typealias TranslationEntry = (key: String, value: String, comment: String?, line: Int) - // MARK: - Stored Type Properties - - static let defaultIgnoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"] - + public static let defaultIgnoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"] // MARK: - Stored Instance Properties - let path: String var oldContentString: String = "" - // MARK: - Initializers - public init?(path: String) { self.path = path do { @@ -40,10 +33,12 @@ public class StringsFileUpdater { } // Updates the keys of this instances strings file with those of the given strings file. - public func incrementallyUpdateKeys(withStringsFileAtPath otherStringFilePath: String, - addNewValuesAsEmpty: Bool, ignoreBaseKeysAndComment ignores: [String] = defaultIgnoreKeys, - override: Bool = false, updateCommentWithBase: Bool = true, keepExistingKeys: Bool = false, - overrideComments: Bool = false, sortByKeys: Bool = false, keepWhitespaceSurroundings: Bool = false) { + public func incrementallyUpdateKeys( + withStringsFileAtPath otherStringFilePath: String, + addNewValuesAsEmpty: Bool, ignoreBaseKeysAndComment ignores: [String] = defaultIgnoreKeys, + override: Bool = false, updateCommentWithBase: Bool = true, keepExistingKeys: Bool = false, + overrideComments: Bool = false, sortByKeys: Bool = false, keepWhitespaceSurroundings: Bool = false + ) { do { let newContentString = try String(contentsOfFile: otherStringFilePath) @@ -51,15 +46,15 @@ public class StringsFileUpdater { var newTranslations = findTranslations(inString: newContentString) if let lastOldTranslation = oldTranslations.last { - newTranslations = newTranslations.map { ($0.0, $0.1, $0.2, $0.3+lastOldTranslation.line+1) } + newTranslations = newTranslations.map { ($0.0, $0.1, $0.2, $0.3 + lastOldTranslation.line + 1) } } let updatedTranslations: [TranslationEntry] = { var translations: [TranslationEntry] = [] if keepExistingKeys { - translations += oldTranslations.filter { (oldKey, _, _, _) in - return newTranslations.filter { (newKey, _, _, _) in oldKey == newKey }.isEmpty + translations += oldTranslations.filter { oldKey, _, _, _ in + return newTranslations.filter { newKey, _, _, _ in oldKey == newKey }.isEmpty } } @@ -70,14 +65,15 @@ public class StringsFileUpdater { // Skip keys that have been marked for ignore in comment if let newComment = newTranslation.comment, newComment.containsAny(of: ignores) { continue } - let oldTranslation = oldTranslations.first { (oldKey, _, _, _) in oldKey == newTranslation.key } + let oldTranslation = oldTranslations.first { oldKey, _, _, _ in oldKey == newTranslation.key } // get value from default comment structure if possible let oldBaseValue: String? = { - if let oldComment = oldTranslation?.comment, let foundMatch = defaultCommentStructureMatches(inString: oldComment) { - return (oldComment as NSString).substring(with: foundMatch.rangeAt(1)) + guard let oldComment = oldTranslation?.comment, let foundMatch = defaultCommentStructureMatches(inString: oldComment) else { + return nil } - return nil + + return (oldComment as NSString).substring(with: foundMatch.range(at: 1)) }() let updatedComment: String? = { @@ -121,7 +117,7 @@ public class StringsFileUpdater { let sortingClosure: (TranslationEntry, TranslationEntry) -> Bool = { if sortByKeys { - return { (translation1, translation2) in + return { translation1, translation2 in // ensure keys with empty values are appended to the end if translation1.value.isEmpty == translation2.value.isEmpty { return translation1.key.lowercased() < translation2.key.lowercased() @@ -130,7 +126,7 @@ public class StringsFileUpdater { } } } else { - return { (translation1, translation2) in translation1.line < translation2.line } + return { translation1, translation2 in translation1.line < translation2.line } } }() @@ -145,7 +141,9 @@ public class StringsFileUpdater { private func defaultCommentStructureMatches(inString string: String) -> NSTextCheckingResult? { // swiftlint:disable:next force_try - let defaultCommentStructureRegex = try! NSRegularExpression(pattern: "\\A Class = \".*\"; .* = \"(.*)\"; ObjectID = \".*\"; \\z", options: .caseInsensitive) + let defaultCommentStructureRegex = try! NSRegularExpression( + pattern: "\\A Class = \".*\"; .* = \"(.*)\"; ObjectID = \".*\"; \\z", options: .caseInsensitive + ) return defaultCommentStructureRegex.firstMatch(in: string, options: .reportCompletion, range: string.fullRange) } @@ -175,7 +173,7 @@ public class StringsFileUpdater { } } - newContentsOfFile = whitespacesOrNewlinesAtBegin + newContentsOfFile.strip + whitespacesOrNewlinesAtEnd + newContentsOfFile = whitespacesOrNewlinesAtBegin + newContentsOfFile.stripped() + whitespacesOrNewlinesAtEnd } try FileManager.default.removeItem(atPath: path) @@ -244,7 +242,7 @@ public class StringsFileUpdater { for sourceTranslation in sourceTranslations { let (sourceKey, sourceValue, sourceComment, sourceLine) = sourceTranslation - var targetTranslationOptional = existingTargetTranslations.filter { $0.0 == sourceKey }.first + var targetTranslationOptional = existingTargetTranslations.first { $0.0 == sourceKey } if targetTranslationOptional == nil { targetTranslationOptional = (sourceKey, "", sourceComment, sourceLine) @@ -254,6 +252,7 @@ public class StringsFileUpdater { NSException(name: NSExceptionName(rawValue: "targetTranslation was nil when not expected"), reason: nil, userInfo: nil).raise() exit(EXIT_FAILURE) } + let (key, value, comment, line) = targetTranslation guard value.isEmpty || override else { @@ -302,24 +301,28 @@ public class StringsFileUpdater { let newlineRegex = try! NSRegularExpression(pattern: "(\\n)", options: .useUnixLineSeparators) // swiftlint:enable force_try - let positionsOfNewlines = SortedArray(array: newlineRegex.matches(in: string, options: .reportCompletion, range: string.fullRange).map { $0.rangeAt(1).location }) + let positionsOfNewlines = SortedArray( + newlineRegex.matches(in: string, options: .reportCompletion, range: string.fullRange).map { $0.range(at: 1).location } + ) let matches = translationRegex.matches(in: string, options: .reportCompletion, range: string.fullRange) var translations: [TranslationEntry] = [] autoreleasepool { translations = matches.map { match in - let valueRange = match.rangeAt(match.numberOfRanges - 1) + let valueRange = match.range(at: match.numberOfRanges - 1) let value: String = (string as NSString).substring(with: valueRange) - let key = (string as NSString).substring(with: match.rangeAt(match.numberOfRanges - 2)) + let key = (string as NSString).substring(with: match.range(at: match.numberOfRanges - 2)) var comment: String? if match.numberOfRanges >= 4 { - let range = match.rangeAt(match.numberOfRanges - 3) + let range = match.range(at: match.numberOfRanges - 3) if range.location != NSNotFound && range.length > 0 { comment = (string as NSString).substring(with: range) } } - let numberOfNewlines = positionsOfNewlines.firstMatchingIndex { $0 > valueRange.location + valueRange.length } ?? positionsOfNewlines.array.count + + let numberOfNewlines = positionsOfNewlines.index { $0 > valueRange.location + valueRange.length } ?? positionsOfNewlines.array.count return TranslationEntry(key: key, value: value, comment: comment, line: numberOfNewlines - 1) } } + return translations } @@ -344,33 +347,29 @@ public class StringsFileUpdater { // Get language from path guard let languageMatch = languageRegex.matches(in: path, options: .reportCompletion, range: path.fullRange).last else { return nil } - let language = (path as NSString).substring(with: languageMatch.rangeAt(1)) + let language = (path as NSString).substring(with: languageMatch.range(at: 1)) // Get region from path if existent guard let regionMatch = regionRegex.matches(in: path, options: .reportCompletion, range: path.fullRange).last else { return (language, nil) } - let region = (path as NSString).substring(with: regionMatch.rangeAt(1)) + let region = (path as NSString).substring(with: regionMatch.range(at: 1)) return (language, region) } } - // MARK: - String Extension - extension String { func containsAny(of substrings: [String]) -> Bool { - for substring in substrings { + for substring in substrings { // swiftlint:disable:this if_as_guard if contains(substring) { return true } } + return false } /// Unescapes any special characters to make String valid String Literal. - /// - /// Source: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html (to be cont.) - /// Continued: #//apple_ref/doc/uid/TP40014097-CH7-ID295 var asStringLiteral: String { let charactersToEscape = ["\\", "\""] // important: backslash must be first entry var escapedString = self diff --git a/Sources/Code/StringsFilesSearch.swift b/Sources/Code/StringsFilesSearch.swift index 50289ab..669ffdc 100644 --- a/Sources/Code/StringsFilesSearch.swift +++ b/Sources/Code/StringsFilesSearch.swift @@ -11,12 +11,9 @@ import Foundation /// Searchs for `.strings` files given a base internationalized Storyboard. public class StringsFilesSearch { // MARK: - Stored Type Properties - public static let shared = StringsFilesSearch() - // MARK: - Instance Methods - public func findAllIBFiles(within baseDirectoryPath: String, withLocale locale: String = "Base") -> [String] { // swiftlint:disable:next force_try let ibFileRegex = try! NSRegularExpression(pattern: ".*\\/\(locale).lproj.*\\.(storyboard|xib)\\z", options: .caseInsensitive) @@ -51,7 +48,7 @@ public class StringsFilesSearch { do { let filesInDirectory = try FileManager.default.contentsOfDirectory(atPath: folderWithLanguageSubfoldersPath) let languageDirPaths = filesInDirectory.filter { $0.range(of: ".lproj") != nil && $0 != "Base.lproj" } - return languageDirPaths.map { folderWithLanguageSubfoldersPath + "/" + $0 + "/" + storyboardName + ".strings" } + return languageDirPaths.map { [folderWithLanguageSubfoldersPath, $0, "\(storyboardName).strings"].joined(separator: "/") } } catch { return [] } @@ -64,6 +61,7 @@ public class StringsFilesSearch { let ibFilePaths = allFilePaths.filter { filePath in return !regularExpression.matches(in: filePath, options: .reportCompletion, range: filePath.fullRange).isEmpty } + return ibFilePaths.map { baseDirectoryPath + "/" + $0 } } catch { return [] diff --git a/Sources/Code/SubCommander.swift b/Sources/Code/SubCommander.swift index 0d24e5f..b492540 100644 --- a/Sources/Code/SubCommander.swift +++ b/Sources/Code/SubCommander.swift @@ -10,7 +10,6 @@ import Foundation public class SubCommander { // MARK: - Sub Types - public enum ParseError: Error, CustomStringConvertible { case missingSubCommand(supportedSubCommands: [String]) case unsupportedSubCommand(supportedSubCommands: [String]) @@ -19,6 +18,7 @@ public class SubCommander { switch self { case let .missingSubCommand(supportedSubCommands): return "Missing sub command. Try one of the following: \(supportedSubCommands)" + case let .unsupportedSubCommand(supportedSubCommands): return "Sub command not supported. Try one of the following: \(supportedSubCommands)" } @@ -27,19 +27,16 @@ public class SubCommander { private struct StderrOutputStream: TextOutputStream { static let stream = StderrOutputStream() + func write(_ string: String) { fputs(string, stderr) } } - // MARK: - Stored Instance Properties - private var subCommandLines: [CommandLineParser.SubCommand: () -> CommandLineKit] = [:] - // MARK: - Instance Methods - public func addCommandLineBlock(commandLineBlock: @escaping () -> CommandLineKit, forSubCommand subCommand: CommandLineParser.SubCommand) { self.subCommandLines[subCommand] = commandLineBlock } diff --git a/Tests/Assets/Code Files Custom Function/SwiftExample1.swift b/Tests/Assets/Code Files Custom Function/SwiftExample1.swift index faf11a0..ada92d8 100644 --- a/Tests/Assets/Code Files Custom Function/SwiftExample1.swift +++ b/Tests/Assets/Code Files Custom Function/SwiftExample1.swift @@ -11,7 +11,7 @@ import Foundation class SwiftExample1 { func exampleFunction1() { BCLocalizedString("TestKey1", comment: "Comment for TestKey1") - String(format: BCLocalizedString("%@ and %.2f", comment: ""), "SomeString", 25.7528938) + String(format: BCLocalizedString("%@ and %.2f", comment: ""), "SomeString", 25.752_893_8) let s1 = BCLocalizedString("test.multiline_comment", comment: "test comment 1") let s2 = BCLocalizedString("test.multiline_comment", comment: "test comment 2") diff --git a/Tests/Assets/Code Files/SwiftExample1.swift b/Tests/Assets/Code Files/SwiftExample1.swift index b0bf557..8823e13 100644 --- a/Tests/Assets/Code Files/SwiftExample1.swift +++ b/Tests/Assets/Code Files/SwiftExample1.swift @@ -11,7 +11,7 @@ import Foundation class SwiftExample1 { func exampleFunction1() { NSLocalizedString("TestKey1", comment: "Comment for TestKey1") - String(format: NSLocalizedString("%@ and %.2f", comment: ""), "SomeString", 25.7528938) + String(format: NSLocalizedString("%@ and %.2f", comment: ""), "SomeString", 25.752_893_8) let s1 = NSLocalizedString("test.multiline_comment", comment: "test comment 1") let s2 = NSLocalizedString("test.multiline_comment", comment: "test comment 2") diff --git a/Tests/Code/CommandLineActorTests.swift b/Tests/Code/CommandLineActorTests.swift index e42b581..76c61df 100644 --- a/Tests/Code/CommandLineActorTests.swift +++ b/Tests/Code/CommandLineActorTests.swift @@ -6,43 +6,42 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import BartyCrouchKit +import XCTest // swiftlint:disable force_try class CommandLineActorTests: XCTestCase { // MARK: - Stored Properties - static let stringsFilesDirPath = "\(BASE_DIR)/Tests/Assets/Strings Files" let codeFilesDirPath = "\(BASE_DIR)/Tests/Assets/Code Files/UnsortedKeys" let unsortedKeysStringsFilePath = "\(stringsFilesDirPath)/UnsortedKeys/Base.lproj/Localizable.strings" let unsortedKeysDirPath = "\(stringsFilesDirPath)/UnsortedKeys" - // MARK: - Test Callbacks - override func setUp() { + super.setUp() + if FileManager.default.fileExists(atPath: unsortedKeysStringsFilePath + ".backup") { try! FileManager.default.removeItem(atPath: unsortedKeysStringsFilePath + ".backup") } + try! FileManager.default.copyItem(atPath: unsortedKeysStringsFilePath, toPath: unsortedKeysStringsFilePath + ".backup") } override func tearDown() { + super.tearDown() + try! FileManager.default.removeItem(atPath: unsortedKeysStringsFilePath) try! FileManager.default.copyItem(atPath: unsortedKeysStringsFilePath + ".backup", toPath: unsortedKeysStringsFilePath) try! FileManager.default.removeItem(atPath: unsortedKeysStringsFilePath + ".backup") } - // MARK: - Test Methods - func testActOnCode() { let args = ["bartycrouch", "code", "-p", codeFilesDirPath, "-l", unsortedKeysDirPath, "-a"] - CommandLineParser(arguments: args).parse { (commonOptions, subCommandOptions) in + CommandLineParser(arguments: args).parse { commonOptions, subCommandOptions in CommandLineActor().act(commonOptions: commonOptions, subCommandOptions: subCommandOptions) guard let updater = StringsFileUpdater(path: self.unsortedKeysStringsFilePath) else { @@ -59,7 +58,7 @@ class CommandLineActorTests: XCTestCase { func testActOnCodeWithSortedOption() { let args = ["bartycrouch", "code", "-p", codeFilesDirPath, "-l", unsortedKeysDirPath, "-a", "-s"] - CommandLineParser(arguments: args).parse { (commonOptions, subCommandOptions) in + CommandLineParser(arguments: args).parse { commonOptions, subCommandOptions in CommandLineActor().act(commonOptions: commonOptions, subCommandOptions: subCommandOptions) guard let updater = StringsFileUpdater(path: self.unsortedKeysStringsFilePath) else { diff --git a/Tests/Code/CommandLineParserTests.swift b/Tests/Code/CommandLineParserTests.swift index 1649880..0117681 100644 --- a/Tests/Code/CommandLineParserTests.swift +++ b/Tests/Code/CommandLineParserTests.swift @@ -6,9 +6,8 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import BartyCrouchKit +import XCTest class CommandLineParserTests: XCTestCase { func testIfCommentCommandIsAdded() { @@ -16,14 +15,17 @@ class CommandLineParserTests: XCTestCase { switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(overrideComments.value) + default: XCTAssertTrue(false) } } + CommandLineParser(arguments: ["bartycrouch", "code", "-p", ".", "-l", ".", "-c"]).parse { _, subCommandOptions in switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(overrideComments.value) + default: XCTAssertTrue(false) } @@ -31,42 +33,61 @@ class CommandLineParserTests: XCTestCase { } func testIfCommentCommandIsNotAdded() { - CommandLineParser(arguments: ["bartycrouch", "translate", "-p", ".", "-i", "no", "-s", "abc", "-l", ".", "--override-comments"]).parse { _, subCommandOptions in + CommandLineParser( + arguments: ["bartycrouch", "translate", "-p", ".", "-i", "no", "-s", "abc", "-l", ".", "--override-comments"] + ).parse { _, subCommandOptions in switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(!overrideComments.value) + default: XCTAssertTrue(true) } } - CommandLineParser(arguments: ["bartycrouch", "translate", "-p", ".", "-i", "no", "-s", "abc", "-l", ".", "-c"]).parse { _, subCommandOptions in + + CommandLineParser( + arguments: ["bartycrouch", "translate", "-p", ".", "-i", "no", "-s", "abc", "-l", ".", "-c"] + ).parse { _, subCommandOptions in switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(!overrideComments.value) + default: XCTAssertTrue(true) } } - CommandLineParser(arguments: ["bartycrouch", "interfaces", "-p", ".", "-i", "no", "--override-comments"]).parse { _, subCommandOptions in + + CommandLineParser( + arguments: ["bartycrouch", "interfaces", "-p", ".", "-i", "no", "--override-comments"] + ).parse { _, subCommandOptions in switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(!overrideComments.value) + default: XCTAssertTrue(true) } } - CommandLineParser(arguments: ["bartycrouch", "interfaces", "-p", ".", "-c"]).parse { _, subCommandOptions in + + CommandLineParser( + arguments: ["bartycrouch", "interfaces", "-p", ".", "-c"] + ).parse { _, subCommandOptions in switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(!overrideComments.value) + default: XCTAssertTrue(true) } } - CommandLineParser(arguments: ["bartycrouch", "code", "-p", ".", "-l", "."]).parse { _, subCommandOptions in + + CommandLineParser( + arguments: ["bartycrouch", "code", "-p", ".", "-l", "."] + ).parse { _, subCommandOptions in switch subCommandOptions { case let .codeOptions(_, _, _, overrideComments, _, _, _, _): XCTAssertTrue(!overrideComments.value) + default: XCTAssertTrue(true) } diff --git a/Tests/Code/ExtractLocStringsCommanderTests.swift b/Tests/Code/ExtractLocStringsCommanderTests.swift index 71e2015..dbcbdac 100644 --- a/Tests/Code/ExtractLocStringsCommanderTests.swift +++ b/Tests/Code/ExtractLocStringsCommanderTests.swift @@ -6,26 +6,25 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import BartyCrouchKit +import XCTest class ExtractLocStringsCommanderTests: XCTestCase { // MARK: - Stored Properties - let baseMultipleArgumentFunctionDirectories: [(String?, String)] = [ - (nil, "\(BASE_DIR)/Tests/Assets/Multiple Arguments Code"), - ("BCLocalizedString", "\(BASE_DIR)/Tests/Assets/Multiple Arguments Code Custom Function") + (nil, "\(BASE_DIR)/Tests/Assets/Multiple Arguments Code"), + ("BCLocalizedString", "\(BASE_DIR)/Tests/Assets/Multiple Arguments Code Custom Function") ] override func tearDown() { + super.tearDown() + for (_, directory) in baseMultipleArgumentFunctionDirectories { removeLocalizableStringsFilesRecursively(in: URL(fileURLWithPath: directory)) } } // MARK: - Test Methods - func test2Arguments() { for (functionName, directory) in baseMultipleArgumentFunctionDirectories { assert( @@ -74,17 +73,20 @@ class ExtractLocStringsCommanderTests: XCTestCase { } } - func assert(_ codeCommander: CodeCommander, takesCodeIn directory: String, customFunction: String?, producesResult expectedLocalizableContentLines: [String]) { + func assert( + _ codeCommander: CodeCommander, takesCodeIn directory: String, customFunction: String?, producesResult expectedLocalizableContentLines: [String] + ) { let exportSuccess = codeCommander.export(stringsFilesToPath: directory, fromCodeInDirectoryPath: directory, customFunction: customFunction) XCTAssertTrue(exportSuccess, "Failed for \(directory) with function \"\(customFunction ?? "NSLocalizedString")\"") do { let contentsOfStringsFile = try String(contentsOfFile: directory + "/Localizable.strings") let linesInStringsFile = contentsOfStringsFile.components(separatedBy: CharacterSet.newlines) - XCTAssertEqual(linesInStringsFile, expectedLocalizableContentLines, "Failed for \(directory) with function \"\(customFunction ?? "NSLocalizedString")\"") + XCTAssertEqual( + linesInStringsFile, expectedLocalizableContentLines, "Failed for \(directory) with function \"\(customFunction ?? "NSLocalizedString")\"" + ) } catch { XCTFail("Failed for \(directory) with function \"\(customFunction ?? "NSLocalizedString")\"") - } } diff --git a/Tests/Code/GenStringsCommanderTests.swift b/Tests/Code/GenStringsCommanderTests.swift index 620fc77..a7ecdf2 100644 --- a/Tests/Code/GenStringsCommanderTests.swift +++ b/Tests/Code/GenStringsCommanderTests.swift @@ -6,21 +6,20 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import BartyCrouchKit +import XCTest class GenStringsCommanderTests: XCTestCase { // MARK: - Stored Properties - let exampleCodeFunctionDirectoryData: [(String?, String)] = [ (nil, "\(BASE_DIR)/Tests/Assets/Code Files"), ("BCLocalizedString", "\(BASE_DIR)/Tests/Assets/Code Files Custom Function") ] // MARK: - Test Configuration Methods - override func tearDown() { + super.tearDown() + do { for (_, path) in exampleCodeFunctionDirectoryData { try FileManager.default.removeItem(atPath: path + "/Localizable.strings") @@ -31,10 +30,8 @@ class GenStringsCommanderTests: XCTestCase { } // MARK: - Test Methods - func testCodeExamples() { for (customFunction, path) in exampleCodeFunctionDirectoryData { - let exportSuccess = GenStringsCommander.shared.export(stringsFilesToPath: path, fromCodeInDirectoryPath: path, customFunction: customFunction) do { @@ -68,10 +65,11 @@ class GenStringsCommanderTests: XCTestCase { "\"TestKey2\" = \"TestKey2\";", "", "" - ], "Failed for \(path) with function \"\(customFunction ?? "NSLocalizedString")\"") + ], "Failed for \(path) with function \"\(customFunction ?? "NSLocalizedString")\"") } catch { XCTFail("Failed for \(path) with function \"\(customFunction ?? "NSLocalizedString")\"") } + XCTAssertTrue(exportSuccess, "Failed for \(path) with function \"\(customFunction ?? "NSLocalizedString")\"") } } diff --git a/Tests/Code/IBToolCommanderTests.swift b/Tests/Code/IBToolCommanderTests.swift index 99262b0..7a8f559 100644 --- a/Tests/Code/IBToolCommanderTests.swift +++ b/Tests/Code/IBToolCommanderTests.swift @@ -6,9 +6,8 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import BartyCrouchKit +import XCTest class IBToolCommanderTests: XCTestCase { func testiOSExampleStoryboard() { diff --git a/Tests/Code/StringsFileUpdaterTests.swift b/Tests/Code/StringsFileUpdaterTests.swift index 1d3ae9a..c1a3148 100644 --- a/Tests/Code/StringsFileUpdaterTests.swift +++ b/Tests/Code/StringsFileUpdaterTests.swift @@ -8,14 +8,13 @@ // swiftlint:disable file_length // swiftlint:disable function_body_length - -import XCTest +// swiftlint:disable type_body_length @testable import BartyCrouchKit +import XCTest -class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_length +class StringsFileUpdaterTests: XCTestCase { // MARK: - Stored Instance Properties - static let stringsFilesDirPath = "\(BASE_DIR)/Tests/Assets/Strings Files" let oldStringsFilePath = "\(stringsFilesDirPath)/OldExample.strings" @@ -25,16 +24,17 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ let longNewStringsFilePath = "\(stringsFilesDirPath)/LongNewExample.strings" let testStringsFilePath = "\(stringsFilesDirPath)/TestExample.strings" + func testStringsFilePath(_ iteration: Int) -> String { return "\(StringsFileUpdaterTests.stringsFilesDirPath)/TestExample\(iteration).strings" } let testExamplesRange = 0...1 - // MARK: - Test Callbacks - override func setUp() { + super.setUp() + // ensure temporary files are cleaned up before testing do { try FileManager.default.removeItem(atPath: self.testStringsFilePath) @@ -47,6 +47,8 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ } override func tearDown() { + super.tearDown() + // cleanup temporary files after testing do { try FileManager.default.removeItem(atPath: self.testStringsFilePath) @@ -58,9 +60,7 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ } catch { print("No TestExample{i}.strings to clean up") } } - // MARK: - Unit Tests - func testFindTranslationsInLines() { let stringsFileUpdater = StringsFileUpdater(path: oldStringsFilePath)! @@ -71,7 +71,8 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ ("test.key", "This is a test key", " Completely custom comment structure in one line "), ("test.key.ignored", "This is a test key to be ignored #bc-ignore!", " Completely custom comment structure in one line to be ignored "), ("abc-12-345.normalTitle", "😀", " Class = \"UIButton\"; normalTitle = \"😀\"; ObjectID = \"abc-12-345\"; "), - ("em1-3S-vgp.text", "Refrakční vzdálenost v metrech", " Class = \"UILabel\"; text = \"Refraktionsentfernung in Meter\"; ObjectID = \"em1-3S-vgp\"; ") + ("em1-3S-vgp.text", "Refrakční vzdálenost v metrech", + " Class = \"UILabel\"; text = \"Refraktionsentfernung in Meter\"; ObjectID = \"em1-3S-vgp\"; ") ] let results = stringsFileUpdater.findTranslations(inString: stringsFileUpdater.oldContentString) @@ -80,7 +81,7 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ var index = 0 - expectedTranslations.forEach { (key, value, comment) in + expectedTranslations.forEach { key, value, comment in XCTAssertGreaterThan(results.count, index) XCTAssertEqual(results[index].0, key) @@ -326,6 +327,7 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ if FileManager.default.fileExists(atPath: localizableStringsFilePath + ".tmp") { try FileManager.default.removeItem(atPath: localizableStringsFilePath + ".tmp") } + try FileManager.default.copyItem(atPath: localizableStringsFilePath, toPath: localizableStringsFilePath + ".tmp") } catch { XCTAssertTrue(false) @@ -335,7 +337,6 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ let stringsFileUpdater = StringsFileUpdater(path: localizableStringsFilePath + ".tmp")! var translations = stringsFileUpdater.findTranslations(inString: stringsFileUpdater.oldContentString) - // test before state (update if failing) XCTAssertEqual(translations[0].key, "Test key") XCTAssertEqual(translations[0].value, "Test value (\(locale))") @@ -351,15 +352,15 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ XCTAssertEqual(translations[2].value, "") XCTAssertEqual(translations[2].comment, nil) - // run tested method - let changedValuesCount = stringsFileUpdater.translateEmptyValues(usingValuesFromStringsFile: sourceStringsFilePath, clientId: id, clientSecret: secret) + let changedValuesCount = stringsFileUpdater.translateEmptyValues( + usingValuesFromStringsFile: sourceStringsFilePath, clientId: id, clientSecret: secret + ) translations = stringsFileUpdater.findTranslations(inString: stringsFileUpdater.oldContentString) XCTAssertEqual(changedValuesCount, 3) - // test after state (update if failing) XCTAssertEqual(translations.count, 4) @@ -401,6 +402,7 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ if FileManager.default.fileExists(atPath: localizableStringsFilePath + ".tmp") { try FileManager.default.removeItem(atPath: localizableStringsFilePath + ".tmp") } + try FileManager.default.copyItem(atPath: localizableStringsFilePath, toPath: localizableStringsFilePath + ".tmp") } catch { XCTAssertTrue(false) @@ -424,7 +426,9 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ XCTAssertEqual(translations[1].comment, " A string where value only available in English. ") // run tested method - let changedValuesCount = stringsFileUpdater.translateEmptyValues(usingValuesFromStringsFile: sourceStringsFilePath, clientId: id, clientSecret: secret) + let changedValuesCount = stringsFileUpdater.translateEmptyValues( + usingValuesFromStringsFile: sourceStringsFilePath, clientId: id, clientSecret: secret + ) translations = stringsFileUpdater.findTranslations(inString: stringsFileUpdater.oldContentString) @@ -462,9 +466,7 @@ class StringsFileUpdaterTests: XCTestCase { // swiftlint:disable:this type_body_ } } - // MARK: - Performance Tests - func testInitPerformance() { measure { 100.times { diff --git a/Tests/Code/StringsFilesSearchTests.swift b/Tests/Code/StringsFilesSearchTests.swift index f4ac0ec..1d8aad2 100644 --- a/Tests/Code/StringsFilesSearchTests.swift +++ b/Tests/Code/StringsFilesSearchTests.swift @@ -6,13 +6,11 @@ // Copyright © 2016 Flinesoft. All rights reserved. // -import XCTest - @testable import BartyCrouchKit +import XCTest class StringsFilesSearchTests: XCTestCase { // MARK: - Test Methods - func testFindAllIBFiles() { let basePath = "\(BASE_DIR)/Tests" @@ -46,9 +44,7 @@ class StringsFilesSearchTests: XCTestCase { XCTAssertEqual(results.sorted(), expectedStringsPaths.sorted()) } - // MARK: - Helpers - func examplePath(platform: String, locale: String, type: String) -> String { return "\(BASE_DIR)/Tests/Assets/Storyboards/\(platform)/\(locale).lproj/Example.\(type)" } From b12ca925a13200059505e913c3f612da217edf1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cihat=20Gu=CC=88ndu=CC=88z?= Date: Tue, 26 Sep 2017 14:34:43 +0200 Subject: [PATCH 5/5] Bump version num + Update requirements --- BartyCrouch.podspec | 2 +- README.md | 10 +++++----- Sources/Supporting Files/Info.plist | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/BartyCrouch.podspec b/BartyCrouch.podspec index 075a7f9..fb21ba0 100644 --- a/BartyCrouch.podspec +++ b/BartyCrouch.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BartyCrouch' - s.version = '3.8.1' + s.version = '3.9.0' s.summary = 'Localization/I18n: Incrementally update your Strings files from .swift, .h, .m(m), .storyboard or .xib files and/or use machine-translation.' s.homepage = 'https://github.com/Flinesoft/BartyCrouch' s.license = { :type => 'MIT', :file => 'LICENSE.md' } diff --git a/README.md b/README.md index 84bb75a..69841f7 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ alt="codebeat badge"> - Version: 3.8.1 + Version: 3.9.0 - Swift: 3 + Swift: 4 License: MIT @@ -41,7 +41,7 @@ BartyCrouch **incrementally updates** your Strings files from your Code *and* fr ## Requirements -- Xcode 8 and Swift 3 +- Xcode 9 and Swift 4 - Xcode Command Line Tools (see [here](http://stackoverflow.com/a/9329325/3451975) for installation instructions) ## Installation diff --git a/Sources/Supporting Files/Info.plist b/Sources/Supporting Files/Info.plist index 9467a96..e356e62 100644 --- a/Sources/Supporting Files/Info.plist +++ b/Sources/Supporting Files/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.8.1 + 3.9.0 CFBundleSignature ???? CFBundleVersion