おかしいな、今やってたんだ。ここでは一般的な考え方だけを説明します。完全なコードは現在 500 行を超えており、書式設定などにより多くのユーティリティを使用しています。
例として、私はプログラムを作成していますhelp(これはかなりダミーです)。単純な構造体には、プログラムが必要とするすべてのオプションと、デフォルト値が含まれています。
struct help_opt
{
string owner;
string path;
bool rec;
int depth;
help_opt() : owner(""), path("/"), rec(false), depth(0) { }
};
別の構造体は、コマンド ライン引数をモデル化します。
struct help_args : public help_opt, public arguments <help_args>
{
template <typename S>
void define(S& s)
{
set(s, owner, "owner", 'w', "force <name> as owner", "name");
set(s, path, "output", 'o', "save all output to <path>", "path");
set(s, rec, "recurse", 'r', "recurse into sub-topics");
set(s, depth, "depth", 'd', "set <number> as maximum depth", "number");
}
string title() const { return "my help"; }
string usage() const { return "help [<options>] [<topic>]"; }
string info() const
{
return
"Display help on <topic>, "
"or list available topics if no <topic> is given.";
}
help_args(int argc, char* argv[]) : arguments(argc, argv) { }
};
classargumentsは必要なすべてのインフラストラクチャです。すべての引数とメタデータ (名前、略語など) はdefine()、それぞれメソッドの呼び出しによって で定義されset()ます。
引数sは、ユーザー入力の収集、ヘルプ テキストの作成、ユーザーが指定した値の表示など、複数の操作をサポートするために使用されます。次に、各メンバーへの参照を渡します。ユーザー入力に応じて適切な値が与えられるか、デフォルト値のままになります。次に、引数名、略語、完全なヘルプ テキスト、およびオプションでパラメーター名が続きます。ブール引数は、パラメーターなしでフラグとして個別に扱われます。
追加のメソッドtitle()などinfo()は、プログラムに固有の情報メッセージを指定します。
実際の処理は のコンストラクタによって行われargumentsます。これが を呼び出しdefine()、help_args次に が を呼び出しset()ますarguments。オプションごとに、コマンド ライン入力がスキャンされ、必要に応じて変数が更新されます。同時に、メタデータが収集され、gnu プログラムのよう--helpに--usage、、、などのオプションの出力が自動的に生成されます。--version
help_argsテンプレートパラメータとして渡されるという事実は、それがテンプレートであるため仮想ではないにもかかわらず、基本クラスから呼び出されるargumentsことを許可 することです。define()単一の操作のみが必要な場合は、プレーンな仮想メソッドに戻すことができます。
私はこれがかなりきれいであることを願っています。利用可能なツールやライブラリがたくさんあることは知っていますが、私はこの方法が本当に好きです。準備ができたら実装を共有できます。ほぼ完了です。