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

Unformatted description configuration in generated help #301

Closed
ghost opened this issue Mar 18, 2018 · 11 comments
Closed

Unformatted description configuration in generated help #301

ghost opened this issue Mar 18, 2018 · 11 comments

Comments

@ghost
Copy link

ghost commented Mar 18, 2018

When displaying the generated usage help of a parent command with sub commands, the description configuration is not using format for "%n". The printed description shows the text unformatted:

Commands:
          dump  %nPrint %ninformation.

The following code can be used to replicate the issue:

public class Demo {
    @Command(name = "main", description = "%nPrint information.", subcommands = Dump.class)
    static class MainCommand implements Runnable {

        @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "Print this help message.")
        private boolean showHelp;

        public void run() {
            System.out.println("main command");
        }
    }

    @Command(name = "dump", description = "%nPrint %ninformation.")
    static class Dump implements Runnable {

        @ParentCommand
        private MainCommand parent;

        @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true, description = "Print this help message.")
        private boolean showHelp;

        @Override
        public void run() {
            System.out.println("sub command");
        }
    }

    public static void main(String[] args) {
        test1();
        //test2();
    }

    public static void test1() {
        CommandLine.run(new MainCommand(), System.out, "-h");
        /* 
        Usage: main [-h]

        Print information.
          -h, --help                  Print this help message.
        Commands:
          dump  %nPrint %ninformation.
         */
    }

    public static void test2() {
        CommandLine.run(new MainCommand(), System.out, "dump", "-h");
        /*
        Usage: dump [-h]
        
        Print
        information.
          -h, --help                  Print this help message.
         */
    }
}

Version: piclocli 2.3.0

Tks,

@remkop
Copy link
Owner

remkop commented Mar 19, 2018

At the moment, only section headings may contain embedded line separator (%n) format specifiers. For section text (description, header, footer), applications can specify multiple strings, which will be displayed on separate lines. For example:

@Command(name = "dump", description = {"Print", "information", "line 3", "line 4"})
class Dump implements Runnable {
//...
}

@remkop remkop added this to the 3.2 milestone May 16, 2018
@remkop remkop modified the milestones: 3.4, 3.6 Aug 3, 2018
@remkop remkop modified the milestones: 3.6, 3.7 Aug 26, 2018
@remkop remkop modified the milestones: 3.7, 3.8 Oct 19, 2018
@topalavlad
Copy link
Contributor

At the moment, only section headings may contain embedded line separator (%n) format specifiers. For section text (description, header, footer), applications can specify multiple strings, which will be displayed on separate lines. For example:

I might be missing something since I'm new to the code, but from what I see, when listing Commands:

  • Only header and description are printed if one of them exists
  • Neither of them is formatted
  • Only the first value is printed out of the array so using description = {"Print", "information", "line 3", "line 4"} will only print Print
public String commandList() {
    ...
                String header = command.usageMessage().header() != null && command.usageMessage().header().length > 0 ? command.usageMessage().header()[0]
                        : (command.usageMessage().description() != null && command.usageMessage().description().length > 0 ? command.usageMessage().description()[0] : "");
                Text[] lines = ansi().text(header).splitLines();
    ...
}

I would like to give this issue a try. I think formatting header on the last line in the snippet above is the way to go. But after checking other similar places, I'm thinking, is formatting with args expected? Because if it is, it seems more difficult than simply formatting %n since each command should have its own parameters maybe?

@remkop
Copy link
Owner

remkop commented Nov 10, 2018

Thanks for considering contributing to picocli!

About your question, let’s keep it simple and stick to just the %n line separator, no formatting parameters. #526 will allow applications to accomplish more complex stuff.

When testing, please also use a few very long strings, such that even after formatting and splitting lines, some lines exceed the usage help message width. Long lines should be wrapped automatically in the last column of the table in the subcommand list section. But please test this.

@remkop remkop modified the milestones: 4.1, 3.8 Nov 10, 2018
@remkop
Copy link
Owner

remkop commented Nov 10, 2018

Just to give you an early heads up: I may roll out a release in a week or so. If that’s too soon no problem, the one after that will likely be the 4.0 release.

@topalavlad
Copy link
Contributor

topalavlad commented Nov 10, 2018

Thanks for the heads up. I tried to think of another way of replacing %n instead of format() because having a description that contains %s for example will fail, but I see the same happens in the command description.

If a user adds the description: This command will replace any %s characters without the intention of actually replacing %s, picocli will throw an exception. I didn't find any way of escaping, pretty sure it's not a common use case though. Maybe something for the backlog?

@remkop
Copy link
Owner

remkop commented Nov 10, 2018

Thanks for the pull request. To answer your question: It’s fine to use the standard String.format method. The exception is fine: there is no way to pass in parameters so using %s doesn’t make sense. Don’t worry about it; I don’t think this is a problem that needs to be solved.

I saw the test in the PR, so when a header containing %n is used in the subcommand listing things work fine now. Did you have a chance to test that a header with very long lines is correctly wrapped in the rightmost column?

Also, what about the usage help for that subcommand itself? Does that render the %n as newlines correctly?

For example, what does the usage help message of the Dump subcommand in the original post look like?

@topalavlad
Copy link
Contributor

topalavlad commented Nov 10, 2018

Did you have a chance to test that a header with very long lines is correctly wrapped in the rightmost column?

Yes, I did test with strings that I split multiple times and even after split span over 2-3 rows. They're wrapped correctly to the right most column.

Also, what about the usage help for that subcommand itself? Does that render the %n as newlines correctly?

For main dump -h it's rendered left most like it would be a main command correctly rendering %n but that already worked fine.

@remkop
Copy link
Owner

remkop commented Nov 10, 2018

Would you mind adding unit tests for your findings?

@topalavlad
Copy link
Contributor

I added a test, I hope that's what you expected.

There's one small inconsistency, usage help does not indent the lines as when listing subcommands. It just prints every line with no whitespace at the beginning.

Also, unrelated to my change, usage help now shows the whole command, not as shown in the issue report: Usage: dump [-h] vs Usage: main dump [-h]. Not an issue, just for the record.

remkop pushed a commit that referenced this issue Nov 10, 2018
Format header and description for subcommands
remkop pushed a commit that referenced this issue Nov 10, 2018
@remkop
Copy link
Owner

remkop commented Nov 10, 2018

It's been a while since I looked at this code. I now see what you mean with the %s formatting parameters. You are correct.

Still, I never was happy with this %s formatting since it is only useful for users who use the Help API directly; it cannot be used via the annotations API or the UsageMessageSpec programmatic API. #526 is a better approach, I think.

I am considering removing the parameters in picocli 4.0.

@remkop remkop closed this as completed in d1dbe8f Nov 10, 2018
@remkop
Copy link
Owner

remkop commented Nov 10, 2018

Merged into master.
Thanks again for the pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants