1 #ifndef OOKII_USAGE_WRITER_H_
4 #define OOKII_USAGE_WRITER_H_
14 template<
typename CharType,
typename Traits,
typename Alloc>
15 class basic_command_line_parser;
17 template<
typename CharType,
typename Traits,
typename Alloc>
18 class basic_command_manager;
20 template<
typename CharType,
typename Traits,
typename Alloc>
97 template<
typename CharType,
typename Traits = std::
char_traits<CharType>,
typename Alloc = std::allocator<CharType>>
102 std::optional<line_wrapping_stream_type> _owned_output;
103 std::optional<line_wrapping_stream_type> _owned_error;
148 error{*_owned_error},
379 _command_manager = &manager;
380 write_usage_internal(manager.
locale());
386 auto support = enable_error_color();
398 error << std::endl << std::endl;
448 output << description << std::endl << std::endl;
458 for (
const auto &arg :
parser().arguments())
467 if (arg.is_required())
502 output <<
" " << command_name;
527 output << c_optionalStart;
559 : std::optional<CharType>(
parser().argument_value_separator());
622 output << c_optionalStart;
642 output << '<' << value_description << '>
';
650 virtual void write_multi_value_suffix()
662 virtual void write_argument_descriptions()
664 auto indent = argument_description_indent;
665 if (parser().mode() == parsing_mode::long_short)
667 // For long/short mode, increase the indentation by the size of the short argument.
668 indent += parser().prefixes()[0].length() + name_separator.length() + 1;
671 output << set_indent(indent);
673 for_each_argument_in_description_order([this, &first](const auto &arg)
677 write_argument_description_list_header();
681 write_argument_description(arg);
694 virtual void write_argument_description_list_header()
696 // Intentionally blank.
709 virtual void write_argument_description(const argument_type &arg)
711 write_argument_description_header(arg);
712 write_argument_description_body(arg);
714 if (blank_line_after_description)
733 virtual void write_argument_description_header(const argument_type &arg)
735 output << reset_indent;
736 write_spacing(argument_description_indent / 2);
737 const auto &short_prefix = parser().prefixes()[0];
738 const auto &prefix = parser().long_prefix().length() == 0
740 : parser().long_prefix();
742 set_color(argument_description_color);
743 if (parser().mode() == parsing_mode::long_short)
745 if (arg.has_short_name())
747 auto short_name = arg.short_name();
748 write_argument_name_for_description(string_view_type{&short_name, 1}, short_prefix);
749 if (arg.has_long_name())
751 output << name_separator;
756 write_spacing(short_prefix.length() + name_separator.length() + 1);
759 if (arg.has_long_name())
761 write_argument_name_for_description(arg.name(), prefix);
766 write_argument_name_for_description(arg.name(), prefix);
772 write_switch_value_description(arg.value_description());
776 write_value_description_for_description(arg.value_description());
779 if (include_aliases_in_description)
781 write_aliases(arg.aliases(), arg.short_aliases(), prefix, short_prefix);
784 set_color(color_reset);
799 virtual void write_argument_description_body(const argument_type &arg)
801 if (!arg.description().empty())
803 write_argument_description(arg.description());
806 if (include_default_value_in_description && arg.has_default_value())
808 write_default_value(arg);
823 virtual void write_argument_name_for_description(string_view_type name, string_view_type prefix)
825 output << prefix << name;
838 virtual void write_value_description_for_description(string_view_type value_description)
840 output << '<
' << value_description << '>
';
854 virtual void write_switch_value_description(string_view_type value_description)
856 output << c_optionalStart;
857 write_value_description_for_description(value_description);
858 output << c_optionalEnd;
875 virtual void write_aliases(const std::vector<string_type> &aliases, const std::vector<CharType> &short_aliases,
876 string_view_type prefix, string_view_type short_prefix)
879 for (const auto &alias : short_aliases)
888 output << name_separator;
891 write_alias(string_view_type{&alias, 1}, short_prefix);
894 for (const auto &alias : aliases)
903 output << name_separator;
906 write_alias(alias, prefix);
923 virtual void write_alias(string_view_type alias, string_view_type prefix)
925 write_argument_name_for_description(alias, prefix);
936 virtual void write_argument_description(string_view_type description)
938 output << description;
951 virtual void write_default_value(const argument_type &arg)
953 output << " Default value: ";
954 arg.write_default_value(output);
968 virtual void write_more_info_message()
970 auto arg = parser().get_help_argument();
973 output << "Run '" << parser().command_name() << " " << arg->name_with_prefix(parser()) << "' for more information."
988 virtual void write_command_list_usage_core()
990 if (!command_manager().description().empty())
992 write_application_description(command_manager().description());
995 output << reset_indent << set_indent(syntax_indent);
996 write_command_list_usage_syntax();
997 output << reset_indent << set_indent(0);
998 write_available_commands_header();
999 write_command_descriptions();
1000 output << reset_indent << set_indent(0);
1001 write_command_list_usage_footer();
1011 virtual void write_command_list_usage_syntax()
1013 write_usage_syntax_prefix(command_manager().application_name());
1014 output << " <command> [arguments]" << std::endl;
1015 if (blank_line_after_syntax)
1017 output << std::endl;
1028 virtual void write_available_commands_header()
1030 output << "The following commands are available:" << std::endl << std::endl;
1039 virtual void write_command_descriptions()
1041 output << set_indent(command_description_indent);
1042 for (const auto &command : command_manager().commands())
1044 write_command_description(command);
1058 virtual void write_command_description(const command_info_type &command)
1060 write_command_description_header(command);
1061 write_command_description_body(command);
1063 if (blank_line_after_command_description)
1065 output << std::endl;
1080 virtual void write_command_description_header(const command_info_type &command)
1082 output << reset_indent;
1083 write_spacing(command_description_indent / 2);
1084 set_color(command_description_color);
1085 write_command_name(command.name());
1086 set_color(color_reset);
1087 output << std::endl;
1099 virtual void write_command_description_body(const command_info_type &command)
1101 if (!command.description().empty())
1103 write_command_description(command.description());
1104 output << std::endl;
1116 virtual void write_command_name(string_view_type name)
1129 virtual void write_command_description(string_view_type description)
1131 output << description;
1138 virtual void write_command_list_usage_footer()
1140 if (!command_manager().common_help_argument().empty())
1142 // If there wasn't already a blank line after the last
command, add one now.
1157 for (
size_t i = 0; i < count; ++i)
1178 return *_command_manager;
1187 return _use_color && *_use_color;
1204 template<
typename Func>
1214 for (
const auto &arg : parser().arguments())
1216 if (check_filter(arg))
1225 std::vector<const argument_type *> arguments;
1226 arguments.reserve(parser().argument_count());
1227 auto source = parser().arguments();
1228 std::transform(source.begin(), source.end(), std::back_inserter(arguments), [](
const auto &arg) { return &arg; });
1229 std::sort(arguments.begin(), arguments.end(), get_sort_function());
1230 for (
const auto &arg : arguments)
1232 if (check_filter(*arg))
1241 bool check_filter(
const argument_type &arg)
const
1243 switch (argument_description_list_filter)
1246 return has_information(arg);
1249 return !arg.description().empty();
1259 bool has_information(
const argument_type &arg)
const
1261 if (!arg.description().empty())
1266 if (use_abbreviated_syntax && arg.position())
1273 if (arg.has_long_name())
1278 else if (arg.has_short_name())
1283 if (include_aliases_in_description && (!arg.aliases().empty() || !arg.short_aliases().empty()))
1288 if (include_default_value_in_description && arg.has_default_value())
1296 std::function<bool(
const argument_type *,
const argument_type *)> get_sort_function()
const
1298 auto comparer = parser().argument_comparer();
1299 switch (argument_description_list_order)
1302 return [comparer](
const argument_type *left,
const argument_type *right)
1304 return comparer(left->name(), right->name());
1308 return [comparer](
const argument_type *left,
const argument_type *right)
1310 return comparer(right->name(), left->name());
1314 return [comparer](
const argument_type *left,
const argument_type *right)
1316 return comparer(left->short_or_long_name(), right->short_or_long_name());
1320 return [comparer](
const argument_type *left,
const argument_type *right)
1322 return comparer(right->short_or_long_name(), left->short_or_long_name());
1326 throw std::logic_error(
"Invalid sort mode.");
1332 auto old_output_loc =
output.imbue(loc);
1333 std::optional<std::locale> old_error_loc;
1334 details::scope_exit revert{[
this, &old_output_loc, &old_error_loc]()
1339 error.imbue(*old_error_loc);
1342 output.imbue(old_output_loc);
1346 if (std::addressof(output) != std::addressof(error))
1348 old_error_loc =
error.imbue(loc);
1351 auto color = enable_color();
1353 if (_parser !=
nullptr)
1355 write_parser_usage_core(request);
1359 write_command_list_usage_core();
1363 vt::virtual_terminal_support enable_color()
1368 _use_color = support.is_supported();
1375 vt::virtual_terminal_support enable_error_color()
1385 const parser_type *_parser{};
1386 const command_manager_type *_command_manager{};
1387 std::optional<bool> _use_color;
1389 static constexpr
char c_optionalStart =
'[';
1390 static constexpr
char c_optionalEnd =
']';
Parses command line arguments into strongly-typed values.
Definition: command_line_parser.h:106
parsing_mode mode() const noexcept
Gets the parsing mode used by this parser.
Definition: command_line_parser.h:243
const std::vector< string_type > & prefixes() const noexcept
Gets a list of all the argument name prefixes accepted by the parser.
Definition: command_line_parser.h:293
const std::locale & locale() const noexcept
Gets the locale used to parse argument values and to format strings.
Definition: command_line_parser.h:311
const string_type & long_prefix() const noexcept
Gets the long argument prefix.
Definition: command_line_parser.h:303
bool allow_white_space_separator() const noexcept
Indicates whether argument names and values can be separated by white space.
Definition: command_line_parser.h:267
Manages registration, creation and invocation of subcommands for an application.
Definition: subcommand.h:313
basic_command_manager & common_help_argument(string_type name_with_prefix)
Sets the name of a help argument, including prefix, that is used by all subcommands.
Definition: subcommand.h:391
const string_type & application_name() const noexcept
Gets the name of the application containing the command.
Definition: subcommand.h:513
const std::locale & locale() const noexcept
Gets the locale used to parse argument values and to format strings.
Definition: subcommand.h:519
Output stream that wraps lines on white-space characters at the specified line length,...
Definition: line_wrapping_stream.h:749
static basic_line_wrapping_ostream for_cout(short default_width=80)
Creates a basic_line_wrapping_ostream that writes to the standard output stream, using the console wi...
Definition: line_wrapping_stream.h:815
static basic_line_wrapping_ostream for_cerr(short default_width=80)
Creates a basic_line_wrapping_ostream that writes to the standard error stream, using the console wid...
Definition: line_wrapping_stream.h:825
Creates usage help for the basic_command_line_parser and basic_command_manager classes.
Definition: usage_writer.h:99
basic_usage_writer(stream_type &output, stream_type &error, bool use_color=false)
Initializes a new instance of the basic_usage_writer class with the specified output and error stream...
Definition: usage_writer.h:174
bool use_abbreviated_syntax
Indicates whether to list only positional arguments in the usage syntax.
Definition: usage_writer.h:257
const char * error_color
The color applied by the write_error() method.
Definition: usage_writer.h:351
stream_type & output
The stream used to write usage help to.
Definition: usage_writer.h:186
virtual void write_positional_argument_name(string_view_type name, string_view_type prefix, std::optional< CharType > separator)
Writes the name of a positional argument.
Definition: usage_writer.h:620
virtual void write_usage_syntax_prefix(string_view_type command_name)
Writes the prefix for the usage syntax, including the executable name and, for subcommands,...
Definition: usage_writer.h:497
bool blank_line_after_syntax
Indicates whether to add a blank line after the usage syntax.
Definition: usage_writer.h:262
basic_usage_writer(std::optional< bool > use_color={})
Initializes a new instance of the basic_usage_writer class.
Definition: usage_writer.h:144
bool include_aliases_in_description
Indicates whether to include the aliases of arguments in the description.
Definition: usage_writer.h:247
stream_type & error
The stream used to write errors to.
Definition: usage_writer.h:189
virtual void write_parser_usage(const parser_type &parser, usage_help_request request=usage_help_request::full)
Creates usage help for the specified parser.
Definition: usage_writer.h:368
virtual void write_value_description(string_view_type value_description)
Writes the value description of an argument.
Definition: usage_writer.h:640
std::basic_ostream< CharType, Traits > stream_type
The concrete stream type used.
Definition: usage_writer.h:126
virtual void write_argument_descriptions()
Writes the list of argument descriptions.
Definition: usage_writer.h:662
virtual void write_command_list_usage(const command_manager_type &manager)
Creates usage help for the specified command manager.
Definition: usage_writer.h:377
virtual void write_spacing(size_t count)
Writes the specified amount of spaces.
Definition: usage_writer.h:1155
size_t argument_description_indent
The level of indentation to use when writing argument descriptions.
Definition: usage_writer.h:210
void for_each_argument_in_description_order(Func f) const
Iterates over the arguments in the order set by the argument_description_list_order field,...
Definition: usage_writer.h:1205
bool include_application_description
Indicates whether to include the application description in the usage help.
Definition: usage_writer.h:237
virtual void write_parser_usage_syntax()
Writes the usage syntax for the application or subcommand.
Definition: usage_writer.h:454
virtual void write_abbreviated_remaining_arguments()
Writes the string used to indicate there are more arguments if the usage syntax was abbreviated.
Definition: usage_writer.h:512
description_list_filter_mode argument_description_list_filter
A value that indicates which arguments should be included in the list of argument descriptions.
Definition: usage_writer.h:216
const command_manager_type & command_manager() const
Gets the basic_command_manager that usage is being written for.
Definition: usage_writer.h:1176
bool blank_line_after_description
Indicates whether to add a blank line after each argument's description.
Definition: usage_writer.h:272
std::basic_string_view< CharType, Traits > string_view_type
The concrete string_view type used.
Definition: usage_writer.h:124
virtual void write_more_info_message()
Writes a message telling to user how to get more detailed help.
Definition: usage_writer.h:968
void write_error(string_view_type message)
Writes an error message to the error stream, using color if enabled.
Definition: usage_writer.h:384
description_list_sort_mode argument_description_list_order
A value that indicates the order of the arguments in the list of argument descriptions.
Definition: usage_writer.h:222
const char * usage_prefix_color
The color applied by the base implementation of the write_usage_syntax_prefix method.
Definition: usage_writer.h:306
virtual void write_argument_syntax(const argument_type &arg)
Writes the string used to indicate there are more arguments if the usage syntax was abbreviated.
Definition: usage_writer.h:539
string_type name_separator
The separator to use between names of arguments and commands.
Definition: usage_writer.h:277
bool use_white_space_value_separator
Indicates whether to use white space as the argument name separator in the usage syntax.
Definition: usage_writer.h:232
virtual void write_multi_value_suffix()
Writes a suffix that indicates an argument is a multi-value argument.
Definition: usage_writer.h:650
bool use_short_names_for_syntax
When using parsing_mode::long_short, use short names in the usage syntax.
Definition: usage_writer.h:267
virtual void write_optional_argument_syntax(const argument_type &arg)
Writes the string used to indicate there are more arguments if the usage syntax was abbreviated.
Definition: usage_writer.h:525
std::basic_string< CharType, Traits, Alloc > string_type
The concrete string type used.
Definition: usage_writer.h:122
const char * color_reset
The sequence used to reset color applied a usage help element.
Definition: usage_writer.h:362
virtual void write_argument_name(string_view_type name, string_view_type prefix)
Writes the name of an argument.
Definition: usage_writer.h:603
bool use_color() const
Gets a value that indicates whether color virtual terminal sequences can be used in the output.
Definition: usage_writer.h:1185
int command_description_indent
The level of indentation to use when writing the command descriptions.
Definition: usage_writer.h:284
bool include_default_value_in_description
Indicates whether to include the default value of arguments in the description.
Definition: usage_writer.h:242
virtual void write_parser_usage_core(usage_help_request request)
Creates the usage help for a basic_command_line_parser instance.
Definition: usage_writer.h:414
const char * command_description_color
The color applied by the base implementation of the write_command_description_header() method.
Definition: usage_writer.h:338
size_t syntax_indent
The level of indentation to use when writing the usage syntax.
Definition: usage_writer.h:203
const parser_type & parser() const
Gets the basic_command_line_parser that usage is being written for.
Definition: usage_writer.h:1167
virtual void write_application_description(string_view_type description)
Writes the application description, or command description in case of a subcommand.
Definition: usage_writer.h:445
size_t application_description_indent
The level of indentation to use when writing the application description.
Definition: usage_writer.h:196
bool blank_line_after_command_description
Indicates whether to add a blank line after each command's description.
Definition: usage_writer.h:289
const char * argument_description_color
The color applied by the base implementation of the write_argument_description_header() method.
Definition: usage_writer.h:322
void set_color(const char *color)
Writes the specified color virtual terminal sequence, if color is enabled.
Definition: usage_writer.h:1192
basic_usage_writer(stream_type &output, bool use_color=false)
Initializes a new instance of the basic_usage_writer class with the specified stream.
Definition: usage_writer.h:160
Provides information about a subcommand.
Definition: subcommand.h:143
Abstract base class for regular and multi-value arguments.
Definition: command_line_argument.h:108
bool has_long_name() const noexcept
Gets a value that indicates whether the argument has a long name.
Definition: command_line_argument.h:160
CharType short_name() const noexcept
Gets the short name of the argument, or a NULL character if it doesn't have one.
Definition: command_line_argument.h:144
virtual bool is_multi_value() const noexcept
Gets a value that indicates whether the argument can be provided more than once, collecting all the s...
Definition: command_line_argument.h:305
virtual bool is_switch() const noexcept=0
Gets a value that indicates whether the argument is a switch, which means it can be supplied without ...
const string_type & value_description() const noexcept
Gets the value description for the argument.
Definition: command_line_argument.h:227
std::optional< size_t > position() const noexcept
Gets the position of the argument.
Definition: command_line_argument.h:254
const string_type & name() const noexcept
Gets the name of the argument.
Definition: command_line_argument.h:133
bool has_short_name() const noexcept
Gets a value that indicates whether the argument has a short name.
Definition: command_line_argument.h:152
static virtual_terminal_support enable_color(standard_stream stream)
Enables color support using virtual terminal sequences for the console attached to the specified stre...
Definition: vt_helper.h:337
Provides an output stream buffer, and associated stream, that allow for white-space wrapping text at ...
constexpr const char * default_format
Resets the text format to the settings before modification.
Definition: vt_helper.h:106
constexpr const char * foreground_cyan
Sets the foreground color to cyan.
Definition: vt_helper.h:145
constexpr const char * foreground_red
Sets the foreground color to red.
Definition: vt_helper.h:130
constexpr const char * foreground_green
Sets the foreground color to green.
Definition: vt_helper.h:133
Namespace containing the core Ookii.CommandLine.Cpp types.
Definition: command_line_argument.h:16
@ output
The standard output stream.
@ error
The standard error stream.
description_list_filter_mode
Indicates which arguments should be included in the description list when printing usage.
Definition: usage_writer.h:39
@ none
Omit the description list entirely.
@ all
Include all arguments.
@ information
Include arguments that have any information that is not included in the syntax, such as aliases,...
@ descripion
Include only arguments that have a description.
usage_help_request
Indicates if and how usage is shown if an error occurred parsing the command line.
Definition: usage_writer.h:26
@ none
No usage help is shown. Instead, the basic_usage_writer::write_more_info_message() message is shown.
@ syntax_only
Only the usage syntax is shown; the argument descriptions are not. In addition, the basic_usage_write...
@ full
Full usage help is shown, including the argument descriptions.
basic_command< char > command
Typedef for basic_command using char as the character type.
Definition: subcommand.h:94
std::basic_ostream< CharType, Traits > & reset_indent(std::basic_ostream< CharType, Traits > &stream)
IO manipulator that lets the next line start at the beginning of the line, without indenting it.
Definition: line_wrapping_stream.h:680
@ long_short
Use POSIX-like rules where arguments have separate long and short names.
details::set_indent_helper set_indent(size_t indent)
IO manipulator that changes the number of spaces that each line is indented with for a line wrapping ...
Definition: line_wrapping_stream.h:658
description_list_sort_mode
Indicates how the arguments in the description list should be sorted.
Definition: usage_writer.h:53
@ alphabetical_short_name
The descriptions are listed in alphabetical order by the short argument name. If the argument has no ...
@ alphabetical_descending
The same as alphabetical, but in reverse order.
@ alphabetical_short_name_descending
The same as alphabetical_short_name, but in reverse order.
@ usage_order
The descriptions are listed in the same order as the usage syntax: first the positional arguments,...
@ alphabetical
The descriptions are listed in alphabetical order by argument name. If the parsing mode is parsing_mo...
@ error
There was an error converting the value to the element type of the argument.
Provides helper types and functions for working with strings.
Provides default values for the fields of basic_usage_writer.
Definition: usage_writer.h:108
static constexpr size_t argument_description_indent
Default value for basic_usage_writer::argument_description_indent.
Definition: usage_writer.h:116
static constexpr size_t application_description_indent
Default value for basic_usage_writer::application_description_indent.
Definition: usage_writer.h:112
static constexpr auto name_separator
Default value for basic_usage_writer::name_separator.
Definition: usage_writer.h:110
static constexpr size_t syntax_indent
Default value for basic_usage_writer::syntax_indent.
Definition: usage_writer.h:114
static constexpr size_t command_description_indent
Default value for basic_usage_writer::command_description_indent.
Definition: usage_writer.h:118
Template used to specify the default value description for a type.
Definition: value_description.h:30