|
19 | 19 | /// The `-v | -f` part is one *set* that’s optional, `<input> <output>` is |
20 | 20 | /// another. Both of these can then be combined into a third set. |
21 | 21 | struct ArgumentSet { |
22 | | - enum Content { |
23 | | - /// A leaf list of arguments. |
24 | | - case arguments([ArgumentDefinition]) |
25 | | - /// A node with additional `[ArgumentSet]` |
26 | | - case sets([ArgumentSet]) |
27 | | - } |
28 | | - var content: Content |
29 | | - var kind: Kind |
| 22 | + var content: [ArgumentDefinition] = [] |
| 23 | + var namePositions: [Name: Int] = [:] |
30 | 24 |
|
31 | | - /// Used to generate _help_ text. |
32 | | - enum Kind { |
33 | | - /// Independent |
34 | | - case additive |
35 | | - /// Mutually exclusive |
36 | | - case exclusive |
37 | | - /// Several ways of achieving the same behavior. Should only display one. |
38 | | - case alternatives |
| 25 | + init<S: Sequence>(_ arguments: S) where S.Element == ArgumentDefinition { |
| 26 | + self.content = Array(arguments) |
| 27 | + self.namePositions = Dictionary( |
| 28 | + content.enumerated().flatMap { i, arg in arg.names.map { ($0, i) } }, |
| 29 | + uniquingKeysWith: { first, _ in first }) |
39 | 30 | } |
40 | 31 |
|
41 | | - init(arguments: [ArgumentDefinition], kind: Kind) { |
42 | | - self.content = .arguments(arguments) |
43 | | - self.kind = kind |
44 | | - } |
| 32 | + init() {} |
45 | 33 |
|
46 | | - init(sets: [ArgumentSet], kind: Kind) { |
47 | | - self.content = .sets(sets) |
48 | | - self.kind = kind |
| 34 | + init(_ arg: ArgumentDefinition) { |
| 35 | + self.init([arg]) |
| 36 | + } |
| 37 | + |
| 38 | + init(sets: [ArgumentSet]) { |
| 39 | + self.init(sets.joined()) |
49 | 40 | } |
50 | 41 | } |
51 | 42 |
|
52 | 43 | extension ArgumentSet: CustomDebugStringConvertible { |
53 | 44 | var debugDescription: String { |
54 | | - switch content { |
55 | | - case .arguments(let args): |
56 | | - return args |
57 | | - .map { $0.debugDescription } |
58 | | - .joined(separator: " / ") |
59 | | - case .sets(let sets): |
60 | | - return sets |
61 | | - .map { "{\($0.debugDescription)}" } |
62 | | - .joined(separator: " / ") |
63 | | - } |
| 45 | + content |
| 46 | + .map { $0.debugDescription } |
| 47 | + .joined(separator: " / ") |
64 | 48 | } |
65 | 49 | } |
66 | 50 |
|
67 | | -extension ArgumentSet { |
68 | | - init() { |
69 | | - self.init(arguments: [], kind: .additive) |
70 | | - } |
71 | | - |
72 | | - init(_ arg: ArgumentDefinition) { |
73 | | - self.init(arguments: [arg], kind: .additive) |
74 | | - } |
75 | | - |
76 | | - init(additive args: [ArgumentDefinition]) { |
77 | | - self.init(arguments: args, kind: .additive) |
78 | | - } |
79 | | - |
80 | | - init(exclusive args: [ArgumentDefinition]) { |
81 | | - self.init(arguments: args, kind: args.count == 1 ? .additive : .exclusive) |
82 | | - } |
83 | | - |
84 | | - init(alternatives args: [ArgumentDefinition]) { |
85 | | - self.init(arguments: args, kind: args.count == 1 ? .additive : .alternatives) |
86 | | - } |
87 | | - |
88 | | - init(additive sets: [ArgumentSet]) { |
89 | | - self.init(sets: sets, kind: .additive) |
| 51 | +extension ArgumentSet: Sequence { |
| 52 | + func makeIterator() -> Array<ArgumentDefinition>.Iterator { |
| 53 | + return content.makeIterator() |
90 | 54 | } |
91 | 55 | } |
92 | 56 |
|
@@ -150,7 +114,7 @@ extension ArgumentSet { |
150 | 114 | let disableArg = ArgumentDefinition(kind: .named(disableNames), help: ArgumentDefinition.Help(options: [.isOptional], key: key), completion: .default, update: .nullary({ (origin, name, values) in |
151 | 115 | hasUpdated = try ArgumentSet.updateFlag(key: key, value: false, origin: origin, values: &values, hasUpdated: hasUpdated, exclusivity: exclusivity) |
152 | 116 | }), initial: { _, _ in }) |
153 | | - return ArgumentSet(exclusive: [enableArg, disableArg]) |
| 117 | + return ArgumentSet([enableArg, disableArg]) |
154 | 118 | } |
155 | 119 |
|
156 | 120 | /// Creates an argument set for an incrementing integer flag. |
@@ -390,7 +354,7 @@ extension ArgumentSet { |
390 | 354 | func first( |
391 | 355 | matching parsed: ParsedArgument |
392 | 356 | ) -> ArgumentDefinition? { |
393 | | - return first(where: { $0.names.contains(parsed.name) }) |
| 357 | + namePositions[parsed.name].map { content[$0] } |
394 | 358 | } |
395 | 359 |
|
396 | 360 | func firstPositional( |
|
0 commit comments