jarro2783 / cxxopts

Lightweight C++ command line option parser
MIT License
4.16k stars 582 forks source link

short arg unable to accept argument. #429

Open vipcxj opened 4 months ago

vipcxj commented 4 months ago
            cxxopts::Options opts("ai-server", "ai server");
            opts.add_options("general")
                ("h,help", "Print usage", cxxopts::value<std::vector<std::string>>()->implicit_value(""))
                ("groups", "Print all groups")
                ("print", "Print configure values of special group. Empty group means all group.", cxxopts::value<std::string>()->implicit_value(""));
            opts.add_options("cfgo")
                ("s,signal_url", "The url of signal server of conference.go", cxxopts::value<std::string>()->default_value(get_default_opt_from_env("SR_CFGO_SIGNAL_URL", "")))
                ("appsink_drop", "Drop old buffers when the buffer queue is filled", cxxopts::value<bool>()->default_value(get_default_opt_from_env("SR_CFGO_APPSINK_DROP", "false")))
                ("appsink_max_buffers", "Maximum amount of buffers in the queue (0 = unlimited).", cxxopts::value<std::uint32_t>()->default_value(get_default_opt_from_env("SR_CFGO_APPSINK_MAX_BUFFERS", "0")))
                ("appsink_max_bytes", "Maximum amount of bytes in the queue (0 = unlimited)", cxxopts::value<std::uint64_t>()->default_value(get_default_opt_from_env("SR_CFGO_APPSINK_MAX_BYTES", "0")))
                ("appsink_max_time", "Maximum total duration of data in the queue (0 = unlimited)", cxxopts::value<std::uint64_t>()->default_value(get_default_opt_from_env("SR_CFGO_APPSINK_MAX_TIME", "0")));>implicit_value(""));
            auto result = opts.parse(argc, argv);
            if (result.count("help"))
            {
                auto & groups = result["help"].as<std::vector<std::string>>();
                for (auto && g : groups)
                {
                    std::cout << "group: " << g << std::endl;
                }
                if (groups.size() == 1 && groups[0].empty())
                {
                    std::cout << opts.help(opts.groups()) << std::endl;
                }
                else
                {
                    std::cout << opts.help(groups) << std::endl;
                }
                exit(0);
            }

main --help=general,cfgo print:

group: general
group: cfgo
ai server
Usage:
  ai-server [OPTION...]

 general options:
  -h, --help [=arg(=)]   Print usage
      --groups           Print all groups
      --print [=arg(=)]  Print configure values of special group. Empty 
                         group means all group.

 cfgo options:
  -s, --signal_url arg          The url of signal server of conference.go 
                                (default: "")
      --appsink_drop            Drop old buffers when the buffer queue is 
                                filled
      --appsink_max_buffers arg
                                Maximum amount of buffers in the queue (0 = 
                                unlimited). (default: 0)
      --appsink_max_bytes arg   Maximum amount of bytes in the queue (0 = 
                                unlimited) (default: 0)
      --appsink_max_time arg    Maximum total duration of data in the queue 
                                (0 = unlimited) (default: 0)

main -hgeneral,cfgo print:

terminate called after throwing an instance of 'cxxopts::exceptions::no_such_option'
  what():  Option 'g' does not exist
Aborted (core dumped)

main -h general,cfgo print

group: 
ai server
Usage:
  ai-server [OPTION...]
  ...

cxxopts think no argument is put to h opt. so goup is implicit_value {""}

By the way, how to make implicit_value of std::vector as empty vector? "" means a vector with one empty string element, it's too strange.

jarro2783 commented 3 months ago

The implicit value syntax is a bit odd because you are giving it a string that is parsed rather than an actual value of the type that you want. I wonder if that should be changed. It might be that a short option with an argument attached doesn't work when it has an implicit value.

For your second example where it just ignores the argument, it thinks that general,cfgo is a positional parameter. This is an ambiguity problem that has been brought up a few times. The problem is that since no argument is required, there is no good way to determine if the next string is an argument to your option or a positional argument.

vipcxj commented 3 months ago

For your second example where it just ignores the argument, it thinks that general,cfgo is a positional parameter. This is an ambiguity problem that has been brought up a few times. The problem is that since no argument is required, there is no good way to determine if the next string is an argument to your option or a positional argument.

I know there should not be any space between -h and general,cfgo. Because -hgeneral,cfgo not work, I try the wrong one. At least the wrong one does not crash.