私が問題を正しく理解している場合は、次の形式のコマンド ライン オプションを解析する必要があります。
[--generic-option ...] cmd [--cmd-specific-option ... ]
これが私の解決策の例です。わかりやすくするために、検証コードは省略しますが、非常に簡単に追加する方法を理解していただければ幸いです。
この例では、「ls」サブコマンドと、場合によっては他のサブコマンドがあります。各サブコマンドにはいくつかの特定のオプションがあり、さらに一般的なオプションがあります。それでは、一般的なオプションとコマンド名を解析することから始めましょう。
po::options_description global("Global options");
global.add_options()
("debug", "Turn on debug output")
("command", po::value<std::string>(), "command to execute")
("subargs", po::value<std::vector<std::string> >(), "Arguments for command");
po::positional_options_description pos;
pos.add("command", 1).
add("subargs", -1);
po::variables_map vm;
po::parsed_options parsed = po::command_line_parser(argc, argv).
options(global).
positional(pos).
allow_unregistered().
run();
po::store(parsed, vm);
コマンド名に対して 1 つの定位置オプションを作成し、コマンド オプションに対して複数の定位置オプションを作成したことに注意してください。
次に、関連するコマンド名で分岐し、再解析します。argc
元のオプションを渡す代わりにargv
、認識されないオプションを文字列の配列の形式で渡します。関数はこれcollect_unrecognized
を提供できます - 私たちがしなければならないのは、(位置の) コマンド名を削除し、関連する で再解析することだけoptions_description
です。
std::string cmd = vm["command"].as<std::string>();
if (cmd == "ls")
{
// ls command has the following options:
po::options_description ls_desc("ls options");
ls_desc.add_options()
("hidden", "Show hidden files")
("path", po::value<std::string>(), "Path to list");
// Collect all the unrecognized options from the first pass. This will include the
// (positional) command name, so we need to erase that.
std::vector<std::string> opts = po::collect_unrecognized(parsed.options, po::include_positional);
opts.erase(opts.begin());
// Parse again...
po::store(po::command_line_parser(opts).options(ls_desc).run(), vm);
variables_map
コマンド固有のオプションには、一般的なオプションと同じものを使用したことに注意してください。これから、関連するアクションを実行できます。
ここに示すコード フラグメントは、いくつかの単体テストを含むコンパイル可能なソース ファイルから取得したものです。gist here で見つけることができます。ぜひダウンロードして遊んでみてください。