mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Adding access to current formatter, using shared pointer to link all formatters
This commit is contained in:
parent
aac957507d
commit
0d9a33d4ca
@ -2,6 +2,7 @@
|
||||
|
||||
class MyFormatter : public CLI::Formatter {
|
||||
public:
|
||||
using Formatter::Formatter;
|
||||
std::string make_option_opts(const CLI::Option *) const override { return " OPTION"; }
|
||||
};
|
||||
|
||||
@ -9,8 +10,8 @@ int main(int argc, char **argv) {
|
||||
CLI::App app;
|
||||
app.set_help_all_flag("--help-all", "Show all help");
|
||||
|
||||
MyFormatter fmt;
|
||||
fmt.column_width(15);
|
||||
auto fmt = std::make_shared<MyFormatter>();
|
||||
fmt->column_width(15);
|
||||
app.formatter(fmt);
|
||||
|
||||
app.add_flag("--flag", "This is a flag");
|
||||
|
@ -106,8 +106,8 @@ class App {
|
||||
/// A pointer to the help all flag if there is one INHERITABLE
|
||||
Option *help_all_ptr_{nullptr};
|
||||
|
||||
/// This is the formatter for help printing. Default provided. INHERITABLE
|
||||
std::function<std::string(const App *, std::string, AppFormatMode)> formatter_{Formatter()};
|
||||
/// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
|
||||
std::shared_ptr<FormatterBase> formatter_{new Formatter()};
|
||||
|
||||
/// The error message printing function INHERITABLE
|
||||
std::function<std::string(const App *, const Error &e)> failure_message_ = FailureMessage::simple;
|
||||
@ -262,11 +262,17 @@ class App {
|
||||
}
|
||||
|
||||
/// Set the help formatter
|
||||
App *formatter(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
|
||||
App *formatter(std::shared_ptr<FormatterBase> fmt) {
|
||||
formatter_ = fmt;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Set the help formatter
|
||||
App *formatter(std::function<std::string(const App *, std::string, AppFormatMode)> fmt) {
|
||||
formatter_ = std::make_shared<FormatterLambda>(fmt);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Check to see if this subcommand was parsed, true only if received on command line.
|
||||
bool parsed() const { return parsed_; }
|
||||
|
||||
@ -1071,13 +1077,16 @@ class App {
|
||||
if(!selected_subcommands.empty())
|
||||
return selected_subcommands.at(0)->help(prev);
|
||||
else
|
||||
return formatter_(this, prev, mode);
|
||||
return formatter_->make_help(this, prev, mode);
|
||||
}
|
||||
|
||||
///@}
|
||||
/// @name Getters
|
||||
///@{
|
||||
|
||||
/// Access the formatter
|
||||
std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
|
||||
|
||||
/// Get the app or subcommand description
|
||||
std::string get_description() const { return description_; }
|
||||
|
||||
|
@ -113,7 +113,7 @@ inline std::string Formatter::make_footer(const App *app) const {
|
||||
return "";
|
||||
}
|
||||
|
||||
inline std::string Formatter::operator()(const App *app, std::string name, AppFormatMode mode) const {
|
||||
inline std::string Formatter::make_help(const App *app, std::string name, AppFormatMode mode) const {
|
||||
|
||||
// This immediatly forwards to the make_expanded method. This is done this way so that subcommands can
|
||||
// have overridden formatters
|
||||
|
@ -21,10 +21,15 @@ class App;
|
||||
enum class AppFormatMode {
|
||||
Normal, //< The normal, detailed help
|
||||
All, //< A fully expanded help
|
||||
Sub, //< Used when printed as part of expanded subcommand
|
||||
Sub, //< Used when printed as part of expanded subcommand
|
||||
};
|
||||
|
||||
class Formatter {
|
||||
/// This is the minimum requirements to run a formatter.
|
||||
///
|
||||
/// A user can subclass this is if they do not care at all
|
||||
/// about the structure in CLI::Formatter.
|
||||
class FormatterBase {
|
||||
protected:
|
||||
/// @name Options
|
||||
///@{
|
||||
|
||||
@ -40,9 +45,14 @@ class Formatter {
|
||||
///@{
|
||||
|
||||
public:
|
||||
Formatter() = default;
|
||||
Formatter(const Formatter &) = default;
|
||||
Formatter(Formatter &&) = default;
|
||||
FormatterBase() = default;
|
||||
FormatterBase(const FormatterBase &) = default;
|
||||
FormatterBase(FormatterBase &&) = default;
|
||||
virtual ~FormatterBase() = default;
|
||||
|
||||
/// This is the key method that puts together help
|
||||
virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0;
|
||||
|
||||
///@}
|
||||
/// @name Setters
|
||||
///@{
|
||||
@ -68,6 +78,30 @@ class Formatter {
|
||||
/// Get the current column width
|
||||
size_t get_column_width() const { return column_width_; }
|
||||
|
||||
///@}
|
||||
};
|
||||
|
||||
/// This is a specialty override for lambda functions
|
||||
class FormatterLambda final : public FormatterBase {
|
||||
using funct_t = std::function<std::string(const App *, std::string, AppFormatMode)>;
|
||||
|
||||
funct_t lambda_;
|
||||
|
||||
public:
|
||||
explicit FormatterLambda(funct_t funct) : lambda_(funct) {}
|
||||
|
||||
/// This will simply call the lambda function
|
||||
std::string make_help(const App *app, std::string name, AppFormatMode mode) const override {
|
||||
return lambda_(app, name, mode);
|
||||
}
|
||||
};
|
||||
|
||||
class Formatter : public FormatterBase {
|
||||
public:
|
||||
Formatter() = default;
|
||||
Formatter(const Formatter &) = default;
|
||||
Formatter(Formatter &&) = default;
|
||||
|
||||
/// @name Overridables
|
||||
///@{
|
||||
|
||||
@ -102,7 +136,7 @@ class Formatter {
|
||||
virtual std::string make_usage(const App *app, std::string name) const;
|
||||
|
||||
/// This puts everything together
|
||||
virtual std::string operator()(const App *, std::string, AppFormatMode) const;
|
||||
std::string make_help(const App *, std::string, AppFormatMode) const override;
|
||||
|
||||
///@}
|
||||
/// @name Options
|
||||
|
@ -11,9 +11,28 @@
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Not;
|
||||
|
||||
class SimpleFormatter : public CLI::FormatterBase {
|
||||
public:
|
||||
SimpleFormatter() : FormatterBase() {}
|
||||
|
||||
std::string make_help(const CLI::App *, std::string, CLI::AppFormatMode) const override {
|
||||
return "This is really simple";
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Formatter, Nothing) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
app.formatter(std::make_shared<SimpleFormatter>());
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
EXPECT_EQ(help, "This is really simple");
|
||||
}
|
||||
|
||||
TEST(Formatter, NothingLambda) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
app.formatter(
|
||||
[](const CLI::App *, std::string, CLI::AppFormatMode) { return std::string("This is really simple"); });
|
||||
|
||||
@ -25,9 +44,9 @@ TEST(Formatter, Nothing) {
|
||||
TEST(Formatter, OptCustomize) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
CLI::Formatter optfmt;
|
||||
optfmt.column_width(25);
|
||||
optfmt.label("REQUIRED", "(MUST HAVE)");
|
||||
auto optfmt = std::make_shared<CLI::Formatter>();
|
||||
optfmt->column_width(25);
|
||||
optfmt->label("REQUIRED", "(MUST HAVE)");
|
||||
app.formatter(optfmt);
|
||||
|
||||
int v;
|
||||
@ -44,13 +63,33 @@ TEST(Formatter, OptCustomize) {
|
||||
" --opt INT (MUST HAVE) Something\n");
|
||||
}
|
||||
|
||||
TEST(Formatter, AptCustomize) {
|
||||
TEST(Formatter, OptCustomizeSimple) {
|
||||
CLI::App app{"My prog"};
|
||||
|
||||
app.get_formatter()->column_width(25);
|
||||
app.get_formatter()->label("REQUIRED", "(MUST HAVE)");
|
||||
|
||||
int v;
|
||||
app.add_option("--opt", v, "Something")->required();
|
||||
|
||||
std::string help = app.help();
|
||||
|
||||
EXPECT_THAT(help, HasSubstr("(MUST HAVE)"));
|
||||
EXPECT_EQ(help,
|
||||
"My prog\n"
|
||||
"Usage: [OPTIONS]\n\n"
|
||||
"Options:\n"
|
||||
" -h,--help Print this help message and exit\n"
|
||||
" --opt INT (MUST HAVE) Something\n");
|
||||
}
|
||||
|
||||
TEST(Formatter, AppCustomize) {
|
||||
CLI::App app{"My prog"};
|
||||
app.add_subcommand("subcom1", "This");
|
||||
|
||||
CLI::Formatter appfmt;
|
||||
appfmt.column_width(20);
|
||||
appfmt.label("Usage", "Run");
|
||||
auto appfmt = std::make_shared<CLI::Formatter>();
|
||||
appfmt->column_width(20);
|
||||
appfmt->label("Usage", "Run");
|
||||
app.formatter(appfmt);
|
||||
|
||||
app.add_subcommand("subcom2", "This");
|
||||
@ -66,6 +105,26 @@ TEST(Formatter, AptCustomize) {
|
||||
" subcom2 This\n");
|
||||
}
|
||||
|
||||
TEST(Formatter, AppCustomizeSimple) {
|
||||
CLI::App app{"My prog"};
|
||||
app.add_subcommand("subcom1", "This");
|
||||
|
||||
app.get_formatter()->column_width(20);
|
||||
app.get_formatter()->label("Usage", "Run");
|
||||
|
||||
app.add_subcommand("subcom2", "This");
|
||||
|
||||
std::string help = app.help();
|
||||
EXPECT_EQ(help,
|
||||
"My prog\n"
|
||||
"Run: [OPTIONS] [SUBCOMMAND]\n\n"
|
||||
"Options:\n"
|
||||
" -h,--help Print this help message and exit\n\n"
|
||||
"Subcommands:\n"
|
||||
" subcom1 This\n"
|
||||
" subcom2 This\n");
|
||||
}
|
||||
|
||||
TEST(Formatter, AllSub) {
|
||||
CLI::App app{"My prog"};
|
||||
CLI::App *sub = app.add_subcommand("subcom", "This");
|
||||
|
Loading…
x
Reference in New Issue
Block a user