Skip to content

Commit a3d53a7

Browse files
authored
Allow single, attached value with .upToNextOption (#610)
Fixes an issue where a single attached value triggered an error on `.upToNextOption` options. Fixes #609.
1 parent 14cba5d commit a3d53a7

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

Sources/ArgumentParser/Parsing/ArgumentSet.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,17 +327,20 @@ struct LenientParser {
327327

328328
case .upToNextOption:
329329
// Use an attached value if it exists...
330+
var foundAttachedValue = false
330331
if let value = parsed.value {
331332
// This was `--foo=bar` style:
332333
try update(origin, parsed.name, value, &result)
333334
usedOrigins.formUnion(origin)
335+
foundAttachedValue = true
334336
} else if argument.allowsJoinedValue,
335337
let (origin2, value) = inputArguments.extractJoinedElement(at: originElement) {
336338
// Found a joined argument
337339
let origins = origin.inserting(origin2)
338340
try update(origins, parsed.name, String(value), &result)
339341
usedOrigins.formUnion(origins)
340342
inputArguments.removeAll(in: usedOrigins)
343+
foundAttachedValue = true
341344
}
342345

343346
// Clear out the initial origin first, since it can include
@@ -350,7 +353,13 @@ struct LenientParser {
350353
guard let first = inputArguments.elements.first,
351354
first.isValue
352355
else {
353-
throw ParserError.missingValueForOption(origin, parsed.name)
356+
// No independent values to be found, which is an error if there was
357+
// no `--foo=bar`-style value already found.
358+
if foundAttachedValue {
359+
break
360+
} else {
361+
throw ParserError.missingValueForOption(origin, parsed.name)
362+
}
354363
}
355364

356365
// ...and then consume the arguments until hitting an option

Tests/ArgumentParserEndToEndTests/RepeatingEndToEndTests.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,24 @@ extension RepeatingEndToEndTests {
210210
XCTAssertEqual(qux.names, ["one", "two"])
211211
XCTAssertNil(qux.extra)
212212
}
213+
214+
AssertParse(Qux.self, ["--verbose", "--names=one"]) { qux in
215+
XCTAssertTrue(qux.verbose)
216+
XCTAssertEqual(qux.names, ["one"])
217+
XCTAssertNil(qux.extra)
218+
}
219+
220+
AssertParse(Qux.self, ["--verbose", "--names=one", "two"]) { qux in
221+
XCTAssertTrue(qux.verbose)
222+
XCTAssertEqual(qux.names, ["one", "two"])
223+
XCTAssertNil(qux.extra)
224+
}
225+
226+
AssertParse(Qux.self, ["--names=one", "--verbose", "two"]) { qux in
227+
XCTAssertTrue(qux.verbose)
228+
XCTAssertEqual(qux.names, ["one"])
229+
XCTAssertEqual(qux.extra, "two")
230+
}
213231
}
214232

215233
func testParsing_repeatingStringUpToNext_Fails() throws {

0 commit comments

Comments
 (0)