question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support intercepting the help message generated by a multiple-subcommand application

See original GitHub issue

Currently, if one has a command-line application with multiple subcommands, and one wants to write a high-level help message to the console, they would write something like this:

String... args = ...;
CommandLine cmd = ...;
cmd.parseWithHandler(new RunLast(), System.out, args);

or if things are a bit more complicated (as is the case for me):

String... args = ...;
CommandLine cmd = ...;
try {
  List<CommandLine> parsedArgs = cmd.parse(args);
  new RunLast().handleParseResult(parsedArgs, System.out, Ansi.AUTO);
  System.exit(0);
} catch (ParameterException exception) {
  new DefaultExceptionHandler()
      .handleException(exception, System.err, Ansi.AUTO, args);
  System.exit(-1);
}

But sadly, this is not quite enough for me, because I need some way of “intercepting” the text sent to System.{out,err} so that I can assert on the contents of auto-generated help message at unit-test time.

The closest solution I’ve thought of so far is to use PrintWriters in place of System.{out,err} so that, at unit-test time, I can swap out System.{out,err} with a custom PrintWriter that diverts the text it receives to a StringWriter, so that I can query the text directly. But sadly, this doesn’t work because RunLast::handleParseResult doesn’t have an overload that accepts a PrintWriter instead of a PrintStream.

Does picocli have something built-in that would allow me to intercept the auto-generated help message of a command-line application with multiple subcommands?

If not, would providing an overload of IParseResultHandler::handleParseResult that accepts a PrintWriter be an idea that the picocli team would be interested in implementing?

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:17 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
remkopcommented, Oct 29, 2017

I just thought of a way to address your requirements while also reducing the number of arguments passed to the parseWithHandler(s) methods (these methods already have too many arguments…)

  • add constructors to the default handler implementations that take a target PrintStream or PrintWriter (also take an optional Help.Ansi parameter)
  • add a method andExit(int) to the default handlers that returns a wrapper that invokes the handler first and then calls System.exit with the specified error code. Add this method to the default handlers instead of adding a static method on CommandLine.

User code, like your application, would look like this:

// production code
cmd.parseWithHandlers(new RunLast(System.out).andExit(0),
                      new DefaultExceptionHandler(System.err).andExit(-1),
                      args);

Test code could look like this:

// test code
StringWriter printWriter = new StringWriter();
cmd.parseWithHandlers(new RunLast(printWriter),
                      new DefaultExceptionHandler(printWriter),
                      args);
assertEquals(expected, printWriter.toString());

This looks a lot cleaner than the current API and I wish I had thought of it earlier…

This also makes it possible to have much simpler IParseResultHandler and IExceptionHandler interfaces:

// remove arguments: PrintStream and Help.Ansi 

// IParseResultHandler2
List<Object> handleParseResult(List<CommandLine> parsedCommands) throws ExecutionException;

// IExceptionHandler2
List<Object> handleException(ParameterException ex, String... args);

Unfortunately I can’t think of another way to avoid breaking backwards compatibility than adding additional interfaces with different names. Darn, I really wish we could have had this conversation a week ago! 😃

1reaction
remkopcommented, Apr 2, 2018

Yes it certainly was helpful! The user manual is already a bit biggish, so How to test picocli command line applications will likely be a separate article. Thanks again for the great feedback!

Read more comments on GitHub >

github_iconTop Results From Across the Web

MVS Interactive Problem Control System (IPCS) Commands
IPCS provides formatting and analysis support for dumps and traces produced by MVS™ and other program products and applications that run on ...
Read more >
Display help message with Python argparse when script is ...
This answer comes from Steven Bethard on Google groups. I'm reposting it here to make it easier for people without a Google account...
Read more >
SHOW Subcommand -- All Other Settings - TechDocs
The SHOW subcommand lists information about ACF2 as it is running on your system. ... Displays all active site-defined structured infostorage applications.
Read more >
IBM SPSS Statistics 22 Command Syntax Reference
The Command Syntax Reference is arranged alphabetically by command name to provide quick access to detailed information about each command in the syntax ......
Read more >
Overview: Dell Remote Access Controller Racadm User's Guide
NOTE: The racadm command-line utility is supported on Dell™ PowerEdge™ 7150 ... The racadm help <subcommand> displays any syntax and command-line options.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found