Skip to content
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

ArgGroup contents incorrectly listed in asciidoc output #1696

Closed
rsenden opened this issue Jun 1, 2022 · 1 comment · Fixed by #1697
Closed

ArgGroup contents incorrectly listed in asciidoc output #1696

rsenden opened this issue Jun 1, 2022 · 1 comment · Fixed by #1697
Labels
theme: codegen An issue or change related to the picocli-codegen module type: bug 🐛
Milestone

Comments

@rsenden
Copy link
Contributor

rsenden commented Jun 1, 2022

One of my command classes is using some ArgGroups, for example with headings 'SSC connection options' and 'SSC authentication options'. In the picocli help output, the options are displayed under the correct heading:

Usage: fcli ssc session login ...
Login to SSC

Generic options:
     ...
Output options:
      ...
SSC connection options:
      --url=<url>
      ...
SSC authentication options:
  -u, --user=<user>
  -p, --password[=<password>]
   ...

However, when generating the asciidoc (using https://github.com/remkop/picocli/tree/main/picocli-codegen#gradle-example-1), the SSC authentication options section is empty, and the options that should appear in that section are displayed under the generic options. The other ArgGroup for connection options is rendered correctly in the asciidoc.

...
// tag::picocli-generated-man-section-options[]
== Options

*-u*, *--user*=_<user>_::

*-p*, *--password*[=_<password>_]::

...

== SSC connection options:

*--url*=_<url>_::
  
...

== SSC authentication options:

<empty>

Any idea why this is happening?

Following is a snippet of the command class, full source code is available here: https://github.com/fortify-ps/fcli/blob/c0fb15cc6275fd814e54626cd201feb67f2f16d1/fcli-ssc/src/main/java/com/fortify/cli/ssc/picocli/command/session/SSCSessionLoginCommand.java#L47

@Command(name = "login", description = "Login to SSC", sortOptions = false)
public class SSCSessionLoginCommand extends AbstractSessionLoginCommand<SSCSessionLoginConfig> {
	@Getter @Inject private SSCSessionLoginHandler sscLoginHandler;
	
	@ArgGroup(exclusive = false, multiplicity = "1", heading = "SSC connection options:%n", order = 1)
	@Getter private LoginConnectionOptions connectionOptions;
	
	@ArgGroup(exclusive = false, multiplicity = "1", heading = "SSC authentication options:%n", order = 2)
	@Getter private SSCAuthOptions authOptions;
	
	static class SSCAuthOptions {
		@ArgGroup(exclusive = true, multiplicity = "1", order = 3)
		@Getter private SSCCredentialOptions credentialOptions;
	}
	
    static class SSCCredentialOptions {
    	@ArgGroup(exclusive = false, multiplicity = "1", order = 1) 
    	@Getter private SSCUserCredentialOptions userOptions = new SSCUserCredentialOptions();
    	@ArgGroup(exclusive = false, multiplicity = "1", order = 2) 
    	@Getter private TokenOptions tokenOptions = new TokenOptions();
    }
    
    static class SSCUserCredentialOptions extends LoginUserCredentialOptions implements ISSCUserCredentialsConfig {
    	@Option(names = {"--expire-in"}, required = false, defaultValue = "1d", showDefaultValue = Visibility.ALWAYS) 
    	@Getter private String expireIn;
    	
    	@Override
    	public OffsetDateTime getExpiresAt() {
    		return DateTimeHelper.getCurrentOffsetDateTimePlusPeriod(expireIn);
    	}
    }
    
    static class TokenOptions {
    	@Option(names = {"--token", "-t"}, required = true, interactive = true, arity = "0..1", echo = false) 
    	@Getter private char[] token;
    }

The same happens by the way for a similarly structured command class; for this class also the connection options are rendered correctly but the authentication options are not: https://github.com/fortify-ps/fcli/blob/c0fb15cc6275fd814e54626cd201feb67f2f16d1/fcli-fod/src/main/java/com/fortify/cli/fod/picocli/command/session/FoDSessionLoginCommand.java#L47

Using picocli version 4.6.3.

@remkop
Copy link
Owner

remkop commented Jun 2, 2022

@rsenden Yes you are right. The logic in ManPageGenerator is different from (and not as good as) the logic in CommandLine that generates the usage help message.

ManPageGenerator only considers options in a group if the group they are in has a non-null header text; whereas in CommandLine it also includes options that are in nested subgroups of the group that has a non-null header.

ManPageGenerator should use this logic instead:

        private List<OptionSpec> excludeHiddenAndGroupOptions(List<OptionSpec> all) {
            List<OptionSpec> result = new ArrayList<OptionSpec>(all);
            for (ArgGroupSpec group : optionSectionGroups()) { result.removeAll(group.allOptionsNested()); }
            for (Iterator<OptionSpec> iter = result.iterator(); iter.hasNext(); ) {
                if (iter.next().hidden()) {
                    iter.remove();
                }
            }
            return result;
        }
        private List<PositionalParamSpec> excludeHiddenAndGroupParams(List<PositionalParamSpec> all) {
            List<PositionalParamSpec> result = new ArrayList<PositionalParamSpec>(all);
            for (ArgGroupSpec group : optionSectionGroups()) { result.removeAll(group.allPositionalParametersNested()); }
            for (Iterator<PositionalParamSpec> iter = result.iterator(); iter.hasNext(); ) {
                if (iter.next().hidden()) {
                    iter.remove();
                }
            }
            return result;
        }

Do you feel like creating a pull request for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: codegen An issue or change related to the picocli-codegen module type: bug 🐛
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants