@@ -377,8 +377,6 @@ extension ArgumentSet {
377377 }
378378
379379 var result = ParsedValues ( elements: [ ] , originalInput: all. originalInput)
380- var positionalValues : [ ( InputOrigin . Element , String ) ] = [ ]
381- var unusedOptions : [ ( InputOrigin . Element , String ) ] = [ ]
382380 var usedOrigins = InputOrigin ( )
383381
384382 try setInitialValues ( into: & result)
@@ -390,8 +388,9 @@ extension ArgumentSet {
390388 }
391389
392390 switch next {
393- case let . value( v) :
394- positionalValues. append ( ( origin, v) )
391+ case . value:
392+ // We'll parse positional values later.
393+ break
395394 case let . option( parsed) :
396395 // Look for an argument that matches this `--option` or `-o`-style
397396 // input. If we can't find one, just move on to the next input. We
@@ -400,7 +399,6 @@ extension ArgumentSet {
400399 guard
401400 let argument: ArgumentDefinition = try ? first ( matching: parsed, at: origin)
402401 else {
403- unusedOptions. append ( ( origin, all. originalInput ( at: origin) ) )
404402 continue
405403 }
406404
@@ -418,14 +416,15 @@ extension ArgumentSet {
418416 case . terminator:
419417 // Mark the terminator as used:
420418 result. set ( ParsedValues . Element ( key: . terminator, value: 0 , inputOrigin: [ origin] ) )
421- unusedOptions. append ( ( origin, all. originalInput ( at: origin) ) )
422419 }
423420 }
424421
425422 // We have parsed all non-positional values at this point.
426423 // Next: parse / consume the positional values.
427424 do {
428- try parsePositionalValues ( positionalValues, unusedOptions: unusedOptions, into: & result)
425+ var stripped = all
426+ stripped. removeAll ( in: usedOrigins)
427+ try parsePositionalValues ( from: stripped, into: & result)
429428 } catch {
430429 switch error {
431430 case ParserError . unexpectedExtraValues:
@@ -470,28 +469,35 @@ extension ArgumentSet {
470469 }
471470
472471 func parsePositionalValues(
473- _ positionalValues: [ ( InputOrigin . Element , String ) ] ,
474- unusedOptions: [ ( InputOrigin . Element , String ) ] ,
472+ from unusedInput: SplitArguments ,
475473 into result: inout ParsedValues
476474 ) throws {
477- guard !positionalValues. isEmpty || !unusedOptions. isEmpty else { return }
478- var positionalValues = positionalValues [ ... ]
479- var unusedOptions = unusedOptions [ ... ]
475+ // Filter out the inputs that aren't "whole" arguments, like `-h` and `-i`
476+ // from the input `-hi`.
477+ var argumentStack = unusedInput. elements. filter {
478+ $0. index. subIndex == . complete
479+ } . map {
480+ ( InputOrigin . Element. argumentIndex ( $0. index) , $0. element)
481+ } [ ... ]
480482
481- /// Pops the next origin / string pair to use.
482- /// If `unconditional` is false, this always pops from `positionalValues`;
483- /// if true, then it pops from whichever of `positionalValues` or
484- /// `unusedOptions` has the element that came first in the original input .
485- func next ( unconditional : Bool ) -> ( InputOrigin . Element , String ) ? {
486- guard unconditional , let firstUnusedOption = unusedOptions . first else {
487- return positionalValues . popFirst ( )
483+ guard !argumentStack . isEmpty else { return }
484+
485+ /// Pops arguments until reaching one that is a value (i.e., isn't dash-
486+ /// prefixed) .
487+ func skipNonValues ( ) {
488+ while argumentStack . first? . 1 . isValue == false {
489+ _ = argumentStack . popFirst ( )
488490 }
489- guard let firstPositional = positionalValues. first else {
490- return unusedOptions. popFirst ( )
491+ }
492+
493+ /// Pops the origin of the next argument to use.
494+ ///
495+ /// If `unconditional` is false, this skips over any non-"value" input.
496+ func next( unconditional: Bool ) -> InputOrigin . Element ? {
497+ if !unconditional {
498+ skipNonValues ( )
491499 }
492- return firstPositional. 0 < firstUnusedOption. 0
493- ? positionalValues. popFirst ( )
494- : unusedOptions. popFirst ( )
500+ return argumentStack. popFirst ( ) ? . 0
495501 }
496502
497503 ArgumentLoop:
@@ -503,16 +509,20 @@ extension ArgumentSet {
503509 let allowOptionsAsInput = argumentDefinition. parsingStrategy == . allRemainingInput
504510
505511 repeat {
506- guard let ( origin, value ) = next ( unconditional: allowOptionsAsInput) else {
512+ guard let origin = next ( unconditional: allowOptionsAsInput) else {
507513 break ArgumentLoop
508514 }
515+ let value = unusedInput. originalInput ( at: origin) !
509516 try update ( [ origin] , nil , value, & result)
510517 } while argumentDefinition. isRepeatingPositional
511518 }
512519
513520 // Finished with the defined arguments; are there leftover values to parse?
514- guard positionalValues. isEmpty else {
515- let extraValues = positionalValues. map { ( InputOrigin ( element: $0. 0 ) , $0. 1 ) }
521+ skipNonValues ( )
522+ guard argumentStack. isEmpty else {
523+ let extraValues : [ ( InputOrigin , String ) ] = argumentStack. map ( \. 0 ) . map {
524+ return ( InputOrigin ( element: $0) , unusedInput. originalInput ( at: $0) !)
525+ }
516526 throw ParserError . unexpectedExtraValues ( extraValues)
517527 }
518528 }
0 commit comments