mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-30 12:43: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 {
|
class MyFormatter : public CLI::Formatter {
|
||||||
public:
|
public:
|
||||||
|
using Formatter::Formatter;
|
||||||
std::string make_option_opts(const CLI::Option *) const override { return " OPTION"; }
|
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;
|
CLI::App app;
|
||||||
app.set_help_all_flag("--help-all", "Show all help");
|
app.set_help_all_flag("--help-all", "Show all help");
|
||||||
|
|
||||||
MyFormatter fmt;
|
auto fmt = std::make_shared<MyFormatter>();
|
||||||
fmt.column_width(15);
|
fmt->column_width(15);
|
||||||
app.formatter(fmt);
|
app.formatter(fmt);
|
||||||
|
|
||||||
app.add_flag("--flag", "This is a flag");
|
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
|
/// A pointer to the help all flag if there is one INHERITABLE
|
||||||
Option *help_all_ptr_{nullptr};
|
Option *help_all_ptr_{nullptr};
|
||||||
|
|
||||||
/// This is the formatter for help printing. Default provided. INHERITABLE
|
/// This is the formatter for help printing. Default provided. INHERITABLE (same pointer)
|
||||||
std::function<std::string(const App *, std::string, AppFormatMode)> formatter_{Formatter()};
|
std::shared_ptr<FormatterBase> formatter_{new Formatter()};
|
||||||
|
|
||||||
/// The error message printing function INHERITABLE
|
/// The error message printing function INHERITABLE
|
||||||
std::function<std::string(const App *, const Error &e)> failure_message_ = FailureMessage::simple;
|
std::function<std::string(const App *, const Error &e)> failure_message_ = FailureMessage::simple;
|
||||||
@ -262,11 +262,17 @@ class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the help formatter
|
/// 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;
|
formatter_ = fmt;
|
||||||
return this;
|
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.
|
/// Check to see if this subcommand was parsed, true only if received on command line.
|
||||||
bool parsed() const { return parsed_; }
|
bool parsed() const { return parsed_; }
|
||||||
|
|
||||||
@ -1071,13 +1077,16 @@ class App {
|
|||||||
if(!selected_subcommands.empty())
|
if(!selected_subcommands.empty())
|
||||||
return selected_subcommands.at(0)->help(prev);
|
return selected_subcommands.at(0)->help(prev);
|
||||||
else
|
else
|
||||||
return formatter_(this, prev, mode);
|
return formatter_->make_help(this, prev, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Getters
|
/// @name Getters
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
|
/// Access the formatter
|
||||||
|
std::shared_ptr<FormatterBase> get_formatter() const { return formatter_; }
|
||||||
|
|
||||||
/// Get the app or subcommand description
|
/// Get the app or subcommand description
|
||||||
std::string get_description() const { return description_; }
|
std::string get_description() const { return description_; }
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ inline std::string Formatter::make_footer(const App *app) const {
|
|||||||
return "";
|
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
|
// This immediatly forwards to the make_expanded method. This is done this way so that subcommands can
|
||||||
// have overridden formatters
|
// have overridden formatters
|
||||||
|
@ -24,7 +24,12 @@ enum class AppFormatMode {
|
|||||||
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
|
/// @name Options
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
@ -40,9 +45,14 @@ class Formatter {
|
|||||||
///@{
|
///@{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Formatter() = default;
|
FormatterBase() = default;
|
||||||
Formatter(const Formatter &) = default;
|
FormatterBase(const FormatterBase &) = default;
|
||||||
Formatter(Formatter &&) = 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
|
/// @name Setters
|
||||||
///@{
|
///@{
|
||||||
@ -68,6 +78,30 @@ class Formatter {
|
|||||||
/// Get the current column width
|
/// Get the current column width
|
||||||
size_t get_column_width() const { return 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
|
/// @name Overridables
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
@ -102,7 +136,7 @@ class Formatter {
|
|||||||
virtual std::string make_usage(const App *app, std::string name) const;
|
virtual std::string make_usage(const App *app, std::string name) const;
|
||||||
|
|
||||||
/// This puts everything together
|
/// 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
|
/// @name Options
|
||||||
|
@ -11,9 +11,28 @@
|
|||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
using ::testing::Not;
|
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) {
|
TEST(Formatter, Nothing) {
|
||||||
CLI::App app{"My prog"};
|
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(
|
app.formatter(
|
||||||
[](const CLI::App *, std::string, CLI::AppFormatMode) { return std::string("This is really simple"); });
|
[](const CLI::App *, std::string, CLI::AppFormatMode) { return std::string("This is really simple"); });
|
||||||
|
|
||||||
@ -25,9 +44,9 @@ TEST(Formatter, Nothing) {
|
|||||||
TEST(Formatter, OptCustomize) {
|
TEST(Formatter, OptCustomize) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
CLI::Formatter optfmt;
|
auto optfmt = std::make_shared<CLI::Formatter>();
|
||||||
optfmt.column_width(25);
|
optfmt->column_width(25);
|
||||||
optfmt.label("REQUIRED", "(MUST HAVE)");
|
optfmt->label("REQUIRED", "(MUST HAVE)");
|
||||||
app.formatter(optfmt);
|
app.formatter(optfmt);
|
||||||
|
|
||||||
int v;
|
int v;
|
||||||
@ -44,13 +63,33 @@ TEST(Formatter, OptCustomize) {
|
|||||||
" --opt INT (MUST HAVE) Something\n");
|
" --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"};
|
CLI::App app{"My prog"};
|
||||||
app.add_subcommand("subcom1", "This");
|
app.add_subcommand("subcom1", "This");
|
||||||
|
|
||||||
CLI::Formatter appfmt;
|
auto appfmt = std::make_shared<CLI::Formatter>();
|
||||||
appfmt.column_width(20);
|
appfmt->column_width(20);
|
||||||
appfmt.label("Usage", "Run");
|
appfmt->label("Usage", "Run");
|
||||||
app.formatter(appfmt);
|
app.formatter(appfmt);
|
||||||
|
|
||||||
app.add_subcommand("subcom2", "This");
|
app.add_subcommand("subcom2", "This");
|
||||||
@ -66,6 +105,26 @@ TEST(Formatter, AptCustomize) {
|
|||||||
" subcom2 This\n");
|
" 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) {
|
TEST(Formatter, AllSub) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
CLI::App *sub = app.add_subcommand("subcom", "This");
|
CLI::App *sub = app.add_subcommand("subcom", "This");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user