-
Notifications
You must be signed in to change notification settings - Fork 480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Properly assign arguments after a double dash to values #610
Properly assign arguments after a double dash to values #610
Conversation
This will almost certainly conflict with #607, where I rewrote the guts of the Tokenizer to allow for proper getopt compatibility (see #601 for rationale). I'm a little short on time this week, but I'll see if I can incorporate your changes, or something equivalent, into my PR branch for #607 so that |
I gave the rebase a try today and discovered that it will take a complete rewrite, which is more than I have time for at the moment (I only have little bits of time for this project this month). The tokenizer isn't the big issue; the big issue is Sequence.cs, which was completely changed by #594 (which is a PR that I created, but the actual code is by @tydunkel and I don't fully understand it yet). All my other PRs (#607 and #608) I wrote on top of #594, and since I don't yet understand the changes to Sequence.cs that @tydunkel made for #594, I won't be able to do the rebase until I have time to properly sit down and understand the code, which won't be for a few more weeks given my other obligations. So @robnasby, if you want to rebase this on top of #608 (probably better than rebasing on top of #607), you'll need to check out the |
P.S. When I rewrote the guts of the tokenizer in #607 I ended up making the ExplicitlyAssigned property meaningless, so if you want to remove it (or rename it to ValueForced), that might let you implement your logic for this PR with fewer changes to the Token API. |
@robnasby , @rmunn
class Options
{
[Option('o', "option", Separator = ',')]
public IEnumerable<string> Option { get; set; }
[Value(1)]
public string Value2 { get; set; }
[Value(0)]
public string Value1 { get; set; }
} |
Please, add xml documentation for all new properties/ .. with explanation using comments. |
This test Fail. class CommandLineOptions3
{
[Value(0)]
public IEnumerable<string> Option { get; set; }
[Value(1)]
public string Value1 { get; set; }
[Value(2)]
public string Value2 { get; set; }
} Result:
Expected:
|
@moh-hassan - As I understand the docs in https://github.com/commandlineparser/commandline/wiki/Getting-Started#value-attribute, if an The documentation says nothing about how class CommandLineOptions
{
[Value(0)]
public string Value0 { get; set; }
[Value(1)]
public string Value1 { get; set; }
[Value(2)]
public string Value2 { get; set; }
} I would expect all four of the following command lines to put
And given what the docs say, in the options class you defined: class CommandLineOptions3
{
[Value(0)]
public IEnumerable<string> Option { get; set; }
[Value(1)]
public string Value1 { get; set; }
[Value(2)]
public string Value2 { get; set; }
} I would expect all of the following command lines to behave exactly the same as well, putting
All five of those lines should produce exactly the same result, given that we are not dealing with Options, but Values. Here's another example. Consider a shell script that does something like this:
Here the intent is to process all text files in the directory stored in the SOMEDIR variable. (The
Speaking as an experienced Linux user, I would be quite surprised, and would file a bug report, if that command line processed only |
That would be a behavior change from the current code, which does not warn (or throw an error) about extra values at the end of the command line. I checked by running the test you suggested here, against the current state of both the I don't mind changing that behavior, but I think that change belongs in a different PR and would be out of scope for this one. |
You are correct, -- is used as you said "stop processing options and consider everything after this point to be a value" In pr #610, it's intended to use -- with extra role as a "value separator between
The test case that I provided is intended to use -- as a value separator between If the test case is incorrect (i.e not applicable or not supported) we can add this in Wiki and provide guidelines for developers how to use this feature effectively. But really, it can be handled and -- do its extra role as a value separator.
Ok, it can be in a different PR.
Xml doc help developer and reviewer to understand the flow of program and help in future maintenance, even if it's missed in the original author. |
The way If your getopt-using program had a But what would happen in getopt if you didn't use So it makes sense to me that in CLP, a In other words:
I believe that this test case is not applicable, because it's testing for behavior that CLP should not have. The behavior I believe CLP should have, since it tries to mimic getopt as closely as possible, is that |
This test case fail but success in v2.8: [Fact]
public void Enable_dash_dash_true_for_IEnumerable_test()
{
//Arrange
var args = "-n abc -p -- -x -y -z 44".Split();
//Act
var parser = new Parser(with =>
{
with.EnableDashDash = true;
});
parser.ParseArguments<Options610>(args)
.WithParsed(opt =>
{
var expected = new[] { "-x", "-y", "-z", "44" };
opt.PluginArgs.Any().Should().BeTrue();
opt.PluginArgs.Should().BeEquivalentTo(expected);
});
}
class Options610
{
// plugin name
[Option('n')]
public string Name { get; set; }
//plugin options
[Option('p')]
public IEnumerable<string> PluginArgs { get; set; }
} |
@moh-hassan That test case is testing for the very bug that #605 is all about, and that this PR is trying to fix. @robnasby (and I as well) believe that anything after So to write that test case properly, so that it fails when the bug is present but succeeds once the bug is fixed, you should reverse what it expects and write it like this: [Fact]
public void Enable_dash_dash_true_for_IEnumerable_test()
{
//Arrange
var args = "-n abc -p -- -x -y -z 44".Split();
//Act
var parser = new Parser(with =>
{
with.EnableDashDash = true;
});
parser.ParseArguments<Options610>(args)
.WithParsed(opt =>
{
var expected = new[] { "-x", "-y", "-z", "44" };
opt.PluginArgs.Any().Should().BeFalse();
opt.ExtraArgs.Any().Should().BeTrue();
opt.ExtraArgs.Should().BeEquivalentTo(expected);
});
}
class Options610
{
// plugin name
[Option('n')]
public string Name { get; set; }
//plugin options
[Option('p')]
public IEnumerable<string> PluginArgs { get; set; }
[Value]
public IEnumerable<string> ExtraArgs { get; set; }
} |
What is the bug here? |
The bug here is #605. The 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:
was expected to produce the results: options.Option = [ "option" ]
options.Values = [ "value1", "value2", "value3" ] Because the |
…rguments after a double dash to values (PR #610)
I have resolved the confliction and merged the PR to develop branch for release v2.9.0-preview2 |
Merged to develop manually |
@moh-hassan Will there be a new release including this fix any time soon? It was committed on Aug 5, 2020 and there has not been a release since Jul 24, 2020. |
Hi @icedoor
I can't publish a new release because the nuget key expired and waiting the project owner to renew the key. |
Hi @moh-hassan , Thanks for the info! Thanks |
CC/ @ericnewton76 |
This is a working solution to issue #605, which properly assigns arguments after a double dash to values, rather than options. However, I'm not particularly happy with the solution, so I'm looking for feedback.
I created a new token type
ValueForced
, which is only used by theTokenizer
whenEnableDashDash
is set and--
is encountered.Sequence
will not selectValueForced
tokens. I think the overall pattern is fine, but I don't like the nameValueForced
for the token. Unfortunately, the work Value is already overloaded quite a bit, which is why I struggled with a better name.I also want to add a test to verify that parsing fails if there are arguments following the double dash, but the options object doesn't include any Value properties. If there are any other tests you'd like me to add, let me know. Thanks!