-
Notifications
You must be signed in to change notification settings - Fork 421
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
Is it expected for an inherited option to not be matched in the ParsedResult when executing a sub-command? #1159
Comments
Thank you for raising this! Let me repeat your question to see if I understand it correctly:
About question 1, I suspect that when abbreviated options/commands were implemented, we overlooked the possibility that abbreviated options could be combined with inherited options. So this may be a bug. But I am just guessing, I need to create a way to reproduce the issue and step through it to look in more detail. About question 2, as you point out, the inherited option is actually set on the parent command, but in honesty I did not consider what the expected Interesting question: I tend to use the |
@metacosm, I could not reproduce the first issue you reported (inherited options in subcommands don't allow abbreviations). Can you provide steps to reproduce the issue? This test passes: @Command(name = "Issue1159")
static class Issue1159 {
@Option(names = "--xxx-yyy", scope = INHERIT)
int x;
@Command
void sub() {
}
}
@Test
public void testIssue1159() {
Issue1159 bean = new Issue1159();
CommandLine cmd = new CommandLine(bean);
cmd.setAbbreviatedOptionsAllowed(true);
cmd.parseArgs("--x-y", "123");
assertEquals(123, bean.x);
cmd.parseArgs("sub", "--x-y", "345");
assertEquals(345, bean.x);
} |
@metacosm, I suspect that the first issue you reported (inherited options in subcommands don't allow abbreviations) was actually caused by a different bug. I created a separate ticket for this: #1162 Abbreviated options are not matched if value attached with '=' separator (like -x=3). Can you confirm that this is correct? (If I am wrong there is another issue that still needs to be solved...) After fixing #1162, the below test now passes, so it seems that inherited options can be abbreviated in subcommands. Please let me know if I am overlooking something. @Test
public void testIssue1159WithEquals() {
Issue1159 bean = new Issue1159();
CommandLine cmd = new CommandLine(bean);
cmd.setAbbreviatedOptionsAllowed(true);
cmd.parseArgs("--x-y=123");
assertEquals(123, bean.x);
cmd.parseArgs("sub", "--x-y=345");
assertEquals(345, bean.x);
} |
I will check hopefully today. However, my options were in the |
I misunderstood what abbreviated options actually meant… 😅 Here's the use case I wondered about: @Command(name = "Issue1159")
static class Issue1159 {
@Option(names = {"--xxx-yyy", "-x"}, scope = INHERIT)
int x;
@Command
void sub() {
}
}
@Test
public void testIssue1159() {
Issue1159 bean = new Issue1159();
CommandLine cmd = new CommandLine(bean);
CommandLine.ParseResult parseResult = cmd.parseArgs("sub", "-x", "345");
Object value = parseResult.matchedOption("-x").getValue(); // this NPEs because matchedOption returns null
assertEquals(345, bean.x);
} I would have expected |
Thanks for that test case. @Command(name = "Issue1159")
static class Issue1159 {
@Option(names = "--xxx-yyy", scope = INHERIT)
int x;
@Command
void sub() {
}
}
@Test
public void testIssue1159ParseResult() {
Issue1159 bean = new Issue1159();
CommandLine cmd = new CommandLine(bean).setAbbreviatedOptionsAllowed(true);
ParseResult parseResult = cmd.parseArgs("sub", "--x", "345");
assertEquals(345, bean.x);
assertTrue(parseResult.hasSubcommand());
ParseResult subResult = parseResult.subcommand();
assertTrue("Matched on the subcommand", subResult.hasMatchedOption("--xxx-yyy")); // works as expected
Object subValue = subResult.matchedOption("--xxx-yyy").getValue(); // also works correctly
assertEquals(345, subValue);
assertFalse("Abbreviated options not supported in ParseResult...",
subResult.hasMatchedOption("--x")); // this does not work
assertFalse("Not matched on the parent command",
parseResult.hasMatchedOption("--xxx-yyy")); // false because the option was not matched on the top-level cmd
} Note:
Is it possible you were not aware that the The only potential issue I see is that What do you think? |
I think there are several "issues":
@Command(name = "Issue1159")
static class Issue1159 {
@Option(names = {"--foo", "-f"}, scope = INHERIT)
int x;
@Command
void sub() {
}
}
@Test
public void testIssue1159() {
Issue1159 bean = new Issue1159();
CommandLine cmd = new CommandLine(bean);
final CommandLine.ParseResult sub = cmd.parseArgs("sub", "-f", "345");
assertEquals("345", sub.commandSpec().findOption('f').getValue().toString());
assertEquals("345", sub.matchedOption("foo").getValue().toString()); // <= NPE
assertEquals("345", sub.matchedOption('f').getValue().toString()); // <= NPE
assertEquals(345, bean.x);
} The gist of my issue is whether it is expected that inherited options are not considered matched on sub-commands. As the Hope this is clearer. |
Sorry I was unclear.
Your expectation is correct. The
With this small modification, your test passes: @Test
public void testIssue1159() {
Issue1159 bean = new Issue1159();
CommandLine cmd = new CommandLine(bean);
// parse result of the *top-level* command
CommandLine.ParseResult top = cmd.parseArgs("sub", "-f", "345");
assertEquals("345", top.commandSpec().findOption('f').getValue().toString()); // unrelated to parse result
assertNull(top.matchedOption("foo")); // --foo was NOT matched *on the top-level command*
assertTrue(top.matchedOptions().isEmpty());
CommandLine.ParseResult sub = top.subcommand(); // get parse result for the subcommand
assertFalse(sub.matchedOptions().isEmpty()); // some option(s) were matched on the subcommand
assertEquals("345", sub.matchedOption("foo").getValue().toString()); // --foo WAS matched on the subcommand
assertEquals("345", sub.matchedOption('f').getValue().toString()); // assertion succeeds
assertEquals(345, bean.x);
} |
@metacosm Did this answer your question? |
@remkop yes, the distinction between top vs sub parse results wasn't clear to me. Thank you! |
Context: I have a command with several sub-commands. The top-level command defines some required options which can be either full or abbreviated. When I execute a sub-command, I noticed that not only the inherited options don't appear to be processed as abbreviated (i.e. the parser for the sub-command spec "loses" the fact that abbreviated options are allowed) but also that they don't appear when doing a
parsedResult.matchedOption()
call… while they do appear when doing aparsedResult.findOption()
call.Is that expected? I could see how it could be expected since, strictly speaking, the option is set on the parent command, not the one that's being executed but I find that confusing: as the option is inherited, I expect it to behave as a regular option on my sub-command…
The text was updated successfully, but these errors were encountered: