Commit e04498c94ddbf4c15cd5fcb2a8655c18dc1b881b
Committed by
Henry Schreiner
1 parent
4389b332
Better help-all, prints more info, better spacing
Showing
7 changed files
with
64 additions
and
13 deletions
CHANGELOG.md
| 1 | -## Version 1.6.2: More special case fixes | |
| 1 | +## Version 1.6.2: Help-all | |
| 2 | 2 | |
| 3 | -This version adds fixes for several warnings, including an experimental optional error on Clang 7. | |
| 3 | +This version fixes some formatting bugs with help-all. It also adds fixes for several warnings, including an experimental optional error on Clang 7. | |
| 4 | 4 | |
| 5 | +* Fixed help-all formatting [#163] | |
| 6 | + * Printing help-all on nested command now fixed (App) | |
| 7 | + * Missing space after help-all restored (Default formatter) | |
| 8 | + * More detail printed on help all (Default formatter) | |
| 9 | + * Help-all subcommands get indented with inner blank lines removed (Default formatter) | |
| 10 | + * `detail::find_and_replace` added to utilities | |
| 5 | 11 | * Fixed CMake install as subproject with `CLI11_INSTALL` flag. [#156] |
| 6 | 12 | * Fixed warning about local variable hiding class member with MSVC [#157] |
| 7 | 13 | * Fixed compile error with default settings on Clang 7 and libc++ [#158] |
| ... | ... | @@ -9,6 +15,7 @@ This version adds fixes for several warnings, including an experimental optional |
| 9 | 15 | [#156]: https://github.com/CLIUtils/CLI11/issues/156 |
| 10 | 16 | [#157]: https://github.com/CLIUtils/CLI11/issues/157 |
| 11 | 17 | [#158]: https://github.com/CLIUtils/CLI11/issues/158 |
| 18 | +[#163]: https://github.com/CLIUtils/CLI11/pull/163 | |
| 12 | 19 | |
| 13 | 20 | ## Version 1.6.1: Platform fixes |
| 14 | 21 | ... | ... |
examples/CMakeLists.txt
examples/nested.cpp
0 → 100644
| 1 | +#include <CLI/CLI.hpp> | |
| 2 | +#include <string> | |
| 3 | + | |
| 4 | +int main(int argc, char **argv) { | |
| 5 | + | |
| 6 | + CLI::App app("Vision Application"); | |
| 7 | + app.set_help_all_flag("--help-all", "Expand all help"); | |
| 8 | + app.add_flag("--version", "Get version"); | |
| 9 | + | |
| 10 | + CLI::App *cameraApp = app.add_subcommand("camera", "Configure the app camera"); | |
| 11 | + cameraApp->require_subcommand(0, 1); // 0 (default) or 1 camera | |
| 12 | + | |
| 13 | + std::string mvcamera_config_file = "mvcamera_config.json"; | |
| 14 | + CLI::App *mvcameraApp = cameraApp->add_subcommand("mvcamera", "MatrixVision Camera Configuration"); | |
| 15 | + mvcameraApp->add_option("-c,--config", mvcamera_config_file, "Config filename", true)->check(CLI::ExistingFile); | |
| 16 | + | |
| 17 | + std::string mock_camera_path; | |
| 18 | + CLI::App *mockcameraApp = cameraApp->add_subcommand("mock", "Mock Camera Configuration"); | |
| 19 | + mockcameraApp->add_option("-p,--path", mock_camera_path, "Path")->required()->check(CLI::ExistingPath); | |
| 20 | + | |
| 21 | + CLI11_PARSE(app, argc, argv); | |
| 22 | +} | ... | ... |
include/CLI/App.hpp
| ... | ... | @@ -1043,7 +1043,7 @@ class App { |
| 1043 | 1043 | // Delegate to subcommand if needed |
| 1044 | 1044 | auto selected_subcommands = get_subcommands(); |
| 1045 | 1045 | if(!selected_subcommands.empty()) |
| 1046 | - return selected_subcommands.at(0)->help(prev); | |
| 1046 | + return selected_subcommands.at(0)->help(prev, mode); | |
| 1047 | 1047 | else |
| 1048 | 1048 | return formatter_->make_help(this, prev, mode); |
| 1049 | 1049 | } | ... | ... |
include/CLI/Formatter.hpp
| ... | ... | @@ -158,8 +158,7 @@ inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mod |
| 158 | 158 | out << make_subcommand(new_com); |
| 159 | 159 | } else { |
| 160 | 160 | out << new_com->help(new_com->get_name(), AppFormatMode::Sub); |
| 161 | - if(new_com != subcommands_group.back()) | |
| 162 | - out << "\n"; | |
| 161 | + out << "\n"; | |
| 163 | 162 | } |
| 164 | 163 | } |
| 165 | 164 | } |
| ... | ... | @@ -175,12 +174,19 @@ inline std::string Formatter::make_subcommand(const App *sub) const { |
| 175 | 174 | |
| 176 | 175 | inline std::string Formatter::make_expanded(const App *sub) const { |
| 177 | 176 | std::stringstream out; |
| 178 | - if(sub->get_description().empty()) | |
| 179 | - out << sub->get_name(); | |
| 180 | - else | |
| 181 | - out << sub->get_name() << " -> " << sub->get_description(); | |
| 177 | + out << sub->get_name() << "\n"; | |
| 178 | + | |
| 179 | + out << make_description(sub); | |
| 180 | + out << make_positionals(sub); | |
| 182 | 181 | out << make_groups(sub, AppFormatMode::Sub); |
| 183 | - return out.str(); | |
| 182 | + out << make_subcommands(sub, AppFormatMode::Sub); | |
| 183 | + | |
| 184 | + // Drop blank spaces | |
| 185 | + std::string tmp = detail::find_and_replace(out.str(), "\n\n", "\n"); | |
| 186 | + tmp = tmp.substr(0, tmp.size() - 1); // Remove the final '\n' | |
| 187 | + | |
| 188 | + // Indent all but the first line (the name) | |
| 189 | + return detail::find_and_replace(tmp, "\n", "\n ") + "\n"; | |
| 184 | 190 | } |
| 185 | 191 | |
| 186 | 192 | inline std::string Formatter::make_option_name(const Option *opt, bool is_positional) const { | ... | ... |
include/CLI/StringTools.hpp
| ... | ... | @@ -204,5 +204,18 @@ inline std::string fix_newlines(std::string leader, std::string input) { |
| 204 | 204 | return input; |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | +/// Find and replace a subtring with another substring | |
| 208 | +inline std::string find_and_replace(std::string str, std::string from, std::string to) { | |
| 209 | + | |
| 210 | + size_t start_pos = 0; | |
| 211 | + | |
| 212 | + while((start_pos = str.find(from, start_pos)) != std::string::npos) { | |
| 213 | + str.replace(start_pos, from.length(), to); | |
| 214 | + start_pos += to.length(); | |
| 215 | + } | |
| 216 | + | |
| 217 | + return str; | |
| 218 | +} | |
| 219 | + | |
| 207 | 220 | } // namespace detail |
| 208 | 221 | } // namespace CLI | ... | ... |
tests/HelpTest.cpp
| ... | ... | @@ -511,10 +511,11 @@ TEST_F(CapturedHelp, CallForAllHelpOutput) { |
| 511 | 511 | " --help-all Help all\n" |
| 512 | 512 | "\n" |
| 513 | 513 | "Subcommands:\n" |
| 514 | - "one -> One description\n" | |
| 514 | + "one\n" | |
| 515 | + " One description\n\n" | |
| 515 | 516 | "two\n" |
| 516 | - "Options:\n" | |
| 517 | - " --three \n"); | |
| 517 | + " Options:\n" | |
| 518 | + " --three \n\n"); | |
| 518 | 519 | } |
| 519 | 520 | TEST_F(CapturedHelp, NewFormattedHelp) { |
| 520 | 521 | app.formatter_fn([](const CLI::App *, std::string, CLI::AppFormatMode) { return "New Help"; }); | ... | ... |