├── .gitignore
├── docs
└── demo.gif
├── SwiftInitializerGenerator.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── project.pbxproj
├── SourceEditorExtension
├── SourceEditorExtension.entitlements
├── SourceEditorExtension.swift
├── Info.plist
├── SourceEditorCommand.swift
├── SIG.swift
└── NSScanner+Swift.swift
├── SwiftInitializerGenerator
├── AppDelegate.swift
├── Info.plist
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
└── Base.lproj
│ └── MainMenu.xib
├── SwiftInitializerGeneratorTests
├── Info.plist
└── SwiftInitializerGeneratorTests.swift
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | xcuserdata/
3 |
--------------------------------------------------------------------------------
/docs/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Bouke/SwiftInitializerGenerator/HEAD/docs/demo.gif
--------------------------------------------------------------------------------
/SwiftInitializerGenerator.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SourceEditorExtension/SourceEditorExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SwiftInitializerGenerator.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SwiftInitializerGenerator/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftInitializerGenerator
4 | //
5 | // Created by Bouke Haarsma on 11-09-16.
6 | // Copyright © 2016 Bouke Haarsma. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | @IBOutlet weak var window: NSWindow!
15 |
16 |
17 | func applicationDidFinishLaunching(_ aNotification: Notification) {
18 | // Insert code here to initialize your application
19 | }
20 |
21 | func applicationWillTerminate(_ aNotification: Notification) {
22 | // Insert code here to tear down your application
23 | }
24 |
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/SwiftInitializerGeneratorTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SourceEditorExtension/SourceEditorExtension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceEditorExtension.swift
3 | // SourceEditorExtension
4 | //
5 | // Created by Bouke Haarsma on 11-09-16.
6 | // Copyright © 2016 Bouke Haarsma. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XcodeKit
11 |
12 | class SourceEditorExtension: NSObject, XCSourceEditorExtension {
13 |
14 | /*
15 | func extensionDidFinishLaunching() {
16 | // If your extension needs to do any work at launch, implement this optional method.
17 | }
18 | */
19 |
20 | /*
21 | var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
22 | // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter.
23 | return []
24 | }
25 | */
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2016 Bouke Haarsma
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7 | of the Software, and to permit persons to whom the Software is furnished to do
8 | so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/SwiftInitializerGenerator/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | Copyright © 2016 Bouke Haarsma. All rights reserved.
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/SwiftInitializerGenerator/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "size" : "16x16",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "size" : "16x16",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "size" : "32x32",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "size" : "32x32",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "size" : "128x128",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "size" : "128x128",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "size" : "256x256",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "size" : "256x256",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "size" : "512x512",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "size" : "512x512",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Swift Initializer Generator
2 | ===========================
3 |
4 | This Xcode Source Code Extension will generate a Swift initializer based on the lines you've selected. Handy if you made a struct public and now you have to provide the initializer implementation yourself.
5 |
6 | Usage
7 | -----
8 |
9 | Select the lines with the attributes that should be included in the initializer. See below; ``>`` is the start of the selection and ``<`` is the end of the selection.
10 | ```swift
11 | struct MyStruct {
12 | > public var a: String
13 | public var b: Int<
14 | }
15 | ```
16 | Run the extension's "Generate Swift Initializer". Voila! The code above is modified to:
17 | ```swift
18 | struct MyStruct {
19 | public var a: String
20 | public var b: Int
21 | public init(a: String, b: Int) {
22 | self.a = a
23 | self.b = b
24 | }
25 | }
26 | ```
27 | 
28 |
29 | Installation
30 | ------------
31 |
32 | 1. On OS X 10.11 El Capitan, run the following command and restart your Mac:
33 |
34 | sudo /usr/libexec/xpccachectl
35 |
36 | 1. Open ``SwiftInitializerGenerator.xcodeproj``
37 | 1. Enable target signing for both the Application and the Source Code Extension using your own developer ID
38 | 1. Product > Archive
39 | 1. Right click archive > Show in Finder
40 | 1. Right click archive > Show Package Contents
41 | 1. Drag ``Swift Initializer Generator.app`` to your Applications folder
42 | 1. Run ``Swift Initializer Generator.app`` and exit again.
43 | 1. Go to System Preferences -> Extensions -> Xcode Source Editor and enable the extension
44 | 1. The menu-item should now be available from Xcode's Editor menu.
45 |
46 | Known limitations
47 | -----------------
48 |
49 | It will only parse attributes defined like ``(open|public|fileprivate|private|internal) [weak] (var|let) NAME: TYPE``.
50 |
--------------------------------------------------------------------------------
/SourceEditorExtension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | SourceEditorExtension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSExtension
26 |
27 | NSExtensionAttributes
28 |
29 | XCSourceEditorCommandDefinitions
30 |
31 |
32 | XCSourceEditorCommandClassName
33 | $(PRODUCT_MODULE_NAME).SourceEditorCommand
34 | XCSourceEditorCommandIdentifier
35 | $(PRODUCT_BUNDLE_IDENTIFIER).SourceEditorCommand
36 | XCSourceEditorCommandName
37 | Generate Swift Initializer
38 |
39 |
40 | XCSourceEditorExtensionPrincipalClass
41 | $(PRODUCT_MODULE_NAME).SourceEditorExtension
42 |
43 | NSExtensionPointIdentifier
44 | com.apple.dt.Xcode.extension.source-editor
45 |
46 | NSHumanReadableCopyright
47 | Copyright © 2016 Bouke Haarsma. All rights reserved.
48 |
49 |
50 |
--------------------------------------------------------------------------------
/SourceEditorExtension/SourceEditorCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SourceEditorCommand.swift
3 | // SourceEditorExtension
4 | //
5 | // Created by Bouke Haarsma on 11-09-16.
6 | // Copyright © 2016 Bouke Haarsma. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XcodeKit
11 |
12 | class SourceEditorCommand: NSObject, XCSourceEditorCommand {
13 |
14 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Swift.Error?) -> Void) {
15 | do {
16 | try generateInitializer(invocation: invocation)
17 | completionHandler(nil)
18 | } catch {
19 | completionHandler(error)
20 | }
21 | }
22 |
23 | private func generateInitializer(invocation: XCSourceEditorCommandInvocation) throws {
24 | guard ["public.swift-source", "com.apple.dt.playground"].contains(invocation.buffer.contentUTI) else {
25 | throw SIGError.notSwiftLanguage
26 | }
27 | guard let selection = invocation.buffer.selections.firstObject as? XCSourceTextRange else {
28 | throw SIGError.noSelection
29 | }
30 |
31 | print(selection.start.line, selection.start.column)
32 | print(selection.end.line, selection.end.column)
33 |
34 | let selectedText: [String]
35 | if selection.start.line == selection.end.line {
36 | selectedText = [String(
37 | (invocation.buffer.lines[selection.start.line] as! String).utf8
38 | .prefix(selection.end.column)
39 | .dropFirst(selection.start.column)
40 | )!]
41 | } else {
42 | selectedText = [String((invocation.buffer.lines[selection.start.line] as! String).utf8.dropFirst(selection.start.column))!]
43 | + ((selection.start.line+1).. String {
61 | return buffer.usesTabsForIndentation
62 | ? "\t"
63 | : String(repeating: " ", count: buffer.indentationWidth)
64 | }
65 |
66 | private func leadingIndentation(from selection: XCSourceTextRange, in buffer: XCSourceTextBuffer) -> String {
67 | let firstLineOfSelection = buffer.lines[selection.start.line] as! String
68 |
69 | if let nonWhitespace = firstLineOfSelection.rangeOfCharacter(from: CharacterSet.whitespaces.inverted) {
70 | return String(firstLineOfSelection.prefix(upTo: nonWhitespace.lowerBound))
71 | } else {
72 | return ""
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/SourceEditorExtension/SIG.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SIG.swift
3 | // SwiftInitializerGenerator
4 | //
5 | // Created by Bouke Haarsma on 21-12-16.
6 | // Copyright © 2016 Bouke Haarsma. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum SIGError: Swift.Error {
12 | case notSwiftLanguage
13 | case noSelection
14 | case invalidSelection
15 | case parseError
16 | }
17 |
18 | let accessModifiers = ["open", "public", "internal", "private", "fileprivate"]
19 |
20 | func generate(selection: [String], indentation: String, leadingIndent: String) throws -> [String] {
21 | var variables = [(String, String)]()
22 |
23 | for line in selection {
24 | let scanner = Scanner(string: line)
25 |
26 | var weak = scanner.scanString("weak", into: nil)
27 | for modifier in accessModifiers {
28 | if scanner.scanString(modifier, into: nil) {
29 | break
30 | }
31 | }
32 | for modifier in accessModifiers {
33 | if scanner.scanString(modifier, into: nil) {
34 | guard let _ = scanner.scanUpTo(")"), let _ = scanner.scanString(")") else {
35 | throw SIGError.parseError
36 | }
37 | }
38 | }
39 | weak = weak || scanner.scanString("weak", into: nil)
40 |
41 | guard scanner.scanString("let", into: nil) || scanner.scanString("var", into: nil) || scanner.scanString("dynamic var", into: nil) else {
42 | continue
43 | }
44 | guard let variableName = scanner.scanUpTo(":"),
45 | scanner.scanString(":", into: nil),
46 | let variableType = scanner.scanUpTo("\n") else {
47 | throw SIGError.parseError
48 | }
49 | variables.append((variableName, variableType))
50 | }
51 |
52 | let arguments = variables.map { "\($0.0): \(addEscapingAttributeIfNeeded(to: $0.1))" }.joined(separator: ", ")
53 |
54 | let expressions = variables.map { "\(indentation)self.\($0.0) = \($0.0)" }
55 |
56 | let lines = (["public init(\(arguments)) {"] + expressions + ["}"]).map { "\(leadingIndent)\($0)" }
57 |
58 | return lines
59 | }
60 |
61 | private func addEscapingAttributeIfNeeded(to typeString: String) -> String {
62 | let predicate = NSPredicate(format: "SELF MATCHES %@", "\\(.*\\)->.*")
63 | if predicate.evaluate(with: typeString.replacingOccurrences(of: " ", with: "")),
64 | !isOptional(typeString: typeString) {
65 | return "@escaping " + typeString
66 | } else {
67 | return typeString
68 | }
69 | }
70 |
71 | private func isOptional(typeString: String) -> Bool {
72 | guard typeString.hasSuffix("!") || typeString.hasSuffix("?") else {
73 | return false
74 | }
75 | var balance = 0
76 | var indexOfClosingBraceMatchingFirstOpenBrace: Int?
77 |
78 | for (index, character) in typeString.enumerated() {
79 | if character == "(" {
80 | balance += 1
81 | } else if character == ")" {
82 | balance -= 1
83 | }
84 | if balance == 0 {
85 | indexOfClosingBraceMatchingFirstOpenBrace = index
86 | break
87 | }
88 | }
89 |
90 | return indexOfClosingBraceMatchingFirstOpenBrace == typeString.count - 2
91 | }
92 |
--------------------------------------------------------------------------------
/SwiftInitializerGeneratorTests/SwiftInitializerGeneratorTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftInitializerGeneratorTests.swift
3 | // SwiftInitializerGeneratorTests
4 | //
5 | // Created by Bouke Haarsma on 21-12-16.
6 | // Copyright © 2016 Bouke Haarsma. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class SwiftInitializerGeneratorTests: XCTestCase {
12 | func assert(input: [String], output: [String], file: StaticString = #file, line: UInt = #line) {
13 | do {
14 | let lines = try generate(selection: input, indentation: " ", leadingIndent: "")
15 | if(lines != output) {
16 | XCTFail("Output is not correct; expected:\n\(output.joined(separator: "\n"))\n\ngot:\n\(lines.joined(separator: "\n"))", file: file, line: line)
17 | }
18 | } catch {
19 | XCTFail("Could not generate initializer: \(error)", file: file, line: line)
20 | }
21 | }
22 |
23 | func testNoAccessModifiers() {
24 | assert(
25 | input: [
26 | "let a: Int",
27 | "let b: Int"
28 | ],
29 | output: [
30 | "public init(a: Int, b: Int) {",
31 | " self.a = a",
32 | " self.b = b",
33 | "}"
34 | ])
35 | }
36 |
37 | func testNoProperties() {
38 | assert(
39 | input: [
40 | "",
41 | ""
42 | ],
43 | output: [
44 | "public init() {",
45 | "}"
46 | ])
47 | }
48 |
49 | func testEmptyLineInBetween() {
50 | assert(
51 | input: [
52 | "let a: Int",
53 | "",
54 | "let b: Int"
55 | ],
56 | output: [
57 | "public init(a: Int, b: Int) {",
58 | " self.a = a",
59 | " self.b = b",
60 | "}"
61 | ])
62 | }
63 |
64 | func testSingleAccessModifier() {
65 | assert(
66 | input: [
67 | "internal let a: Int",
68 | "private let b: Int"
69 | ],
70 | output: [
71 | "public init(a: Int, b: Int) {",
72 | " self.a = a",
73 | " self.b = b",
74 | "}"
75 | ])
76 | }
77 |
78 | func testDoubleAccessModifier() {
79 | assert(
80 | input: [
81 | "public internal(set) let a: Int",
82 | "public private(set) let b: Int"
83 | ],
84 | output: [
85 | "public init(a: Int, b: Int) {",
86 | " self.a = a",
87 | " self.b = b",
88 | "}"
89 | ])
90 | }
91 |
92 |
93 | func testCommentLine() {
94 | assert(
95 | input: [
96 | "/// a very important property",
97 | "let a: Int",
98 | "// this one, not so much",
99 | "let b: Int",
100 | "/*",
101 | " * pay attention to this one",
102 | " */",
103 | "let c: IBOutlet!"
104 | ],
105 | output: [
106 | "public init(a: Int, b: Int, c: IBOutlet!) {",
107 | " self.a = a",
108 | " self.b = b",
109 | " self.c = c",
110 | "}"
111 | ])
112 | }
113 |
114 | func testDynamicVar() {
115 | assert(
116 | input: ["dynamic var hello: String",
117 | "dynamic var a: Int?",
118 | "var b: Float"],
119 | output: [
120 | "public init(hello: String, a: Int?, b: Float) {",
121 | " self.hello = hello",
122 | " self.a = a",
123 | " self.b = b",
124 | "}"
125 | ])
126 | }
127 |
128 | func testEscapingClosure() {
129 | assert(
130 | input: [
131 | "let a: (String) -> Int?",
132 | "let b: () -> () -> Void",
133 | "let c: ((String, Int))->()",
134 | ],
135 | output: [
136 | "public init(a: @escaping (String) -> Int?, b: @escaping () -> () -> Void, c: @escaping ((String, Int))->()) {",
137 | " self.a = a",
138 | " self.b = b",
139 | " self.c = c",
140 | "}"
141 | ])
142 | }
143 |
144 | func testNoEscapingAttribute() {
145 | assert(
146 | input: [
147 | "let a: (() -> Void)?",
148 | "let b: [() -> Void]",
149 | "let c: (()->())!"
150 | ],
151 | output: [
152 | "public init(a: (() -> Void)?, b: [() -> Void], c: (()->())!) {",
153 | " self.a = a",
154 | " self.b = b",
155 | " self.c = c",
156 | "}"
157 | ])
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/SourceEditorExtension/NSScanner+Swift.swift:
--------------------------------------------------------------------------------
1 | // NSScanner+Swift.swift
2 | // A set of Swift-idiomatic methods for NSScanner
3 | //
4 | // (c) 2015 Nate Cook, licensed under the MIT license
5 |
6 | import Foundation
7 |
8 | extension Scanner {
9 |
10 | // MARK: Strings
11 |
12 | /// Returns a string, scanned as long as characters from a given character set are encountered, or `nil` if none are found.
13 | func scanCharacters(from set: CharacterSet) -> String? {
14 | var value: NSString? = ""
15 | if scanCharacters(from: set, into: &value),
16 | let value = value {
17 | return String(value)
18 | }
19 | return nil
20 | }
21 |
22 | /// Returns a string, scanned until a character from a given character set are encountered, or the remainder of the scanner's string. Returns `nil` if the scanner is already `atEnd`.
23 | func scanUpToCharacters(from set: CharacterSet) -> String? {
24 | var value: NSString? = ""
25 | if scanUpToCharacters(from: set, into: &value),
26 | let value = value {
27 | return String(value)
28 | }
29 | return nil
30 | }
31 |
32 | /// Returns the given string if scanned, or `nil` if not found.
33 | func scanString(_ str: String) -> String? {
34 | var value: NSString? = ""
35 | if scanString(str, into: &value),
36 | let value = value {
37 | return String(value)
38 | }
39 | return nil
40 | }
41 |
42 | /// Returns a string, scanned until the given string is found, or the remainder of the scanner's string. Returns `nil` if the scanner is already `atEnd`.
43 | func scanUpTo(_ str: String) -> String? {
44 | var value: NSString? = ""
45 | if scanUpTo(str, into: &value),
46 | let value = value {
47 | return String(value)
48 | }
49 | return nil
50 | }
51 |
52 | // MARK: Numbers
53 |
54 | /// Returns a Double if scanned, or `nil` if not found.
55 | func scanDouble() -> Double? {
56 | var value = 0.0
57 | if scanDouble(&value) {
58 | return value
59 | }
60 | return nil
61 | }
62 |
63 | /// Returns a Float if scanned, or `nil` if not found.
64 | func scanFloat() -> Float? {
65 | var value: Float = 0.0
66 | if scanFloat(&value) {
67 | return value
68 | }
69 | return nil
70 | }
71 |
72 | /// Returns an Int if scanned, or `nil` if not found.
73 | func scanInt() -> Int? {
74 | var value = 0
75 | if scanInt(&value) {
76 | return value
77 | }
78 | return nil
79 | }
80 |
81 | /// Returns an Int32 if scanned, or `nil` if not found.
82 | func scanInt32() -> Int32? {
83 | var value: Int32 = 0
84 | if scanInt32(&value) {
85 | return value
86 | }
87 | return nil
88 | }
89 |
90 | /// Returns an Int64 if scanned, or `nil` if not found.
91 | func scanInt64() -> Int64? {
92 | var value: Int64 = 0
93 | if scanInt64(&value) {
94 | return value
95 | }
96 | return nil
97 | }
98 |
99 | /// Returns a UInt64 if scanned, or `nil` if not found.
100 | func scanUnsignedLongLong() -> UInt64? {
101 | var value: UInt64 = 0
102 | if scanUnsignedLongLong(&value) {
103 | return value
104 | }
105 | return nil
106 | }
107 |
108 | /// Returns an Decimal if scanned, or `nil` if not found.
109 | func scanDecimal() -> Decimal? {
110 | var value = Decimal()
111 | if scanDecimal(&value) {
112 | return value
113 | }
114 | return nil
115 | }
116 |
117 | // MARK: Hex Numbers
118 |
119 | /// Returns a Double if scanned in hexadecimal, or `nil` if not found.
120 | func scanHexDouble() -> Double? {
121 | var value = 0.0
122 | if scanHexDouble(&value) {
123 | return value
124 | }
125 | return nil
126 | }
127 |
128 | /// Returns a Float if scanned in hexadecimal, or `nil` if not found.
129 | func scanHexFloat() -> Float? {
130 | var value: Float = 0.0
131 | if scanHexFloat(&value) {
132 | return value
133 | }
134 | return nil
135 | }
136 |
137 | /// Returns a UInt32 if scanned in hexadecimal, or `nil` if not found.
138 | func scanHexInt32() -> UInt32? {
139 | var value: UInt32 = 0
140 | if scanHexInt32(&value) {
141 | return value
142 | }
143 | return nil
144 | }
145 |
146 | /// Returns a UInt64 if scanned in hexadecimal, or `nil` if not found.
147 | func scanHexInt64() -> UInt64? {
148 | var value: UInt64 = 0
149 | if scanHexInt64(&value) {
150 | return value
151 | }
152 | return nil
153 | }
154 |
155 | typealias Position = (line: Range, row: Int, pos: Int)
156 | var position: Position {
157 | let index = string.index(string.startIndex, offsetBy: scanLocation)
158 | var head = string.startIndex..
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
--------------------------------------------------------------------------------