Automated Usage Generation
Context
Hey, firstly just wanted to say thanks for the addition of the CLI parser. One feature that I've ended up hand-rolling in my own codebase but which I feel could be generally applicable is a generated Usage/Help function (directly from the named tuple read() types so renames are tracked etc) for printing the expected CLI arguments.
The library already has everything needed to generate this, so it seems like a natural addition.
Proposal
A usage function in rfl::cli, generated from the same struct
rfl::cli::read<T>() parses into:
template <class T, class... Ps>
std::string usage(const std::string& program_name, bool detailed = false);
Given:
enum class LogLevel { debug, info, warn };
struct Database {
std::string host;
int port;
};
struct Config {
rfl::Positional<std::string> input_file;
std::string host_name;
bool verbose;
std::vector<std::string> tags;
rfl::Short<"p", int> port;
Database database;
std::optional<LogLevel> log_level;
};
rfl::cli::usage<Config>("my_binary") returns:
Usage: my_binary <input-file> --host-name=<value> --verbose[=<bool>] --tags=<v1,v2,...> -p|--port=<value> --database.host=<value> --database.port=<value> [--log-level=<debug|info|warn>]
The detailed flag could extend this to a full help form, taking into account any descriptions passed via rfl::Description. Given:
struct Config {
rfl::Description<"Path to the input file", rfl::Positional<std::string>> input_file;
rfl::Description<"Host to connect to", std::string> host_name;
bool verbose;
rfl::Description<"Port to connect on", rfl::Short<"p", int>> port;
rfl::Description<"Minimum level to log", std::optional<LogLevel>> log_level;
};
rfl::cli::usage<Config>("my_binary", /*detailed=*/true) returns the usage line followed
by one line per argument, with the description where one was given:
Usage: my_binary <input-file> --host-name=<value> --verbose[=<bool>] -p|--port=<value> [--log-level=<debug|info|warn>]
Arguments:
input-file: Path to the input file
host-name: Host to connect to
verbose:
port: Port to connect on
log-level: Minimum level to log
I'd be happy to put up a PR for this if it seems useful.
Note: The proposal only covers manual generation, there's potential to auto handle a --help/--usage in future but that's out of scope.
Automated Usage Generation
Context
Hey, firstly just wanted to say thanks for the addition of the CLI parser. One feature that I've ended up hand-rolling in my own codebase but which I feel could be generally applicable is a generated
Usage/Helpfunction (directly from the named tupleread()types so renames are tracked etc) for printing the expected CLI arguments.The library already has everything needed to generate this, so it seems like a natural addition.
Proposal
A
usagefunction inrfl::cli, generated from the same structrfl::cli::read<T>()parses into:Given:
rfl::cli::usage<Config>("my_binary")returns:The
detailedflag could extend this to a full help form, taking into account any descriptions passed viarfl::Description. Given:rfl::cli::usage<Config>("my_binary", /*detailed=*/true)returns the usage line followedby one line per argument, with the description where one was given:
I'd be happy to put up a PR for this if it seems useful.
Note: The proposal only covers manual generation, there's potential to auto handle a
--help/--usagein future but that's out of scope.