Skip to content

Commit 77b25dd

Browse files
djbekylef
authored andcommitted
feat(options): Add support for variadic options (#38)
1 parent a79ecd2 commit 77b25dd

File tree

4 files changed

+56
-2
lines changed

4 files changed

+56
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Commander Changelog
22

3+
## unreleased
4+
5+
### Enhancements
6+
37
- Renamed VaradicArgument to VariadicArgument.
8+
- Adds support for variadic options, allowing the user to repeat options to
9+
provide additional values.
410

511
## 0.5.0
612

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ Hello Kyle
120120
##### Types of descriptors
121121

122122
- Option - An optional option with a value.
123-
- Options - A option with a value which can be used multiple times, your command is passed an array containing all option values.
123+
- Options - A option with a value which can be used multiple times, your command is passed an array containing all option values. You need to specify ahead of time how many values you expect. Example: `--myOption value1 value2 value3`
124+
- VariadicOption - Same as options, but instead of a fixed `count` of values, the user can just repeat the option with additional values. Example: `--myOption value1 --myOption value2`
124125
- Flag - A boolean, on/off flag.
125126
- Argument - A positional argument.
126127
- VariadicArgument - A variadic argument

Sources/ArgumentDescription.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,37 @@ open class Options<T : ArgumentConvertible> : ArgumentDescriptor {
155155
}
156156

157157

158+
open class VaradicOption<T : ArgumentConvertible> : ArgumentDescriptor {
159+
public typealias ValueType = [T]
160+
161+
open let name:String
162+
open let description:String?
163+
open let `default`:ValueType
164+
open var type:ArgumentType { return .option }
165+
166+
public init(_ name:String, _ default:ValueType = [], description:String? = nil) {
167+
self.name = name
168+
self.`default` = `default`
169+
self.description = description
170+
}
171+
172+
open func parse(_ parser:ArgumentParser) throws -> ValueType {
173+
var values: ValueType? = nil
174+
175+
while let shifted = try parser.shiftValueForOption(name) {
176+
let argument = try T(string: shifted)
177+
178+
if values == nil {
179+
values = ValueType()
180+
}
181+
values?.append(argument)
182+
}
183+
184+
return values ?? `default`
185+
}
186+
}
187+
188+
158189
open class Flag : ArgumentDescriptor {
159190
public typealias ValueType = Bool
160191

Tests/CommanderTests/ArgumentParserSpec.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public func testArgumentParser() {
77
var parser: ArgumentParser!
88

99
$0.before {
10-
parser = ArgumentParser(arguments: ["first", "-f", "--verbose", "middle", "end"])
10+
parser = ArgumentParser(arguments: ["first", "-f", "--verbose", "middle", "end", "--varOption", "varValue1", "--varOption", "varValue2"])
1111
}
1212

1313
$0.describe("shifting") {
@@ -87,5 +87,21 @@ public func testArgumentParser() {
8787
try expect(value?.last) == "end"
8888
}
8989
}
90+
91+
$0.describe("variadic options") {
92+
$0.it("should return arguments for option") {
93+
let option = VaradicOption<String>("varOption")
94+
let values = try option.parse(parser)
95+
try expect(values.count) == 2
96+
try expect(values.first) == "varValue1"
97+
try expect(values.last) == "varValue2"
98+
}
99+
100+
$0.it("should return empty array when option is unknown") {
101+
let option = VaradicOption<String>("unknown")
102+
let values = try option.parse(parser)
103+
try expect(values.count) == 0
104+
}
105+
}
90106
}
91107
}

0 commit comments

Comments
 (0)