Reputation: 61
I've search high and low and can't find this. What is the CLI11 method to print out the help. I want to be able to show the user the help when they've entered incorrect info.
Also, does CLI11 throw an exception when no option are given? If not, how do you tell how many options have been given?
Upvotes: 4
Views: 2036
Reputation: 715
When I use app.parse(argc, argv)
in my source code, ./myproj -h
error:
terminate called after throwing an instance of 'CLI::CallForHelp'
what(): This should be caught in your main function, see examples
When I use MACROS CLI11_PARSE
in my source code, no error for ./myproj -h
CLI11_PARSE(app, argc, argv);
Upvotes: 0
Reputation: 452
// App::help() returns a std::string
std::cerr << app::help() << std::flush;
App::exit(...)
leads to help text being emittedHere's the member function App::exit
from CLI/App.hpp
.
We can see that a std::ostream
object out
is used in conjunction with App::help()
and App::help("", AppFormatMode::All)
,
int exit(const Error &e, std::ostream &out = std::cout, std::ostream &err = std::cerr) const {
/// Avoid printing anything if this is a CLI::RuntimeError
if(e.get_name() == "RuntimeError")
return e.get_exit_code();
if(e.get_name() == "CallForHelp") {
out << help();
return e.get_exit_code();
}
if(e.get_name() == "CallForAllHelp") {
out << help("", AppFormatMode::All);
return e.get_exit_code();
}
if(e.get_name() == "CallForVersion") {
out << e.what() << std::endl;
return e.get_exit_code();
}
if(e.get_exit_code() != static_cast<int>(ExitCodes::Success)) {
if(failure_message_)
err << failure_message_(this, e) << std::flush;
}
return e.get_exit_code();
}
App::help(...)
itselfApp::help(...)
itself has the following prototype:
std::string help(std::string prev = "", AppFormatMode mode = AppFormatMode::Normal) const
We can therefore use App::help
(Compiler Explorer demo short url, demo full url):
// C++ Standard Library
#include <iostream>
#include <string>
// 3rd party libraries
#include "CLI/CLI.hpp"
int main() {
CLI::App app{"Demonstration app"};
// Assigning to string for demonstrative purposes
const std::string help_text = app.help();
std::cerr << help_text << std::flush;
return 0;
}
yielding:
Demonstration app
Usage: [OPTIONS]
Options:
-h,--help Print this help message and exit
This also works for subcommands (Compiler Explorer demo short url, demo full url):
CLI::App* app_sub_command = app.add_subcommand("usage", "This is a subcommand");
std::cerr << app_sub_command->help() << std::flush;
which yields:
This is a subcommand
Usage: usage [OPTIONS]
Options:
-h,--help Print this help message and exit
The function signature of App::help
came to be on commit 952f291
, in April of 2018.
Upvotes: 6
Reputation: 61
I will answer my own question so that it may help someone else in the future.
I ran across a code snippet on the net that hinted at a solution and lead me to an answer. In short, there is no CLI11 method to directly print out the help text. However, there are two ways to print the help text programmatically.
try/catch block
This the CLI11 native method. After you have set up all your option definitions, define a try/catch block as in:
CLIx::App app( argc,
argv );
.
.
.
try
{
app.parse( argc,
argv);
}
catch( const CLI::CallForHelp &e )
{
exit( app.exit( e ) );
}
The line "exit( app.exit( e ) );" calls the app parser method "exit" which prints the help text and returns an errorcode to exit the program. Then when you want help text printed, simply do a throw:
throw CLI::CallForHelp();
This exception is never described in any if the documentation, and is only discovered by crawling through CLI11's source.
sort of directly, slightly clumsy
The previous method assumes you want to exit the program after printing the help text. In my case that wouldn't work since I have users entering commands with options at an interactive prompt as part of my program. Instead, you can call CLI11's exit method directly with a fake exception:
app.exit( CLI::CallForHelp() );
Kind of goofy, but gets the job done.
Again, nowhere is this documented anywhere and is only discover by going through the CLI11 code.
Lastly, despite this little wart, I highly recommend CLI11. It's easy to use and quite powerful.
Upvotes: 2