おかしいな、今やってたんだ。ここでは一般的な考え方だけを説明します。完全なコードは現在 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()
単一の操作のみが必要な場合は、プレーンな仮想メソッドに戻すことができます。
私はこれがかなりきれいであることを願っています。利用可能なツールやライブラリがたくさんあることは知っていますが、私はこの方法が本当に好きです。準備ができたら実装を共有できます。ほぼ完了です。