1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-04-29 12:13:52 +00:00
CLI11/include/CLI/Formatter.hpp
Henry Fredrick Schreiner 952f2913e3 First attempt at formatter (app and option)
in progress: formatters

Getting closer

Working on apps

One test actually runs

All builds, added filter functions

Reverting a few behavours as needed

Repairs

All tests pass

Fixing error with adding help flag

Labels are simpler mappings, normalized setters

Adding help_all

Adding a few more tests

One more line tested

Adding one more check

Adding to readme

Simplify naming

Adding default constructors

Fixing spacing issues with subcommand all printout

Adding a couple of tests
2018-04-30 08:17:31 -04:00

191 lines
5.4 KiB
C++

#pragma once
// Distributed under the 3-Clause BSD License. See accompanying
// file LICENSE or https://github.com/CLIUtils/CLI11 for details.
#include <string>
#include <map>
#include "CLI/StringTools.hpp"
namespace CLI {
class Option;
class App;
/// This enum signifies what situation the option is beig printed in.
///
/// This is passed in as part of the built in formatter in App; it is
/// possible that a custom App formatter could avoid using it, however.
enum class OptionFormatMode {
Usage, //< In the program usage line
Positional, //< In the positionals
Optional //< In the normal optionals
};
/// This enum signifies the type of help requested
///
/// This is passed in by App; all user classes must accept this as
/// the second argument.
enum class AppFormatMode {
Normal, //< The normal, detailed help
All, //< A fully expanded help
Sub, //< Used when printed as part of expanded subcommand
};
/// This is an example formatter (and also the default formatter)
/// For option help.
class OptionFormatter {
protected:
/// @name Options
///@{
/// @brief The required help printout labels (user changeable)
/// Values are REQUIRED, NEEDS, EXCLUDES
std::map<std::string, std::string> labels_{{"REQUIRED", "(REQUIRED)"}};
/// The width of the first column
size_t column_width_{30};
///@}
/// @name Basic
///@{
public:
OptionFormatter() = default;
OptionFormatter(const OptionFormatter &) = default;
OptionFormatter(OptionFormatter &&) = default;
///@}
/// @name Setters
///@{
/// Set the "REQUIRED" label
void label(std::string key, std::string val) { labels_[key] = val; }
/// Set the column width
void column_width(size_t val) { column_width_ = val; }
///@}
/// @name Getters
///@{
/// Get the current value of a name (REQUIRED, etc.)
std::string get_label(std::string key) const {
if(labels_.find(key) == labels_.end())
return key;
else
return labels_.at(key);
}
/// Get the current column width
size_t get_column_width() const { return column_width_; }
///@}
/// @name Overridables
///@{
/// @brief This is the name part of an option, Default: left column
virtual std::string make_name(const Option *, OptionFormatMode) const;
/// @brief This is the options part of the name, Default: combined into left column
virtual std::string make_opts(const Option *) const;
/// @brief This is the description. Default: Right column, on new line if left column too large
virtual std::string make_desc(const Option *) const;
/// @brief This is used to print the name on the USAGE line (by App formatter)
virtual std::string make_usage(const Option *opt) const;
/// @brief This is the standard help combiner that does the "default" thing.
virtual std::string operator()(const Option *opt, OptionFormatMode mode) const {
std::stringstream out;
if(mode == OptionFormatMode::Usage)
out << make_usage(opt);
else
detail::format_help(out, make_name(opt, mode) + make_opts(opt), make_desc(opt), column_width_);
return out.str();
}
///@}
};
class AppFormatter {
/// @name Options
///@{
/// The width of the first column
size_t column_width_{30};
/// @brief The required help printout labels (user changeable)
/// Values are Needs, Excludes, etc.
std::map<std::string, std::string> labels_;
///@}
/// @name Basic
///@{
public:
AppFormatter() = default;
AppFormatter(const AppFormatter &) = default;
AppFormatter(AppFormatter &&) = default;
///@}
/// @name Setters
///@{
/// Set the "REQUIRED" label
void label(std::string key, std::string val) { labels_[key] = val; }
/// Set the column width
void column_width(size_t val) { column_width_ = val; }
///@}
/// @name Getters
///@{
/// Get the current value of a name (REQUIRED, etc.)
std::string get_label(std::string key) const {
if(labels_.find(key) == labels_.end())
return key;
else
return labels_.at(key);
}
/// Get the current column width
size_t get_column_width() const { return column_width_; }
/// @name Overridables
///@{
/// This prints out a group of options
virtual std::string make_group(std::string group, std::vector<const Option *> opts, OptionFormatMode mode) const;
/// This prints out all the groups of options
virtual std::string make_groups(const App *app, AppFormatMode mode) const;
/// This prints out all the subcommands
virtual std::string make_subcommands(const App *app, AppFormatMode mode) const;
/// This prints out a subcommand
virtual std::string make_subcommand(const App *sub) const;
/// This prints out a subcommand in help-all
virtual std::string make_expanded(const App *sub) const;
/// This prints out all the groups of options
virtual std::string make_footer(const App *app) const;
/// This displays the description line
virtual std::string make_description(const App *app) const;
/// This displays the usage line
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;
///@}
};
} // namespace CLI