Commit b774c57dc2e632f3dc17f6653d8bedb09e3efa88

Authored by Henry Fredrick Schreiner
1 parent 67047b71

Adding help testing, option groups

cmake/AddGoogletest.cmake
@@ -14,16 +14,16 @@ download_project(PROJ googletest @@ -14,16 +14,16 @@ download_project(PROJ googletest
14 ) 14 )
15 15
16 16
17 -add_subdirectory(${googletest_SOURCE_DIR}/googletest ${googletest_SOURCE_DIR})  
18 -  
19 -mark_as_advanced(  
20 - gtest_build_samples  
21 - gtest_build_tests  
22 - gtest_disable_pthreads  
23 - gtest_force_shared_crt  
24 - gtest_hide_internal_symbols  
25 - BUILD_SHARED_LIBS  
26 -) 17 +add_subdirectory(${googletest_SOURCE_DIR} ${googletest_SOURCE_DIR})
  18 +
  19 +#mark_as_advanced(
  20 +# gtest_build_samples
  21 +# gtest_build_tests
  22 +# gtest_disable_pthreads
  23 +# gtest_force_shared_crt
  24 +# gtest_hide_internal_symbols
  25 +# BUILD_SHARED_LIBS
  26 +#)
27 27
28 if (CMAKE_CONFIGURATION_TYPES) 28 if (CMAKE_CONFIGURATION_TYPES)
29 add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} 29 add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
@@ -34,14 +34,14 @@ else() @@ -34,14 +34,14 @@ else()
34 --force-new-ctest-process --output-on-failure) 34 --force-new-ctest-process --output-on-failure)
35 endif() 35 endif()
36 36
37 -include_directories(${gtest_SOURCE_DIR}/include) 37 +#include_directories(${gtest_SOURCE_DIR}/include)
38 38
39 # More modern way to do the last line, less messy but needs newish CMake: 39 # More modern way to do the last line, less messy but needs newish CMake:
40 # target_include_directories(gtest INTERFACE ${gtest_SOURCE_DIR}/include) 40 # target_include_directories(gtest INTERFACE ${gtest_SOURCE_DIR}/include)
41 41
42 # Target must already exist 42 # Target must already exist
43 macro(add_gtest TESTNAME) 43 macro(add_gtest TESTNAME)
44 - target_link_libraries(${TESTNAME} PUBLIC gtest gtest_main) 44 + target_link_libraries(${TESTNAME} PUBLIC gtest gmock gtest_main)
45 add_test(${TESTNAME} ${TESTNAME}) 45 add_test(${TESTNAME} ${TESTNAME})
46 endmacro() 46 endmacro()
47 47
include/CLI/App.hpp
@@ -559,15 +559,16 @@ public: @@ -559,15 +559,16 @@ public:
559 559
560 // Check for options 560 // Check for options
561 bool npos = false; 561 bool npos = false;
  562 + std::set<std::string> groups;
562 for(const Option_p &opt : options) { 563 for(const Option_p &opt : options) {
563 if(opt->nonpositional()) { 564 if(opt->nonpositional()) {
564 npos = true; 565 npos = true;
565 - break; 566 + groups.insert(opt->get_group());
566 } 567 }
567 } 568 }
568 569
569 if(npos) 570 if(npos)
570 - out << " [OPTIONS...]"; 571 + out << " [OPTIONS]";
571 572
572 // Positionals 573 // Positionals
573 bool pos=false; 574 bool pos=false;
@@ -593,13 +594,15 @@ public: @@ -593,13 +594,15 @@ public:
593 594
594 // Options 595 // Options
595 if(npos) { 596 if(npos) {
596 - out << "Options:" << std::endl;  
597 - for(const Option_p &opt : options) {  
598 - if(opt->nonpositional())  
599 - detail::format_help(out, opt->help_name(), opt->get_description(), wid);  
600 - 597 + for (const std::string& group : groups) {
  598 + out << group << ":" << std::endl;
  599 + for(const Option_p &opt : options) {
  600 + if(opt->nonpositional() && opt->get_group() == group)
  601 + detail::format_help(out, opt->help_name(), opt->get_description(), wid);
  602 +
  603 + }
  604 + out << std::endl;
601 } 605 }
602 - out << std::endl;  
603 } 606 }
604 607
605 // Subcommands 608 // Subcommands
include/CLI/Option.hpp
@@ -34,7 +34,7 @@ protected: @@ -34,7 +34,7 @@ protected:
34 // These are for help strings 34 // These are for help strings
35 std::string defaultval; 35 std::string defaultval;
36 std::string typeval; 36 std::string typeval;
37 - 37 + std::string _group {"Options"};
38 38
39 bool _default {false}; 39 bool _default {false};
40 bool _required {false}; 40 bool _required {false};
@@ -115,6 +115,15 @@ public: @@ -115,6 +115,15 @@ public:
115 return this; 115 return this;
116 } 116 }
117 117
  118 + Option* group(std::string name) {
  119 + _group = name;
  120 + return this;
  121 + }
  122 +
  123 + const std::string& get_group() const {
  124 + return _group;
  125 + }
  126 +
118 /// Get the description 127 /// Get the description
119 const std::string& get_description() const { 128 const std::string& get_description() const {
120 return description; 129 return description;
tests/CMakeLists.txt
1 include(AddGoogletest) 1 include(AddGoogletest)
2 2
3 -set(CLI_TESTS SmallTest IniTest CLITest) 3 +set(CLI_TESTS SmallTest IniTest CLITest HelpTest)
4 4
5 foreach(T ${CLI_TESTS}) 5 foreach(T ${CLI_TESTS})
6 6
tests/HelpTest.cpp 0 → 100644
  1 +#ifdef CLI_SINGLE_FILE
  2 +#include "CLI11.hpp"
  3 +#else
  4 +#include "CLI/CLI.hpp"
  5 +#endif
  6 +
  7 +#include "gtest/gtest.h"
  8 +#include "gmock/gmock.h"
  9 +#include <fstream>
  10 +
  11 +using ::testing::HasSubstr;
  12 +
  13 +TEST(THelp, Basic) {
  14 + CLI::App app{"My prog"};
  15 +
  16 + std::string help = app.help();
  17 +
  18 + EXPECT_THAT(help, HasSubstr("My prog"));
  19 + EXPECT_THAT(help, HasSubstr("-h,--help"));
  20 + EXPECT_THAT(help, HasSubstr("Options:"));
  21 + EXPECT_THAT(help, HasSubstr("Usage:"));
  22 +
  23 +}
  24 +
  25 +TEST(THelp, OptionalPositional) {
  26 + CLI::App app{"My prog"};
  27 +
  28 + std::string x;
  29 + app.add_option("something", x, "My option here");
  30 +
  31 + std::string help = app.help();
  32 +
  33 + EXPECT_THAT(help, HasSubstr("My prog"));
  34 + EXPECT_THAT(help, HasSubstr("-h,--help"));
  35 + EXPECT_THAT(help, HasSubstr("Options:"));
  36 + EXPECT_THAT(help, HasSubstr("Positionals:"));
  37 + EXPECT_THAT(help, HasSubstr("something STRING"));
  38 + EXPECT_THAT(help, HasSubstr("My option here"));
  39 + EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] [something]"));
  40 +
  41 +}
  42 +TEST(THelp, OptionalPositionalAndOptions) {
  43 + CLI::App app{"My prog"};
  44 + app.add_flag("-q,--quick");
  45 +
  46 + std::string x;
  47 + app.add_option("something", x, "My option here");
  48 +
  49 + std::string help = app.help();
  50 +
  51 + EXPECT_THAT(help, HasSubstr("My prog"));
  52 + EXPECT_THAT(help, HasSubstr("-h,--help"));
  53 + EXPECT_THAT(help, HasSubstr("Options:"));
  54 + EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] [something]"));
  55 +
  56 +}
  57 +
  58 +TEST(THelp, RequiredPositionalAndOptions) {
  59 + CLI::App app{"My prog"};
  60 + app.add_flag("-q,--quick");
  61 +
  62 + std::string x;
  63 + app.add_option("something", x, "My option here")
  64 + ->required();
  65 +
  66 + std::string help = app.help();
  67 +
  68 + EXPECT_THAT(help, HasSubstr("My prog"));
  69 + EXPECT_THAT(help, HasSubstr("-h,--help"));
  70 + EXPECT_THAT(help, HasSubstr("Options:"));
  71 + EXPECT_THAT(help, HasSubstr("Positionals:"));
  72 + EXPECT_THAT(help, HasSubstr("Usage: program [OPTIONS] something"));
  73 +
  74 +}