Commit e04498c94ddbf4c15cd5fcb2a8655c18dc1b881b

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 4389b332

Better help-all, prints more info, better spacing

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
... ... @@ -126,3 +126,5 @@ set_property(TEST subcom_in_files PROPERTY PASS_REGULAR_EXPRESSION
126 126 "Using foo!")
127 127  
128 128 add_cli_exe(formatter formatter.cpp)
  129 +
  130 +add_cli_exe(nested nested.cpp)
... ...
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"; });
... ...