OpenFPGA/libs/EXTERNAL/libargparse/src/argparse_formatter.cpp

249 lines
7.8 KiB
C++
Raw Normal View History

#include <cassert>
#include "argparse_formatter.hpp"
#include "argparse_util.hpp"
#include "argparse.hpp"
namespace argparse {
constexpr size_t OPTION_HELP_SLACK = 2;
std::string INDENT = " ";
std::string USAGE_PREFIX = "usage: ";
std::string long_option_str(const Argument& argument);
std::string short_option_str(const Argument& argument);
std::string determine_metavar(const Argument& argument);
/*
* DefaultFormatter
*/
DefaultFormatter::DefaultFormatter(size_t option_name_width, size_t total_width)
: option_name_width_(option_name_width)
, total_width_(total_width)
{}
void DefaultFormatter::set_parser(ArgumentParser* parser) {
parser_ = parser;
}
std::string DefaultFormatter::format_usage() const {
if (!parser_) throw ArgParseError("parser not initialized in help formatter");
std::stringstream ss;
ss << USAGE_PREFIX << parser_->prog();
int num_unshown_options = 0;
for (const auto& group : parser_->argument_groups()) {
auto args = group.arguments();
for(const auto& arg : args) {
if(arg->show_in() != ShowIn::USAGE_AND_HELP) {
num_unshown_options++;
continue;
}
ss << " ";
if (!arg->required()) {
ss << "[";
}
auto short_opt = short_option_str(*arg);
if (!short_opt.empty()) {
ss << short_opt;
} else {
ss << long_option_str(*arg);
}
if (!arg->required()) {
ss << "]";
}
}
}
if (num_unshown_options > 0) {
ss << " [OTHER_OPTIONS ...]";
}
size_t prefix_len = USAGE_PREFIX.size();
std::stringstream wrapped_ss;
bool first = true;
for(const auto& line : wrap_width(ss.str(), total_width_ - prefix_len, {" [", " -"})) {
if(!first) {
//pass
wrapped_ss << std::string(prefix_len, ' ');
}
wrapped_ss << line;
first = false;
}
wrapped_ss << "\n";
return wrapped_ss.str();
}
std::string DefaultFormatter::format_description() const {
if (!parser_) throw ArgParseError("parser not initialized in help formatter");
std::stringstream ss;
ss << "\n";
for(auto& line : wrap_width(parser_->description(), total_width_)) {
ss << line;
}
ss << "\n";
return ss.str();
}
std::string DefaultFormatter::format_arguments() const {
if (!parser_) throw ArgParseError("parser not initialized in help formatter");
std::stringstream ss;
for (const auto& group : parser_->argument_groups()) {
auto args = group.arguments();
if (args.size() > 0) {
ss << "\n";
ss << group.name() << ":" << "\n";
for (const auto& arg : args) {
std::stringstream arg_ss;
arg_ss << std::boolalpha;
auto long_opt_descr = long_option_str(*arg);
auto short_opt_descr = short_option_str(*arg);
//name/option
arg_ss << INDENT;
if (!short_opt_descr.empty()) {
arg_ss << short_opt_descr;
}
if (!long_opt_descr.empty()) {
if (!short_opt_descr.empty()) {
arg_ss << ", ";
}
arg_ss << long_opt_descr;
}
size_t pos = arg_ss.str().size();
if (pos + OPTION_HELP_SLACK > option_name_width_) {
//If the option name is too long, wrap the help
//around to a new line
arg_ss << "\n";
pos = 0;
}
//Argument help
auto help_lines = wrap_width(arg->help(), total_width_ - option_name_width_);
for (auto& line : help_lines) {
//Pad out the help
assert(pos <= option_name_width_);
arg_ss << std::string(option_name_width_ - pos, ' ');
//Print a wrapped line
arg_ss << line;
pos = 0;
}
//Default
if (!arg->default_value().empty()) {
if(!arg->help().empty()) {
arg_ss << " ";
}
arg_ss << "(Default: " << arg->default_value() << ")";
}
arg_ss << "\n";
ss << arg_ss.str();
}
if (!group.epilog().empty()) {
ss << "\n";
auto epilog_lines = wrap_width(group.epilog(), total_width_ - INDENT.size());
for (auto& line : epilog_lines) {
ss << INDENT << line;
}
ss << "\n";
}
}
}
return ss.str();
}
std::string DefaultFormatter::format_epilog() const {
if (!parser_) throw ArgParseError("parser not initialized in help formatter");
std::stringstream ss;
ss << "\n";
for(auto& line : wrap_width(parser_->epilog(), total_width_)) {
ss << line;
}
ss << "\n";
return ss.str();
}
std::string DefaultFormatter::format_version() const {
if (!parser_) throw ArgParseError("parser not initialized in help formatter");
return parser_->version() + "\n";
}
/*
* Utilities
*/
std::string long_option_str(const Argument& argument) {
auto long_opt = argument.long_option();
if(argument.nargs() != '0' && !argument.positional()) {
long_opt += + " " + determine_metavar(argument);
}
return long_opt;
}
std::string short_option_str(const Argument& argument) {
auto short_opt = argument.short_option();
if(!short_opt.empty()) {
if(argument.nargs() != '0' && !argument.positional()) {
short_opt += " " + determine_metavar(argument);
}
return short_opt;
} else {
return "";
}
}
std::string determine_metavar(const Argument& arg) {
std::string base_metavar = arg.metavar();
if (!arg.choices().empty()) {
//We allow choices to override the default metavar
std::stringstream choices_ss;
choices_ss << "{";
bool first = true;
for(auto choice : arg.choices()) {
if (!first) {
choices_ss << ", ";
}
choices_ss << choice;
first = false;
}
choices_ss << "}";
base_metavar = choices_ss.str();
}
std::string metavar;
if (arg.nargs() == '0' || arg.positional()) {
//empty
metavar = "";
} else if (arg.nargs() == '1') {
metavar = base_metavar;
} else if (arg.nargs() == '?') {
metavar = "[" + base_metavar + "]";
} else if (arg.nargs() == '+') {
metavar = base_metavar + " [" + base_metavar + " ...]";
} else if (arg.nargs() == '*') {
metavar = "[" + base_metavar + " [" + base_metavar + " ...]]";
} else {
assert(false);
}
return metavar;
}
} //namespace