2 #include "private/cli/commandparserandexecutor.hpp"
7 #include <boost/program_options.hpp>
8 #include "private/cli/commandmap.hpp"
10 using namespace shareddatalayer;
11 using namespace shareddatalayer::cli;
12 namespace po = boost::program_options;
16 void outputBashCompletion(std::ostream& os,
17 const po::options_description& commonOpts,
18 CommandMap& commandMap)
20 const auto commandNames(commandMap.getCommandNames());
21 std::set<std::string> optionNames;
22 for (const auto& i : commonOpts.options())
23 optionNames.insert(i->long_name());
24 for (const auto& i : commandNames)
25 for (const auto& j : commandMap.getCommandOptions(i).options())
26 optionNames.insert(j->long_name());
28 os << "_sdltool()\n{\n COMPREPLY=()\n local commands=\"";
29 for (const auto& i : commandNames)
31 os << "\"\n local options=\"";
32 for (const auto& i : optionNames)
33 os << "--" << i << ' ';
36 local cur="${COMP_WORDS[COMP_CWORD]}"
38 if [[ ${cur} == -* ]] ; then
39 COMPREPLY=( $(compgen -W "${options}" -- ${cur}) )
42 COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
46 complete -F _sdltool sdltool
51 void printShortHelp(std::ostream& os,
52 const po::options_description& commonOpts,
53 CommandMap& commandMap)
55 os << "Usage: sdltool [OPTIONS] COMMAND [COMMAND SPECIFIC OPTIONS]\n\n";
57 os << "\nAvailable commands:\n";
58 commandMap.shortHelp(os);
61 int privateParseAndExecute(int argc,
65 CommandMap& commandMap)
67 po::options_description commonHiddenOptsDescription("Common hidden options");
68 commonHiddenOptsDescription.add_options()
69 ("pos-command", po::value<std::string>(), "sdltool command to run")
70 ("pos-subargs", po::value<std::vector<std::string>>(), "Arguments for command");
72 po::options_description commonVisibleOptsDescription("Common options");
73 commonVisibleOptsDescription.add_options()
74 ("help", "Show help for COMMAND")
75 ("repeat", po::value<size_t>()->default_value(1U), "Times to repeat the command")
76 ("bash-completion", "Generate bash completion script")
77 ("version", "Show version information");
79 po::options_description commonOptsDescription("All common options");
80 commonOptsDescription.add(commonHiddenOptsDescription);
81 commonOptsDescription.add(commonVisibleOptsDescription);
83 po::positional_options_description commonPosOptsDescription;
84 commonPosOptsDescription
85 .add("pos-command", 1)
86 .add("pos-subargs", -1); // all positional arguments after 'command'
88 po::variables_map commonVarsMap;
89 po::parsed_options commonParsed(po::command_line_parser(argc, argv)
90 .options(commonOptsDescription)
91 .positional(commonPosOptsDescription)
94 po::store(commonParsed, commonVarsMap);
95 po::notify(commonVarsMap);
97 if (!commonVarsMap.count("pos-command"))
99 if (commonVarsMap.count("help"))
101 printShortHelp(out, commonVisibleOptsDescription, commandMap);
104 if (commonVarsMap.count("bash-completion"))
106 outputBashCompletion(out, commonVisibleOptsDescription, commandMap);
109 if (commonVarsMap.count("version"))
111 out << PACKAGE_STRING << std::endl;
114 err << "missing command\n\n";
115 printShortHelp(err, commonVisibleOptsDescription, commandMap);
119 auto leftOverOpts = po::collect_unrecognized(commonParsed.options, po::include_positional);
120 if (!leftOverOpts.empty())
121 leftOverOpts.erase(leftOverOpts.begin());
123 const auto commandName(commonVarsMap["pos-command"].as<std::string>());
125 if (commonVarsMap.count("help"))
130 commandMap.longHelp(out, commandName);
134 catch (const CommandMap::UnknownCommandName&)
139 err << "unknown command: \"" << commandName << "\"\n";
145 const auto& commandOptions(commandMap.getCommandOptions(commandName));
147 po::variables_map subcmdVarsMap;
148 auto subcmdParsed(po::command_line_parser(leftOverOpts).options(commandOptions).run());
149 po::store(subcmdParsed, subcmdVarsMap);
150 po::notify(subcmdVarsMap);
152 return commandMap.execute(commandName,
156 commonVarsMap["repeat"].as<size_t>());
160 int shareddatalayer::cli::parseAndExecute(int argc,
164 CommandMap& commandMap)
168 return privateParseAndExecute(argc, argv, out, err, commandMap);
170 catch (const std::exception& e)
172 err << e.what() << std::endl;