/***************************************************************************** * * demo program - part of CLIPP (command line interfaces for modern C++) * * released under MIT license * * (c) 2017-2018 André Müller; foss@andremueller-online.de * *****************************************************************************/ #include #include #include #include #include //------------------------------------------------------------------- enum class mode { none, train, validate, classify }; struct settings { mode selected = mode::none; std::string imageFile; std::string labelFile; std::string modelFile = "out.mdl"; std::size_t batchSize = 128; std::size_t threads = 0; std::size_t inputLimit = 0; std::vector inputFiles; }; //------------------------------------------------------------------- settings configuration(int argc, char* argv[]) { using namespace clipp; settings s; std::vector unrecognized; auto isfilename = clipp::match::prefix_not("-"); auto inputOptions = ( required("-i", "-I", "--img") & !value(isfilename, "image file", s.imageFile), required("-l", "-L", "--lbl") & !value(isfilename, "label file", s.labelFile) ); auto trainMode = ( command("train", "t", "T").set(s.selected,mode::train) .if_conflicted([]{std::cerr << "conflicting modes\n"; }), inputOptions, (option("-n") & integer("limit", s.inputLimit)) % "limit number of input images", (option("-o", "-O", "--out") & !value("model file", s.modelFile)) % "write model to specific file; default: 'out.mdl'", (option("-b", "--batch-size") & integer("batch size", s.batchSize)), (option("-p") & integer("threads", s.threads)) % "number of threads to use; default: optimum for machine" ); auto validationMode = ( command("validate", "v", "V").set(s.selected,mode::validate), !value(isfilename, "model", s.modelFile), inputOptions ); auto classificationMode = ( command("classify", "c", "C").set(s.selected,mode::classify), !value(isfilename, "model", s.modelFile), !values(isfilename, "images", s.inputFiles) ); auto cli = ( trainMode | validationMode | classificationMode, any_other(unrecognized) ); auto res = parse(argc, argv, cli); debug::print(std::cout, res); if(!res || !unrecognized.empty()) { std::string msg = "Wrong command line arguments!\n"; if(s.selected == mode::none) { msg += "Please select a mode!\n"; } else { for(const auto& m : res.missing()) { if(!m.param()->flags().empty()) { msg += "Missing option: " + m.param()->flags().front() + '\n'; } else if(!m.param()->label().empty()) { msg += "Missing value: " + m.param()->label() + '\n'; } } for(const auto& arg : unrecognized) { msg += "Argument not recognized: " + arg + '\n'; } } auto fmt = doc_formatting{}.first_column(8).doc_column(16); //.max_flags_per_param_in_usage(3).surround_alternative_flags("(", ")"); msg += "\nUsage:\n" + usage_lines(cli, argv[0], fmt).str() + '\n'; msg += "\nOptions:\n" + documentation(cli, fmt).str() + '\n'; throw std::invalid_argument{msg}; } return s; } //------------------------------------------------------------------- int main(int argc, char* argv[]) { try { auto conf = configuration(argc, argv); std::cout << "SUCCESS\n"; } catch(std::exception& e) { std::cerr << "ERROR: " << e.what() << '\n'; } }