Skip to content

Instantly share code, notes, and snippets.

@j-rivero
Created May 21, 2025 11:52
Show Gist options
  • Save j-rivero/b4e332833440a85b463f66f9ee87524f to your computer and use it in GitHub Desktop.
Save j-rivero/b4e332833440a85b463f66f9ee87524f to your computer and use it in GitHub Desktop.
Use subcommands.
diff --git a/src/cmd/model_main.cc b/src/cmd/model_main.cc
index 4d1cabda5..ccc994c5d 100644
--- a/src/cmd/model_main.cc
+++ b/src/cmd/model_main.cc
@@ -27,21 +27,9 @@
#include "ModelCommandAPI.hh"
//////////////////////////////////////////////////
-/// \brief Enumeration of available model commands
-enum class ModelCommand
+/// \brief Structure to hold model info options
+struct ModelInfoOptions
{
- kNone,
- kModelList,
- kModelInfo
-};
-
-//////////////////////////////////////////////////
-/// \brief Structure to hold all available model options
-struct ModelOptions
-{
- /// \brief Command to execute
- ModelCommand command{ModelCommand::kNone};
-
/// \brief Name of the model to show
std::string modelName{""};
@@ -62,94 +50,82 @@ struct ModelOptions
};
//////////////////////////////////////////////////
-/// \brief Callback fired when options are successfully parsed
-void runModelCommand(const ModelOptions &_opt)
+/// \brief Callback fired when executing list subcommand
+void runListCommand()
{
- switch(_opt.command)
- {
- case ModelCommand::kModelList:
- cmdModelList();
- break;
- case ModelCommand::kModelInfo:
- {
- const char *linkName{nullptr};
- if(_opt.linkName.has_value())
- linkName = _opt.linkName.value().c_str();
-
- const char *jointName{nullptr};
- if(_opt.jointName.has_value())
- jointName = _opt.jointName.value().c_str();
-
- const char *sensorName{nullptr};
- if(_opt.sensorName.has_value())
- sensorName = _opt.sensorName.value().c_str();
-
- cmdModelInfo(_opt.modelName.c_str(), _opt.pose, linkName,
- jointName, sensorName);
- }
- break;
- case ModelCommand::kNone:
- default:
- throw CLI::CallForHelp();
- }
+ cmdModelList();
}
//////////////////////////////////////////////////
-void addModelFlags(CLI::App &_app)
+/// \brief Callback fired when executing model info subcommand
+void runModelCommand(const ModelInfoOptions &_opt)
{
- auto opt = std::make_shared<ModelOptions>();
+ const char *linkName{nullptr};
+ if(_opt.linkName.has_value())
+ linkName = _opt.linkName.value().c_str();
- auto command = _app.add_option_group("command", "Command to be executed.");
+ const char *jointName{nullptr};
+ if(_opt.jointName.has_value())
+ jointName = _opt.jointName.value().c_str();
- command->add_flag_callback("--list",
- [opt](){
- opt->command = ModelCommand::kModelList;
- },
- "Get a list of available models.");
+ const char *sensorName{nullptr};
+ if(_opt.sensorName.has_value())
+ sensorName = _opt.sensorName.value().c_str();
- auto modelCmd = command->add_option_function<std::string>("-m,--model",
- [opt](const std::string &_modelName){
- opt->command = ModelCommand::kModelInfo;
- opt->modelName = _modelName;
- },
- "Select the model to be shown.");
+ cmdModelInfo(_opt.modelName.c_str(), _opt.pose, linkName,
+ jointName, sensorName);
+}
- auto linkCmd = command->add_option_function<std::string>("-l,--link",
- [opt](const std::string &_linkName){
- opt->linkName = _linkName;
- },
+//////////////////////////////////////////////////
+void addModelCommands(CLI::App &_app)
+{
+ // Create subcommand for listing models
+ auto listCmd = _app.add_subcommand("list", "Get a list of available models.");
+ listCmd->callback([]() {
+ runListCommand();
+ });
+
+ // Create subcommand for model info
+ auto modelCmd = _app.add_subcommand("model", "Select a model to be shown.");
+
+ auto modelOpt = std::make_shared<ModelInfoOptions>();
+
+ modelCmd->add_option("name",
+ modelOpt->modelName,
+ "Model name")->required();
+
+ // Add options to the model subcommand
+ modelCmd->add_option("-l,--link",
+ modelOpt->linkName,
"Select a link to show its properties.\n"
"If no arg is passed all links are printed.")
- ->needs(modelCmd)
->expected(0, 1)
->default_val("");
- command->add_option_function<std::string>("-s,--sensor",
- [opt](const std::string &_sensorName){
- opt->sensorName = _sensorName;
- },
+ modelCmd->add_option("-s,--sensor",
+ modelOpt->sensorName,
"Select a sensor to show its properties.\n"
"If no arg is passed all sensors are printed.")
- ->needs(modelCmd)
- ->needs(linkCmd)
->expected(0, 1)
->default_val("");
- command->add_option_function<std::string>("-j,--joint",
- [opt](const std::string &_jointName){
- opt->jointName = _jointName;
- },
+ modelCmd->add_option("-j,--joint",
+ modelOpt->jointName,
"Select a joint to show its properties.\n"
"If no arg is passed all joints are printed.")
- ->needs(modelCmd)
->expected(0, 1)
->default_val("");
- command->add_flag("-p,--pose", opt->pose,
- "Print the pose of the model.")
- ->needs(modelCmd);
+ modelCmd->add_option("-p,--pose",
+ modelOpt->pose,
+ "Print the pose of the model.");
+
+ modelCmd->callback([modelOpt](){
+ runModelCommand(*modelOpt);
+ });
- _app.callback([opt](){ runModelCommand(*opt); });
+ // Require one subcommand
+ _app.require_subcommand(1, 1);
}
//////////////////////////////////////////////////
@@ -167,7 +143,7 @@ int main(int argc, char** argv)
app.add_flag("--force-version", "Use a specific library version.");
app.add_flag("--versions", "Show the available versions.");
- addModelFlags(app);
+ addModelCommands(app);
app.formatter(std::make_shared<GzFormatter>(&app));
CLI11_PARSE(app, argc, argv);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment