Skip to content

Commit cfbcb29

Browse files
committed
fix(help): Support showing default values for custom types
Fixes #62
1 parent e5b50ad commit cfbcb29

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

CHANGELOG.md

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

3+
## Master
4+
5+
### Bug Fixes
6+
7+
- Showing default values for custom `ArgumentConvertible` types are now
8+
supported in the `--help` output of commands.
9+
10+
311
## 0.8.0
412

513
### Enhancements

Sources/Commander/ArgumentDescription.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,13 @@ class BoxedArgumentDescriptor {
281281
} else if let value = value as? Option<Int> {
282282
`default` = value.`default`.description
283283
} else {
284-
// TODO, default for Option of generic type
285-
`default` = nil
284+
let mirror = Mirror(reflecting: value)
285+
286+
if let defaultDescendant = mirror.descendant("default"), let defaultConvertible = defaultDescendant as? CustomStringConvertible {
287+
`default` = defaultConvertible.description
288+
} else {
289+
`default` = nil
290+
}
286291
}
287292
}
288293
}

Tests/CommanderTests/ArgumentDescriptionSpec.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,37 @@ public func testArgumentDescription() {
2424
try expect(help.description) == "Options:\n --opt1 [default: example]\n --flag1 [default: false] - an example\n --flag2 [default: true]"
2525
try expect(help.ansiDescription) == "Options:\n \(ANSI.blue)--opt1\(ANSI.reset) [default: example]\n \(ANSI.blue)--flag1\(ANSI.reset) [default: false] - an example\n \(ANSI.blue)--flag2\(ANSI.reset) [default: true]"
2626
}
27+
28+
$0.it("shows default for custom types conforming to CustomStringConvertible") {
29+
enum Direction: String, CustomStringConvertible, ArgumentConvertible {
30+
case north
31+
case south
32+
33+
public init(parser: ArgumentParser) throws {
34+
if let value = parser.shift() {
35+
switch value {
36+
case "north":
37+
self = .north
38+
case "south":
39+
self = .south
40+
default:
41+
throw ArgumentError.invalidType(value: value, type: "direction", argument: nil)
42+
}
43+
} else {
44+
throw ArgumentError.missingValue(argument: nil)
45+
}
46+
}
47+
48+
var description: String {
49+
return rawValue
50+
}
51+
}
52+
53+
let help = Help([
54+
BoxedArgumentDescriptor(value: Option("direction", default: Direction.south)),
55+
])
56+
57+
try expect(help.description) == "Options:\n --direction [default: south]"
58+
}
2759
}
2860
}

0 commit comments

Comments
 (0)