1 // Copyright (c) 2017-2021, University of Cincinnati, developed by Henry Schreiner 2 // under NSF AWARD 1414736 and by the respective contributors. 3 // All rights reserved. 4 // 5 // SPDX-License-Identifier: BSD-3-Clause 6 7 #ifdef CLI11_SINGLE_FILE 8 #include "CLI11.hpp" 9 #else 10 #include "CLI/CLI.hpp" 11 #endif 12 13 #include "catch.hpp" 14 #include <fstream> 15 16 using Catch::Matchers::Contains; 17 18 class SimpleFormatter : public CLI::FormatterBase { 19 public: SimpleFormatter()20 SimpleFormatter() : FormatterBase() {} 21 make_help(const CLI::App *,std::string,CLI::AppFormatMode) const22 std::string make_help(const CLI::App *, std::string, CLI::AppFormatMode) const override { 23 return "This is really simple"; 24 } 25 }; 26 27 TEST_CASE("Formatter: Nothing", "[formatter]") { 28 CLI::App app{"My prog"}; 29 30 app.formatter(std::make_shared<SimpleFormatter>()); 31 32 std::string help = app.help(); 33 34 CHECK("This is really simple" == help); 35 } 36 37 TEST_CASE("Formatter: NothingLambda", "[formatter]") { 38 CLI::App app{"My prog"}; 39 40 app.formatter_fn( __anon68cefdc00102(const CLI::App *, std::string, CLI::AppFormatMode) 41 [](const CLI::App *, std::string, CLI::AppFormatMode) { return std::string("This is really simple"); }); 42 43 std::string help = app.help(); 44 45 CHECK("This is really simple" == help); 46 } 47 48 TEST_CASE("Formatter: OptCustomize", "[formatter]") { 49 CLI::App app{"My prog"}; 50 51 auto optfmt = std::make_shared<CLI::Formatter>(); 52 optfmt->column_width(25); 53 optfmt->label("REQUIRED", "(MUST HAVE)"); 54 app.formatter(optfmt); 55 56 int v{0}; 57 app.add_option("--opt", v, "Something")->required(); 58 59 std::string help = app.help(); 60 61 CHECK_THAT(help, Contains("(MUST HAVE)")); 62 CHECK(help == "My prog\n" 63 "Usage: [OPTIONS]\n\n" 64 "Options:\n" 65 " -h,--help Print this help message and exit\n" 66 " --opt INT (MUST HAVE) Something\n\n"); 67 } 68 69 TEST_CASE("Formatter: OptCustomizeSimple", "[formatter]") { 70 CLI::App app{"My prog"}; 71 72 app.get_formatter()->column_width(25); 73 app.get_formatter()->label("REQUIRED", "(MUST HAVE)"); 74 75 int v{0}; 76 app.add_option("--opt", v, "Something")->required(); 77 78 std::string help = app.help(); 79 80 CHECK_THAT(help, Contains("(MUST HAVE)")); 81 CHECK(help == "My prog\n" 82 "Usage: [OPTIONS]\n\n" 83 "Options:\n" 84 " -h,--help Print this help message and exit\n" 85 " --opt INT (MUST HAVE) Something\n\n"); 86 } 87 88 TEST_CASE("Formatter: OptCustomizeOptionText", "[formatter]") { 89 CLI::App app{"My prog"}; 90 91 app.get_formatter()->column_width(25); 92 93 int v{0}; 94 app.add_option("--opt", v, "Something")->option_text("(ARG)"); 95 96 std::string help = app.help(); 97 98 CHECK_THAT(help, Contains("(ARG)")); 99 CHECK(help == "My prog\n" 100 "Usage: [OPTIONS]\n\n" 101 "Options:\n" 102 " -h,--help Print this help message and exit\n" 103 " --opt (ARG) Something\n\n"); 104 } 105 106 TEST_CASE("Formatter: FalseFlagExample", "[formatter]") { 107 CLI::App app{"My prog"}; 108 109 app.get_formatter()->column_width(25); 110 app.get_formatter()->label("REQUIRED", "(MUST HAVE)"); 111 112 int v{0}; 113 app.add_flag("--opt,!--no_opt", v, "Something"); 114 115 bool flag{false}; 116 app.add_flag("!-O,--opt2,--no_opt2{false}", flag, "Something else"); 117 118 std::string help = app.help(); 119 120 CHECK_THAT(help, Contains("--no_opt{false}")); 121 CHECK_THAT(help, Contains("--no_opt2{false}")); 122 CHECK_THAT(help, Contains("-O{false}")); 123 } 124 125 TEST_CASE("Formatter: AppCustomize", "[formatter]") { 126 CLI::App app{"My prog"}; 127 app.add_subcommand("subcom1", "This"); 128 129 auto appfmt = std::make_shared<CLI::Formatter>(); 130 appfmt->column_width(20); 131 appfmt->label("Usage", "Run"); 132 app.formatter(appfmt); 133 134 app.add_subcommand("subcom2", "This"); 135 136 std::string help = app.help(); 137 CHECK(help == "My prog\n" 138 "Run: [OPTIONS] [SUBCOMMAND]\n\n" 139 "Options:\n" 140 " -h,--help Print this help message and exit\n\n" 141 "Subcommands:\n" 142 " subcom1 This\n" 143 " subcom2 This\n\n"); 144 } 145 146 TEST_CASE("Formatter: AppCustomizeSimple", "[formatter]") { 147 CLI::App app{"My prog"}; 148 app.add_subcommand("subcom1", "This"); 149 150 app.get_formatter()->column_width(20); 151 app.get_formatter()->label("Usage", "Run"); 152 153 app.add_subcommand("subcom2", "This"); 154 155 std::string help = app.help(); 156 CHECK(help == "My prog\n" 157 "Run: [OPTIONS] [SUBCOMMAND]\n\n" 158 "Options:\n" 159 " -h,--help Print this help message and exit\n\n" 160 "Subcommands:\n" 161 " subcom1 This\n" 162 " subcom2 This\n\n"); 163 } 164 165 TEST_CASE("Formatter: AllSub", "[formatter]") { 166 CLI::App app{"My prog"}; 167 CLI::App *sub = app.add_subcommand("subcom", "This"); 168 sub->add_flag("--insub", "MyFlag"); 169 170 std::string help = app.help("", CLI::AppFormatMode::All); 171 CHECK_THAT(help, Contains("--insub")); 172 CHECK_THAT(help, Contains("subcom")); 173 } 174 175 TEST_CASE("Formatter: AllSubRequired", "[formatter]") { 176 CLI::App app{"My prog"}; 177 CLI::App *sub = app.add_subcommand("subcom", "This"); 178 sub->add_flag("--insub", "MyFlag"); 179 sub->required(); 180 std::string help = app.help("", CLI::AppFormatMode::All); 181 CHECK_THAT(help, Contains("--insub")); 182 CHECK_THAT(help, Contains("subcom")); 183 CHECK_THAT(help, Contains("REQUIRED")); 184 } 185 186 TEST_CASE("Formatter: NamelessSub", "[formatter]") { 187 CLI::App app{"My prog"}; 188 CLI::App *sub = app.add_subcommand("", "This subcommand"); 189 sub->add_flag("--insub", "MyFlag"); 190 191 std::string help = app.help("", CLI::AppFormatMode::Normal); 192 CHECK_THAT(help, Contains("--insub")); 193 CHECK_THAT(help, Contains("This subcommand")); 194 } 195 196 TEST_CASE("Formatter: NamelessSubInGroup", "[formatter]") { 197 CLI::App app{"My prog"}; 198 CLI::App *sub = app.add_subcommand("", "This subcommand"); 199 CLI::App *sub2 = app.add_subcommand("sub2", "subcommand2"); 200 sub->add_flag("--insub", "MyFlag"); 201 int val{0}; 202 sub2->add_option("pos", val, "positional"); 203 sub->group("group1"); 204 sub2->group("group1"); 205 std::string help = app.help("", CLI::AppFormatMode::Normal); 206 CHECK_THAT(help, Contains("--insub")); 207 CHECK_THAT(help, Contains("This subcommand")); 208 CHECK_THAT(help, Contains("group1")); 209 CHECK_THAT(help, Contains("sub2")); 210 CHECK(help.find("pos") == std::string::npos); 211 } 212