/*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2015-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <folly/experimental/NestedCommandLineApp.h>
#include <iostream>
+
#include <folly/FileUtil.h>
#include <folly/Format.h>
#include <folly/experimental/io/FsUtil.h>
// Guess the program name as basename(executable)
std::string guessProgramName() {
try {
- return fs::executable_path().filename().native();
+ return fs::executable_path().filename().string();
} catch (const std::exception&) {
return "UNKNOWN";
}
}
-} // namespace
+} // namespace
ProgramExit::ProgramExit(int status, const std::string& msg)
: std::runtime_error(msg),
status_(status) {
- CHECK_NE(status, 0);
+ // Message is only allowed for non-zero exit status
+ CHECK(status_ != 0 || msg.empty());
}
NestedCommandLineApp::NestedCommandLineApp(
std::string programName,
std::string version,
+ std::string programHeading,
+ std::string programHelpFooter,
InitFunction initFunction)
- : programName_(std::move(programName)),
- version_(std::move(version)),
- initFunction_(std::move(initFunction)),
- globalOptions_("Global options") {
+ : programName_(std::move(programName)),
+ programHeading_(std::move(programHeading)),
+ programHelpFooter_(std::move(programHelpFooter)),
+ version_(std::move(version)),
+ initFunction_(std::move(initFunction)),
+ globalOptions_("Global options") {
addCommand("help", "[command]",
"Display help (globally or for a given command)",
"Displays help (globally or for a given command).",
}
void NestedCommandLineApp::displayHelp(
- const po::variables_map& globalOptions,
+ const po::variables_map& /* globalOptions */,
const std::vector<std::string>& args) {
if (args.empty()) {
// General help
printf(
- "Usage: %s [global_options...] <command> [command_options...] "
- "[command_args...]\n\n", programName_.c_str());
+ "%s\nUsage: %s [global_options...] <command> [command_options...] "
+ "[command_args...]\n\n",
+ programHeading_.c_str(),
+ programName_.c_str());
std::cout << globalOptions_;
printf("\nAvailable commands:\n");
int(maxLen), p.first.c_str(), resolveAlias(p.second).c_str());
}
}
+ std::cout << "\n" << programHelpFooter_ << "\n";
} else {
// Help for a given command
auto& p = findCommand(args.front());
if (p.first != args.front()) {
- printf("`%1$s' is an alias for `%2$s'; showing help for `%2$s'\n",
- args.front().c_str(), p.first.c_str());
+ printf("`%s' is an alias for `%s'; showing help for `%s'\n",
+ args.front().c_str(), p.first.c_str(), p.first.c_str());
}
auto& info = p.second;
info.argStr.empty() ? "" : " ",
info.argStr.c_str());
+ printf("%s\n", info.fullHelp.c_str());
+
std::cout << globalOptions_;
if (!info.options.options().empty()) {
printf("\n");
std::cout << info.options;
}
-
- printf("\n%s\n", info.fullHelp.c_str());
}
}
int NestedCommandLineApp::run(int argc, const char* const argv[]) {
if (programName_.empty()) {
- programName_ = fs::path(argv[0]).filename().native();
+ programName_ = fs::path(argv[0]).filename().string();
}
return run(std::vector<std::string>(argv + 1, argv + argc));
}
if (programName_.empty()) {
programName_ = guessProgramName();
}
- auto parsed = parseNestedCommandLine(args, globalOptions_);
+
+ bool not_clean = false;
+ std::vector<std::string> cleanArgs;
+ std::vector<std::string> endArgs;
+
+ for (auto& na : args) {
+ if (na == "--") {
+ not_clean = true;
+ } else if (not_clean) {
+ endArgs.push_back(na);
+ } else {
+ cleanArgs.push_back(na);
+ }
+ }
+
+ auto parsed = parseNestedCommandLine(cleanArgs, globalOptions_);
po::variables_map vm;
po::store(parsed.options, vm);
if (vm.count("help")) {
auto cmdOptions =
po::command_line_parser(parsed.rest).options(info.options).run();
+
po::store(cmdOptions, vm);
po::notify(vm);
auto cmdArgs = po::collect_unrecognized(cmdOptions.options,
po::include_positional);
+ cmdArgs.insert(cmdArgs.end(), endArgs.begin(), endArgs.end());
+
if (initFunction_) {
initFunction_(cmd, vm, cmdArgs);
}
info.command(vm, cmdArgs);
}
-} // namespaces
+} // namespace folly