Commit 101d847c295fd710d98975bfdd3602d2e6f201b2

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 3ff6fcae

Use filter fn to simplify, sort includes

CHANGELOG.md
@@ -33,6 +33,8 @@ Other changes: @@ -33,6 +33,8 @@ Other changes:
33 * Testing (only) now uses submodules. [#111] 33 * Testing (only) now uses submodules. [#111]
34 * Removed `requires` in favor of `needs` (deprecated in last version) [#112] 34 * Removed `requires` in favor of `needs` (deprecated in last version) [#112]
35 * Better CMake policy handling [#110] 35 * Better CMake policy handling [#110]
  36 +* Includes are properly sorted [#120]
  37 +* `lname` and `sname` have getters, added `const get_parent` [#120]
36 38
37 [#109]: https://github.com/CLIUtils/CLI11/pull/109 39 [#109]: https://github.com/CLIUtils/CLI11/pull/109
38 [#110]: https://github.com/CLIUtils/CLI11/pull/110 40 [#110]: https://github.com/CLIUtils/CLI11/pull/110
@@ -42,6 +44,7 @@ Other changes: @@ -42,6 +44,7 @@ Other changes:
42 [#116]: https://github.com/CLIUtils/CLI11/pull/116 44 [#116]: https://github.com/CLIUtils/CLI11/pull/116
43 [#118]: https://github.com/CLIUtils/CLI11/pull/118 45 [#118]: https://github.com/CLIUtils/CLI11/pull/118
44 [#118]: https://github.com/CLIUtils/CLI11/pull/119 46 [#118]: https://github.com/CLIUtils/CLI11/pull/119
  47 +[#120]: https://github.com/CLIUtils/CLI11/pull/120
45 48
46 ### Version 1.5.3: Compiler compatibility 49 ### Version 1.5.3: Compiler compatibility
47 This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported. 50 This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.
examples/enum.cpp
1 -#include <sstream>  
2 #include <CLI/CLI.hpp> 1 #include <CLI/CLI.hpp>
  2 +#include <sstream>
3 3
4 enum class Level : int { High, Medium, Low }; 4 enum class Level : int { High, Medium, Low };
5 5
examples/inter_argument_order.cpp
1 #include <CLI/CLI.hpp> 1 #include <CLI/CLI.hpp>
  2 +#include <algorithm>
2 #include <iostream> 3 #include <iostream>
3 -#include <vector>  
4 #include <tuple> 4 #include <tuple>
5 -#include <algorithm> 5 +#include <vector>
6 6
7 int main(int argc, char **argv) { 7 int main(int argc, char **argv) {
8 CLI::App app{"An app to practice mixing unlimited arguments, but still recover the original order."}; 8 CLI::App app{"An app to practice mixing unlimited arguments, but still recover the original order."};
include/CLI/App.hpp
@@ -1013,8 +1013,8 @@ class App { @@ -1013,8 +1013,8 @@ class App {
1013 for(const Option_p &opt : options_) { 1013 for(const Option_p &opt : options_) {
1014 1014
1015 // Only process option with a long-name and configurable 1015 // Only process option with a long-name and configurable
1016 - if(!opt->lnames_.empty() && opt->get_configurable()) {  
1017 - std::string name = prefix + opt->lnames_[0]; 1016 + if(!opt->get_lnames().empty() && opt->get_configurable()) {
  1017 + std::string name = prefix + opt->get_lnames()[0];
1018 std::string value; 1018 std::string value;
1019 1019
1020 // Non-flags 1020 // Non-flags
@@ -1025,8 +1025,8 @@ class App { @@ -1025,8 +1025,8 @@ class App {
1025 value = detail::inijoin(opt->results()); 1025 value = detail::inijoin(opt->results());
1026 1026
1027 // If the option has a default and is requested by optional argument 1027 // If the option has a default and is requested by optional argument
1028 - else if(default_also && !opt->defaultval_.empty())  
1029 - value = opt->defaultval_; 1028 + else if(default_also && !opt->get_defaultval().empty())
  1029 + value = opt->get_defaultval();
1030 // Flag, one passed 1030 // Flag, one passed
1031 } else if(opt->count() == 1) { 1031 } else if(opt->count() == 1) {
1032 value = "true"; 1032 value = "true";
@@ -1148,6 +1148,9 @@ class App { @@ -1148,6 +1148,9 @@ class App {
1148 /// Get the parent of this subcommand (or nullptr if master app) 1148 /// Get the parent of this subcommand (or nullptr if master app)
1149 App *get_parent() { return parent_; } 1149 App *get_parent() { return parent_; }
1150 1150
  1151 + /// Get the parent of this subcommand (or nullptr if master app) (const version)
  1152 + const App *get_parent() const { return parent_; }
  1153 +
1151 /// Get a pointer to the config option. (const) 1154 /// Get a pointer to the config option. (const)
1152 const Option *get_config_ptr() const { return config_ptr_; } 1155 const Option *get_config_ptr() const { return config_ptr_; }
1153 1156
include/CLI/Formatter.hpp
@@ -10,42 +10,44 @@ @@ -10,42 +10,44 @@
10 10
11 namespace CLI { 11 namespace CLI {
12 12
13 -inline std::string  
14 -Formatter::make_group(std::string group, std::vector<const Option *> opts, bool is_positional) const { 13 +inline std::string Formatter::make_group(const App *app,
  14 + std::string group,
  15 + bool is_positional,
  16 + std::function<bool(const Option *)> filter) const {
15 std::stringstream out; 17 std::stringstream out;
16 - out << "\n" << group << ":\n";  
17 - for(const Option *opt : opts) {  
18 - out << make_option(opt, is_positional); 18 + std::vector<const Option *> opts = app->get_options(filter);
  19 +
  20 + if(!opts.empty()) {
  21 + out << "\n" << group << ":\n";
  22 + for(const Option *opt : opts) {
  23 + out << make_option(opt, is_positional);
  24 + }
19 } 25 }
20 26
21 return out.str(); 27 return out.str();
22 } 28 }
23 29
  30 +inline std::string Formatter::make_positionals(const App *app) const {
  31 + return make_group(app, get_label("Positionals"), true, [](const Option *opt) {
  32 + return !opt->get_group().empty() && opt->get_positional();
  33 + });
  34 +}
  35 +
24 inline std::string Formatter::make_groups(const App *app, AppFormatMode mode) const { 36 inline std::string Formatter::make_groups(const App *app, AppFormatMode mode) const {
25 std::stringstream out; 37 std::stringstream out;
26 std::vector<std::string> groups = app->get_groups(); 38 std::vector<std::string> groups = app->get_groups();
27 - std::vector<const Option *> positionals =  
28 - app->get_options([](const Option *opt) { return !opt->get_group().empty() && opt->get_positional(); });  
29 -  
30 - if(!positionals.empty())  
31 - out << make_group(get_label("Positionals"), positionals, true);  
32 39
33 // Options 40 // Options
34 for(const std::string &group : groups) { 41 for(const std::string &group : groups) {
35 - std::vector<const Option *> grouped_items =  
36 - app->get_options([&group](const Option *opt) { return opt->nonpositional() && opt->get_group() == group; });  
37 -  
38 - if(mode == AppFormatMode::Sub) {  
39 - grouped_items.erase(std::remove_if(grouped_items.begin(),  
40 - grouped_items.end(),  
41 - [app](const Option *opt) {  
42 - return app->get_help_ptr() == opt || app->get_help_all_ptr() == opt;  
43 - }),  
44 - grouped_items.end());  
45 - } 42 + if(!group.empty()) {
  43 + out << make_group(app, group, false, [app, mode, &group](const Option *opt) {
  44 + return opt->get_group() == group // Must be in the right group
  45 + && opt->nonpositional() // Must not be a positional
  46 + && (mode != AppFormatMode::Sub // If mode is Sub, then
  47 + || (app->get_help_ptr() != opt // Ignore help pointer
  48 + && app->get_help_all_ptr() != opt)); // Ignore help all pointer
  49 + });
46 50
47 - if(!group.empty() && !grouped_items.empty()) {  
48 - out << make_group(group, grouped_items, false);  
49 if(group != groups.back()) 51 if(group != groups.back())
50 out << "\n"; 52 out << "\n";
51 } 53 }
@@ -113,21 +115,19 @@ inline std::string Formatter::make_footer(const App *app) const { @@ -113,21 +115,19 @@ inline std::string Formatter::make_footer(const App *app) const {
113 115
114 inline std::string Formatter::operator()(const App *app, std::string name, AppFormatMode mode) const { 116 inline std::string Formatter::operator()(const App *app, std::string name, AppFormatMode mode) const {
115 117
  118 + // This immediatly forwards to the make_expanded method. This is done this way so that subcommands can
  119 + // have overridden formatters
  120 + if(mode == AppFormatMode::Sub)
  121 + return make_expanded(app);
  122 +
116 std::stringstream out; 123 std::stringstream out;
117 - if(mode == AppFormatMode::Normal) {  
118 - out << make_description(app);  
119 - out << make_usage(app, name);  
120 - out << make_groups(app, mode);  
121 - out << make_subcommands(app, mode);  
122 - out << make_footer(app);  
123 - } else if(mode == AppFormatMode::Sub) {  
124 - out << make_expanded(app);  
125 - } else if(mode == AppFormatMode::All) {  
126 - out << make_description(app);  
127 - out << make_usage(app, name);  
128 - out << make_groups(app, mode);  
129 - out << make_subcommands(app, mode);  
130 - } 124 +
  125 + out << make_description(app);
  126 + out << make_usage(app, name);
  127 + out << make_positionals(app);
  128 + out << make_groups(app, mode);
  129 + out << make_subcommands(app, mode);
  130 + out << make_footer(app);
131 131
132 return out.str(); 132 return out.str();
133 } 133 }
@@ -151,8 +151,6 @@ inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mod @@ -151,8 +151,6 @@ inline std::string Formatter::make_subcommands(const App *app, AppFormatMode mod
151 // For each group, filter out and print subcommands 151 // For each group, filter out and print subcommands
152 for(const std::string &group : subcmd_groups_seen) { 152 for(const std::string &group : subcmd_groups_seen) {
153 out << "\n" << group << ":\n"; 153 out << "\n" << group << ":\n";
154 - if(mode == AppFormatMode::All)  
155 - out << "\n";  
156 std::vector<const App *> subcommands_group = app->get_subcommands( 154 std::vector<const App *> subcommands_group = app->get_subcommands(
157 [&group](const App *app) { return detail::to_lower(app->get_group()) == detail::to_lower(group); }); 155 [&group](const App *app) { return detail::to_lower(app->get_group()) == detail::to_lower(group); });
158 for(const App *new_com : subcommands_group) { 156 for(const App *new_com : subcommands_group) {
@@ -177,7 +175,10 @@ inline std::string Formatter::make_subcommand(const App *sub) const { @@ -177,7 +175,10 @@ inline std::string Formatter::make_subcommand(const App *sub) const {
177 175
178 inline std::string Formatter::make_expanded(const App *sub) const { 176 inline std::string Formatter::make_expanded(const App *sub) const {
179 std::stringstream out; 177 std::stringstream out;
180 - out << sub->get_name() << "\n " << sub->get_description(); 178 + if(sub->get_description().empty())
  179 + out << sub->get_name();
  180 + else
  181 + out << sub->get_name() << " -> " << sub->get_description();
181 out << make_groups(sub, AppFormatMode::Sub); 182 out << make_groups(sub, AppFormatMode::Sub);
182 return out.str(); 183 return out.str();
183 } 184 }
include/CLI/FormatterFwd.hpp
@@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
3 // Distributed under the 3-Clause BSD License. See accompanying 3 // Distributed under the 3-Clause BSD License. See accompanying
4 // file LICENSE or https://github.com/CLIUtils/CLI11 for details. 4 // file LICENSE or https://github.com/CLIUtils/CLI11 for details.
5 5
6 -#include <string>  
7 #include <map> 6 #include <map>
  7 +#include <string>
8 8
9 #include "CLI/StringTools.hpp" 9 #include "CLI/StringTools.hpp"
10 10
@@ -72,10 +72,16 @@ class Formatter { @@ -72,10 +72,16 @@ class Formatter {
72 ///@{ 72 ///@{
73 73
74 /// This prints out a group of options 74 /// This prints out a group of options
75 - virtual std::string make_group(std::string group, std::vector<const Option *> opts, bool is_positional) const; 75 + ///
  76 + /// Use the filter to pick out the items you want in your group
  77 + virtual std::string
  78 + make_group(const App *app, std::string group, bool is_positional, std::function<bool(const Option *)> filter) const;
  79 +
  80 + /// This prints out just the positionals "group"
  81 + virtual std::string make_positionals(const App *app) const;
76 82
77 /// This prints out all the groups of options 83 /// This prints out all the groups of options
78 - virtual std::string make_groups(const App *app, AppFormatMode mode) const; 84 + std::string make_groups(const App *app, AppFormatMode mode) const;
79 85
80 /// This prints out all the subcommands 86 /// This prints out all the subcommands
81 virtual std::string make_subcommands(const App *app, AppFormatMode mode) const; 87 virtual std::string make_subcommands(const App *app, AppFormatMode mode) const;
@@ -102,6 +108,7 @@ class Formatter { @@ -102,6 +108,7 @@ class Formatter {
102 /// @name Options 108 /// @name Options
103 ///@{ 109 ///@{
104 110
  111 + /// This prints out an option help line, either positional or optional form
105 virtual std::string make_option(const Option *opt, bool is_positional) const { 112 virtual std::string make_option(const Option *opt, bool is_positional) const {
106 std::stringstream out; 113 std::stringstream out;
107 detail::format_help( 114 detail::format_help(
include/CLI/Option.hpp
@@ -402,6 +402,12 @@ class Option : public OptionBase&lt;Option&gt; { @@ -402,6 +402,12 @@ class Option : public OptionBase&lt;Option&gt; {
402 /// The default value (for help printing) 402 /// The default value (for help printing)
403 std::string get_defaultval() const { return defaultval_; } 403 std::string get_defaultval() const { return defaultval_; }
404 404
  405 + /// Get the long names
  406 + const std::vector<std::string> get_lnames() const { return lnames_; }
  407 +
  408 + /// Get the short names
  409 + const std::vector<std::string> get_snames() const { return snames_; }
  410 +
405 /// The number of times the option expects to be included 411 /// The number of times the option expects to be included
406 int get_expected() const { return expected_; } 412 int get_expected() const { return expected_; }
407 413
include/CLI/StringTools.hpp
@@ -8,8 +8,8 @@ @@ -8,8 +8,8 @@
8 #include <locale> 8 #include <locale>
9 #include <sstream> 9 #include <sstream>
10 #include <string> 10 #include <string>
11 -#include <vector>  
12 #include <type_traits> 11 #include <type_traits>
  12 +#include <vector>
13 13
14 namespace CLI { 14 namespace CLI {
15 namespace detail { 15 namespace detail {
include/CLI/Validators.hpp
@@ -28,7 +28,7 @@ namespace CLI { @@ -28,7 +28,7 @@ namespace CLI {
28 28
29 /// 29 ///
30 struct Validator { 30 struct Validator {
31 - /// This is the type name, if emtpy the type name will not be changed 31 + /// This is the type name, if empty the type name will not be changed
32 std::string tname; 32 std::string tname;
33 std::function<std::string(const std::string &filename)> func; 33 std::function<std::string(const std::string &filename)> func;
34 34
@@ -77,7 +77,7 @@ struct Validator { @@ -77,7 +77,7 @@ struct Validator {
77 } 77 }
78 }; 78 };
79 79
80 -// The implemntation of the built in validators is using the Validator class; 80 +// The implementation of the built in validators is using the Validator class;
81 // the user is only expected to use the const (static) versions (since there's no setup). 81 // the user is only expected to use the const (static) versions (since there's no setup).
82 // Therefore, this is in detail. 82 // Therefore, this is in detail.
83 namespace detail { 83 namespace detail {
scripts/check_style.sh
@@ -3,7 +3,7 @@ set -evx @@ -3,7 +3,7 @@ set -evx
3 3
4 clang-format --version 4 clang-format --version
5 5
6 -git ls-files -- '*.cpp' '*.hpp' | xargs clang-format -i -style=file 6 +git ls-files -- '*.cpp' '*.hpp' | xargs clang-format -sort-includes -i -style=file
7 7
8 git diff --exit-code --color 8 git diff --exit-code --color
9 9
tests/AppTest.cpp
1 #include "app_helper.hpp" 1 #include "app_helper.hpp"
2 -#include <cstdlib>  
3 #include <complex> 2 #include <complex>
  3 +#include <cstdlib>
4 4
5 TEST_F(TApp, OneFlagShort) { 5 TEST_F(TApp, OneFlagShort) {
6 app.add_flag("-c,--count"); 6 app.add_flag("-c,--count");
tests/CreationTest.cpp
@@ -2,7 +2,10 @@ @@ -2,7 +2,10 @@
2 #include <cstdlib> 2 #include <cstdlib>
3 3
4 TEST_F(TApp, AddingExistingShort) { 4 TEST_F(TApp, AddingExistingShort) {
5 - app.add_flag("-c,--count"); 5 + CLI::Option *opt = app.add_flag("-c,--count");
  6 + EXPECT_EQ(opt->get_lnames(), std::vector<std::string>({"count"}));
  7 + EXPECT_EQ(opt->get_snames(), std::vector<std::string>({"c"}));
  8 +
6 EXPECT_THROW(app.add_flag("--cat,-c"), CLI::OptionAlreadyAdded); 9 EXPECT_THROW(app.add_flag("--cat,-c"), CLI::OptionAlreadyAdded);
7 } 10 }
8 11
tests/FormatterTest.cpp
@@ -4,8 +4,8 @@ @@ -4,8 +4,8 @@
4 #include "CLI/CLI.hpp" 4 #include "CLI/CLI.hpp"
5 #endif 5 #endif
6 6
7 -#include "gtest/gtest.h"  
8 #include "gmock/gmock.h" 7 #include "gmock/gmock.h"
  8 +#include "gtest/gtest.h"
9 #include <fstream> 9 #include <fstream>
10 10
11 using ::testing::HasSubstr; 11 using ::testing::HasSubstr;
tests/HelpTest.cpp
@@ -4,8 +4,8 @@ @@ -4,8 +4,8 @@
4 #include "CLI/CLI.hpp" 4 #include "CLI/CLI.hpp"
5 #endif 5 #endif
6 6
7 -#include "gtest/gtest.h"  
8 #include "gmock/gmock.h" 7 #include "gmock/gmock.h"
  8 +#include "gtest/gtest.h"
9 #include <fstream> 9 #include <fstream>
10 10
11 using ::testing::HasSubstr; 11 using ::testing::HasSubstr;
@@ -492,7 +492,8 @@ TEST_F(CapturedHelp, CallForAllHelp) { @@ -492,7 +492,8 @@ TEST_F(CapturedHelp, CallForAllHelp) {
492 EXPECT_EQ(err.str(), ""); 492 EXPECT_EQ(err.str(), "");
493 } 493 }
494 TEST_F(CapturedHelp, CallForAllHelpOutput) { 494 TEST_F(CapturedHelp, CallForAllHelpOutput) {
495 - app.add_subcommand("one"); 495 + app.set_help_all_flag("--help-all", "Help all");
  496 + app.add_subcommand("one", "One description");
496 CLI::App *sub = app.add_subcommand("two"); 497 CLI::App *sub = app.add_subcommand("two");
497 sub->add_flag("--three"); 498 sub->add_flag("--three");
498 499
@@ -502,6 +503,20 @@ TEST_F(CapturedHelp, CallForAllHelpOutput) { @@ -502,6 +503,20 @@ TEST_F(CapturedHelp, CallForAllHelpOutput) {
502 EXPECT_THAT(out.str(), HasSubstr("one")); 503 EXPECT_THAT(out.str(), HasSubstr("one"));
503 EXPECT_THAT(out.str(), HasSubstr("two")); 504 EXPECT_THAT(out.str(), HasSubstr("two"));
504 EXPECT_THAT(out.str(), HasSubstr("--three")); 505 EXPECT_THAT(out.str(), HasSubstr("--three"));
  506 +
  507 + EXPECT_EQ(out.str(),
  508 + "My Test Program\n"
  509 + "Usage: [OPTIONS] [SUBCOMMAND]\n"
  510 + "\n"
  511 + "Options:\n"
  512 + " -h,--help Print this help message and exit\n"
  513 + " --help-all Help all\n"
  514 + "\n"
  515 + "Subcommands:\n"
  516 + "one -> One description\n"
  517 + "two\n"
  518 + "Options:\n"
  519 + " --three \n");
505 } 520 }
506 TEST_F(CapturedHelp, NewFormattedHelp) { 521 TEST_F(CapturedHelp, NewFormattedHelp) {
507 app.formatter([](const CLI::App *, std::string, CLI::AppFormatMode) { return "New Help"; }); 522 app.formatter([](const CLI::App *, std::string, CLI::AppFormatMode) { return "New Help"; });
tests/HelpersTest.cpp
1 #include "app_helper.hpp" 1 #include "app_helper.hpp"
2 2
  3 +#include <complex>
  4 +#include <cstdint>
3 #include <cstdio> 5 #include <cstdio>
4 #include <fstream> 6 #include <fstream>
5 -#include <cstdint>  
6 #include <string> 7 #include <string>
7 -#include <complex>  
8 8
9 TEST(Split, SimpleByToken) { 9 TEST(Split, SimpleByToken) {
10 auto out = CLI::detail::split("one.two.three", '.'); 10 auto out = CLI::detail::split("one.two.three", '.');
tests/IniTest.cpp
1 #include "app_helper.hpp" 1 #include "app_helper.hpp"
2 2
  3 +#include "gmock/gmock.h"
3 #include <cstdio> 4 #include <cstdio>
4 #include <sstream> 5 #include <sstream>
5 -#include "gmock/gmock.h"  
6 6
7 using ::testing::HasSubstr; 7 using ::testing::HasSubstr;
8 using ::testing::Not; 8 using ::testing::Not;
tests/SubcommandTest.cpp
1 #include "app_helper.hpp" 1 #include "app_helper.hpp"
2 2
3 -#include "gtest/gtest.h"  
4 #include "gmock/gmock.h" 3 #include "gmock/gmock.h"
  4 +#include "gtest/gtest.h"
5 5
6 using ::testing::HasSubstr; 6 using ::testing::HasSubstr;
7 using ::testing::Not; 7 using ::testing::Not;
tests/TimerTest.cpp
1 -#include "gtest/gtest.h"  
2 -#include "gmock/gmock.h"  
3 #include "CLI/Timer.hpp" 1 #include "CLI/Timer.hpp"
4 -#include <string> 2 +#include "gmock/gmock.h"
  3 +#include "gtest/gtest.h"
5 #include <chrono> 4 #include <chrono>
6 -#include <thread>  
7 #include <sstream> 5 #include <sstream>
  6 +#include <string>
  7 +#include <thread>
8 8
9 using ::testing::HasSubstr; 9 using ::testing::HasSubstr;
10 10