diff --git a/Sources/ArgumentParser/Parsing/ArgumentSet.swift b/Sources/ArgumentParser/Parsing/ArgumentSet.swift index c8286198..054f4527 100644 --- a/Sources/ArgumentParser/Parsing/ArgumentSet.swift +++ b/Sources/ArgumentParser/Parsing/ArgumentSet.swift @@ -327,10 +327,12 @@ struct LenientParser { case .upToNextOption: // Use an attached value if it exists... + var foundAttachedValue = false if let value = parsed.value { // This was `--foo=bar` style: try update(origin, parsed.name, value, &result) usedOrigins.formUnion(origin) + foundAttachedValue = true } else if argument.allowsJoinedValue, let (origin2, value) = inputArguments.extractJoinedElement(at: originElement) { // Found a joined argument @@ -338,6 +340,7 @@ struct LenientParser { try update(origins, parsed.name, String(value), &result) usedOrigins.formUnion(origins) inputArguments.removeAll(in: usedOrigins) + foundAttachedValue = true } // Clear out the initial origin first, since it can include @@ -350,7 +353,13 @@ struct LenientParser { guard let first = inputArguments.elements.first, first.isValue else { - throw ParserError.missingValueForOption(origin, parsed.name) + // No independent values to be found, which is an error if there was + // no `--foo=bar`-style value already found. + if foundAttachedValue { + break + } else { + throw ParserError.missingValueForOption(origin, parsed.name) + } } // ...and then consume the arguments until hitting an option diff --git a/Tests/ArgumentParserEndToEndTests/RepeatingEndToEndTests.swift b/Tests/ArgumentParserEndToEndTests/RepeatingEndToEndTests.swift index 43c12c0a..cad7a3b5 100644 --- a/Tests/ArgumentParserEndToEndTests/RepeatingEndToEndTests.swift +++ b/Tests/ArgumentParserEndToEndTests/RepeatingEndToEndTests.swift @@ -210,6 +210,24 @@ extension RepeatingEndToEndTests { XCTAssertEqual(qux.names, ["one", "two"]) XCTAssertNil(qux.extra) } + + AssertParse(Qux.self, ["--verbose", "--names=one"]) { qux in + XCTAssertTrue(qux.verbose) + XCTAssertEqual(qux.names, ["one"]) + XCTAssertNil(qux.extra) + } + + AssertParse(Qux.self, ["--verbose", "--names=one", "two"]) { qux in + XCTAssertTrue(qux.verbose) + XCTAssertEqual(qux.names, ["one", "two"]) + XCTAssertNil(qux.extra) + } + + AssertParse(Qux.self, ["--names=one", "--verbose", "two"]) { qux in + XCTAssertTrue(qux.verbose) + XCTAssertEqual(qux.names, ["one"]) + XCTAssertEqual(qux.extra, "two") + } } func testParsing_repeatingStringUpToNext_Fails() throws {