Skip to content

Commit 333ea29

Browse files
committed
Argument convertible
1 parent ccfe0af commit 333ea29

File tree

7 files changed

+161
-11
lines changed

7 files changed

+161
-11
lines changed

Commander.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
279256B01BB3237D00E66B9E /* CommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279256AF1BB3237D00E66B9E /* CommandTests.swift */; settings = {ASSET_TAGS = (); }; };
1717
279256B21BB325F400E66B9E /* GroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279256B11BB325F400E66B9E /* GroupTests.swift */; settings = {ASSET_TAGS = (); }; };
1818
279256B41BB3260D00E66B9E /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279256B31BB3260D00E66B9E /* Group.swift */; settings = {ASSET_TAGS = (); }; };
19+
279256B61BB32A8E00E66B9E /* ArgumentConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279256B51BB32A8E00E66B9E /* ArgumentConvertible.swift */; settings = {ASSET_TAGS = (); }; };
20+
279256B81BB32B3F00E66B9E /* ArgumentConvertibleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279256B71BB32B3F00E66B9E /* ArgumentConvertibleTests.swift */; settings = {ASSET_TAGS = (); }; };
1921
27B1A0FF1BACD69500B1260F /* ArgumentParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27B1A0FE1BACD69500B1260F /* ArgumentParserTests.swift */; settings = {ASSET_TAGS = (); }; };
2022
/* End PBXBuildFile section */
2123

@@ -42,6 +44,8 @@
4244
279256AF1BB3237D00E66B9E /* CommandTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandTests.swift; sourceTree = "<group>"; };
4345
279256B11BB325F400E66B9E /* GroupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupTests.swift; sourceTree = "<group>"; };
4446
279256B31BB3260D00E66B9E /* Group.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Group.swift; sourceTree = "<group>"; };
47+
279256B51BB32A8E00E66B9E /* ArgumentConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArgumentConvertible.swift; sourceTree = "<group>"; };
48+
279256B71BB32B3F00E66B9E /* ArgumentConvertibleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArgumentConvertibleTests.swift; sourceTree = "<group>"; };
4549
27B1A0FE1BACD69500B1260F /* ArgumentParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArgumentParserTests.swift; sourceTree = "<group>"; };
4650
/* End PBXFileReference section */
4751

@@ -87,6 +91,7 @@
8791
children = (
8892
2768A2231BACC38C00F994EE /* Commander.h */,
8993
2768A23A1BACC3B600F994EE /* ArgumentParser.swift */,
94+
279256B51BB32A8E00E66B9E /* ArgumentConvertible.swift */,
9095
279256A91BB3226E00E66B9E /* CommandType.swift */,
9196
279256AB1BB322FA00E66B9E /* Command.swift */,
9297
279256B31BB3260D00E66B9E /* Group.swift */,
@@ -99,6 +104,7 @@
99104
isa = PBXGroup;
100105
children = (
101106
27B1A0FE1BACD69500B1260F /* ArgumentParserTests.swift */,
107+
279256B71BB32B3F00E66B9E /* ArgumentConvertibleTests.swift */,
102108
279256AD1BB3237300E66B9E /* CommandTypeTests.swift */,
103109
279256AF1BB3237D00E66B9E /* CommandTests.swift */,
104110
279256B11BB325F400E66B9E /* GroupTests.swift */,
@@ -218,6 +224,7 @@
218224
2768A23B1BACC3B600F994EE /* ArgumentParser.swift in Sources */,
219225
279256AA1BB3226E00E66B9E /* CommandType.swift in Sources */,
220226
279256AC1BB322FA00E66B9E /* Command.swift in Sources */,
227+
279256B61BB32A8E00E66B9E /* ArgumentConvertible.swift in Sources */,
221228
279256B41BB3260D00E66B9E /* Group.swift in Sources */,
222229
);
223230
runOnlyForDeploymentPostprocessing = 0;
@@ -226,6 +233,7 @@
226233
isa = PBXSourcesBuildPhase;
227234
buildActionMask = 2147483647;
228235
files = (
236+
279256B81BB32B3F00E66B9E /* ArgumentConvertibleTests.swift in Sources */,
229237
279256B01BB3237D00E66B9E /* CommandTests.swift in Sources */,
230238
27B1A0FF1BACD69500B1260F /* ArgumentParserTests.swift in Sources */,
231239
279256AE1BB3237300E66B9E /* CommandTypeTests.swift in Sources */,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
public protocol ArgumentConvertible {
2+
/// Initialise the type with an ArgumentParser
3+
init?(parser: ArgumentParser)
4+
}
5+
6+
extension String : ArgumentConvertible {
7+
public init?(parser: ArgumentParser) {
8+
if let value = parser.shift() {
9+
self.init(value)
10+
} else {
11+
return nil
12+
}
13+
}
14+
}
15+
16+
extension Int : ArgumentConvertible {
17+
public init?(parser: ArgumentParser) {
18+
if let value = parser.shift() {
19+
self.init(value)
20+
} else {
21+
return nil
22+
}
23+
}
24+
}
25+
26+
27+
extension Float : ArgumentConvertible {
28+
public init?(parser: ArgumentParser) {
29+
if let value = parser.shift() {
30+
self.init(value)
31+
} else {
32+
return nil
33+
}
34+
}
35+
}
36+
37+
38+
extension Double : ArgumentConvertible {
39+
public init?(parser: ArgumentParser) {
40+
if let value = parser.shift() {
41+
self.init(value)
42+
} else {
43+
return nil
44+
}
45+
}
46+
}

Commander/ArgumentParser.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ private enum Arg {
1010
}
1111

1212

13-
public final class ArgumentParser {
13+
public final class ArgumentParser : ArgumentConvertible {
1414
private var arguments:[Arg]
1515

1616
/// Initialises the ArgumentParser with an array of arguments
@@ -31,6 +31,10 @@ public final class ArgumentParser {
3131
}
3232
}
3333

34+
public init?(parser: ArgumentParser) {
35+
arguments = parser.arguments
36+
}
37+
3438
/// Returns the first positional argument in the remaining arguments.
3539
/// This will remove the argument from the remaining arguments.
3640
public func shift() -> String? {

Commander/Command.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ struct AnonymousCommand : CommandType {
1111
}
1212
}
1313

14-
1514
/// Create a command using a closure
1615
public func command(closure:() -> ()) -> CommandType {
1716
return AnonymousCommand { parser in
@@ -20,6 +19,10 @@ public func command(closure:() -> ()) -> CommandType {
2019
}
2120

2221
/// Create a command which takes the argument parser using a closure
23-
public func command(closure:ArgumentParser -> ()) -> CommandType {
24-
return AnonymousCommand(closure)
22+
public func command<A : ArgumentConvertible>(closure:A -> ()) -> CommandType {
23+
return AnonymousCommand { parser in
24+
if let argument = A(parser: parser) {
25+
closure(argument)
26+
}
27+
}
2528
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import XCTest
2+
import Commander
3+
4+
5+
class StringArgumentConvertibleTests : XCTestCase {
6+
func testValue() {
7+
let parser = ArgumentParser(arguments: ["argument"])
8+
let value = String(parser: parser)
9+
10+
XCTAssertEqual(value, "argument")
11+
}
12+
13+
func testNoValue() {
14+
let parser = ArgumentParser(arguments: [])
15+
let value = String(parser: parser)
16+
17+
XCTAssertNil(value)
18+
}
19+
}
20+
21+
22+
class IntArgumentConvertibleTests : XCTestCase {
23+
func testValue() {
24+
let parser = ArgumentParser(arguments: ["5"])
25+
let value = Int(parser: parser)
26+
27+
XCTAssertEqual(value, 5)
28+
}
29+
30+
func testInvalidValue() {
31+
let parser = ArgumentParser(arguments: ["five"])
32+
let value = Int(parser: parser)
33+
34+
XCTAssertNil(value)
35+
}
36+
37+
func testNoValue() {
38+
let parser = ArgumentParser(arguments: [])
39+
let value = Int(parser: parser)
40+
41+
XCTAssertNil(value)
42+
}
43+
}
44+
45+
class FloatArgumentConvertibleTests : XCTestCase {
46+
func testValue() {
47+
let parser = ArgumentParser(arguments: ["5"])
48+
let value = Float(parser: parser)
49+
50+
XCTAssertEqual(value, 5)
51+
}
52+
53+
func testInvalidValue() {
54+
let parser = ArgumentParser(arguments: ["five"])
55+
let value = Float(parser: parser)
56+
57+
XCTAssertNil(value)
58+
}
59+
60+
func testNoValue() {
61+
let parser = ArgumentParser(arguments: [])
62+
let value = Float(parser: parser)
63+
64+
XCTAssertNil(value)
65+
}
66+
}
67+
68+
class DoubleArgumentConvertibleTests : XCTestCase {
69+
func testValue() {
70+
let parser = ArgumentParser(arguments: ["5"])
71+
let value = Double(parser: parser)
72+
73+
XCTAssertEqual(value, 5)
74+
}
75+
76+
func testInvalidValue() {
77+
let parser = ArgumentParser(arguments: ["five"])
78+
let value = Double(parser: parser)
79+
80+
XCTAssertNil(value)
81+
}
82+
83+
func testNoValue() {
84+
let parser = ArgumentParser(arguments: [])
85+
let value = Double(parser: parser)
86+
87+
XCTAssertNil(value)
88+
}
89+
}

CommanderTests/CommandTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ class CommandTests : XCTestCase {
1414
XCTAssertTrue(didRun)
1515
}
1616

17-
func testCommandWithArgumentParser() {
18-
let parser = ArgumentParser(arguments: [])
19-
var ranParser:ArgumentParser? = nil
17+
func testCommandWithOnePositionalArgument() {
18+
let parser = ArgumentParser(arguments: ["Kyle", "Fuller"])
19+
var ranName:String? = nil
2020

21-
command { parser in
22-
ranParser = parser
21+
command { (name:String) in
22+
ranName = name
2323
}.run(parser)
2424

25-
XCTAssertTrue(ranParser === parser)
25+
XCTAssertEqual(ranName, "Kyle")
2626
}
2727
}

CommanderTests/CommandTypeTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class CommandTypeTests : XCTestCase {
66
func testRunWithArgumentsArray() {
77
var firstArgument:String? = nil
88

9-
command { parser in
9+
command { (parser:ArgumentParser) in
1010
firstArgument = parser.shift()
1111
}.run(["test"])
1212

0 commit comments

Comments
 (0)