根据第一个选项选择选项组

Selecting option group according the first option

本文关键字:选项 选择 第一个      更新时间:2023-10-16

我已经实现了一个应用程序(让我们称之为"app"),它执行两种类型的任务,TATB。每种任务类型的命令行选项都不同。这就是为什么我决定用户将用"命令"指定任务类型:

app command_a --opt_1  --opt_2     # For TA
app command_b --opt_3  --opt_4     # For TB

当然,command_acommand_b是相互排斥的(你可以在这里看到如何做到这一点)

问题1:选择用于解析命令行的options_description对象的最佳方法是什么?

问题2:实现命令帮助系统的最佳方式是什么?示例:

app help command_a              # Display help for TA

这是我在研究库2个小时后可以实现的最佳答案。我把这个作为答案发布是因为在某种程度上给出了这个问题的解决方案,但我知道很有可能有人提出了更好的解决方案。

选择用于解析命令行的options_description对象的最佳方法是什么

到目前为止,我成功地根据第一个选项在两个options_description对象之间进行了选择(有关更多详细信息,请参阅代码)。我所做的是:

  1. 创建两个选项_描述对象OptDescA用于TAOptDescB用于TB
  2. 检查第一个参数是command_a还是command_b
  3. 根据第一个参数,我用OptDescAOptDescB解析命令行

对于点3,我必须将argc递减1,并将argv指针向前移动1。

po::store(po::parse_command_line(argc - 1, argv + 1, OptDescA), vm);

这样我就不必在OptDescAOptDescB中处理command_acommand_b

实现"命令"帮助系统的最佳方式是什么

嗯,这对我来说是最困难的。有关实现的详细信息,请参阅下面的代码。

我的帮助系统的问题是我必须键入:

app help command_a

相反,最常见的是:

app command_a help

此外,在您键入应用程序帮助后,输出为:

Available commands:
 --help arg            Display this message
 --command_a           Do command_a stuff
 --command_b           Do command_b stuff

注意丑陋的--help arg

代码

#include <iostream>
#include <string>
#include <boost/program_options.hpp>
using namespace std;

void help_system(string target);

int main(int argc, char *argv[]) 
{
    namespace po = boost::program_options;
    po::options_description command_a("Command_a options");
    command_a.add_options()
        ("option_1", po::value<int>()->required(), "option_1 desc")
        ("option_2", po::value<int>()->required(), "option_2 desc")
        ;
    po::options_description command_b("Command_b options");
    command_b.add_options()
        ("option_3", po::value<int>()->required(), "option_3 desc")
        ("option_4", po::value<int>()->required(), "option_4 desc")
        ;
    po::options_description commands("Available commands");
    commands.add_options()
        ("help", po::value<string>()->default_value(""), "Display this message")
        ("command_a", "Do command_a stuff")
        ("command_b", "Do command_b stuff")
        ;
    po::variables_map vm;
    if (string("command_a") == string(*(argv + 1))) {
        try{ po::store(po::parse_command_line(argc - 1, argv + 1, command_a), vm); }
        catch (exception &e){ cout << "Error: " << e.what() << endl; }
    }
    else if (string("command_b") == string(*(argv + 1))) {
        try{ po::store(po::parse_command_line(argc - 1, argv + 1, command_b), vm); }
        catch (exception &e){ cout << "Error: " << e.what() << endl; }
    }
    else if (string("help") == string(*(argv + 1)))
    {
        cout << commands << endl;
    }
    try { po::notify(vm); }
    catch (exception &e) { cout << "Error: " << e.what() << endl; }
    return 0;
}

void help_system(string target)
{
    if (target.c_str() == "command_a") {}  // The ideal is to do "cout << command_a" here
                                           // but right now command_a is out of the scope.
    if (target.c_str() == "command_b") {}
}