commandline icon indicating copy to clipboard operation
commandline copied to clipboard

DashDash (--) doesn't work properly with multi-value options

Open robnasby opened this issue 5 years ago • 4 comments

When using the "DashDash" feature, the results are unexpected when using a multi-valued option.

Single-valued option (base case)

Program.cs

    class Program
    {
        #region Main

        static int Main(string[] args)
        {
            return new Parser(with => with.EnableDashDash = true)
                    .ParseArguments<CommandLineOptions>(args)
                    .MapResult(options => RunWrappedExecutable(options),
                               _ => -2);
        }

        #endregion
    }

CommandLineOptions.cs

    class CommandLineOptions
    {
        #region Properties

        [Option('o', "option")]
        public string Option { get; set; }

        [Value(0)]
        public IEnumerable<string> Values { get; set; }

        #endregion
    }

Running the program as follows:

foo.exe -o "option" -- value1 value2 value3

produces the (expected) results:

options.Option = "option"
options.Values = [ "value1", "value2", "value3" ]

Multi-valued option (broken case)

CommandLineOptions.cs

    class CommandLineOptions
    {
        #region Properties

        [Option('o', "option")]
        public IEnumerable<string> Option { get; set; }

        [Value(0)]
        public IEnumerable<string> Values { get; set; }

        #endregion
    }

Running the program as follows:

foo.exe -o "option" -- value1 value2 value3

produces the (unexpected) results:

options.Option = [ "option", "value1", "value2", "value3" ]
options.Values = [ ]

Conclusion

My expectation is that any arguments after the -- would be processed as values, rather than options. Can you confirm my expectations match yours? If so, I'm happy to try to resolve this issue and submit a PR. Thanks!

robnasby avatar Mar 23 '20 19:03 robnasby

After digging into the source, the issue is a loss of context during tokenization. Arguments after the double dash are of type Value, but they are combined with the tokens generated from arguments before the double dash. During parsing, when the multi-value Name token is encountered, it grabs all subsequent Value tokens, since it has no way to distinguish between those before the double dash and those after.

One way to resolve this is to introduce a new token type ValueForced, which can never be attributed to an option property. This should force them to go to value properties (and trigger an error if there are no value properties available).

robnasby avatar Mar 25 '20 23:03 robnasby

My expectation is that any arguments after the -- would be processed as values, rather than options.

Yes, you are correct. The only effect of double dash '--' is terminating all options and any following arguments are treated as non-option arguments, even if they begin with a hyphen and can't be used for partitioning values.

so parsing

-o option1  -- value1 --value2 value3

will be -o: option token option1 value1 --value2 value3 : value token and will be assigned to 'Option' Enumerator.

Value token has a property ExplicitlyAssigned which is true when parser split the option of IEnumerable<string> otherwise it's false.

Edit: In the scenario 'Multi-valued option' I find #607 merged with both #594 and #610 solved it nicely.

moh-hassan avatar Apr 13 '20 22:04 moh-hassan

Hi! I am trying to understand when this is going to be fixed. There is a lot of issues related to it but I understand this as the root issue. I am currently having this exact issue. I have tried version 2.8.0 and the new 2.9.0-preview1. Is there some kind of workaround to actually make -- split multi-options and values?' (I do have EnableDashDash = true)

The expected behavior of -o first second -- some -cool "--values 1 2 3" would be:

-o : [ "first", "second" ]
values: [ "some", "-cool", "--values 1 2 3" ]

Where o is an IEnumerable.

Thanks

icedoor avatar Dec 07 '20 14:12 icedoor

Hi there,

What's the status of this issue? It looks to me that it's recognized as a bug to be fixed? It really bothers me as there is virtually no way to combine IEnumerable Option with Value. I have to split a single string argument instead of IEnumerable, which looks ugly.

Kimi-Arthur avatar Sep 13 '23 16:09 Kimi-Arthur