C++向け簡易コマンドラインパーザ cmdline
を作りました。
http://github.com/tanakh/cmdline
何か
コマンドライン引き数の解析を助けるライブラリです。同じ目的のライブラリに、Cの標準関数であるgetoptやgoogleのgflagsなどがありますが、cmdlineは適当に使えてそこそこ便利というのを目指しています。getoptは使いにくいし、usageも自分で書く必要がある。gflagsはライブラリをインストールしたり、リンクしたりちょっと大掛かり。cmdlineは、1ヘッダファイルで、コピーするだけで使えて、修正BSDライセンスで公開しているので、自由にプログラムに取り込んでいただけます。
コードサンプル
#include "cmdline.h" int main(int argc, char *argv[]) { cmdline::parser p; p.add("hoge", 'h', "hoge flag with no value"); p.add<int>("moge", 'm', "moge flag with int value", false, 123); p.add("help", 0, "print help"); // add other flags... if (!p.parse(argc, argv)||p.exist("help")){ std::cout<<p.error_full()<<p.usage(); return 0; } // main code... if (p.exist("hoge")) std::cout<<"there is hoge flag"<<std::endl; std::cout<<"moge value: "<<p.get<int>("moge")<<std::endl; // ... }
上プログラムのように、cmdline::parserのオブジェクトを生成してやり、parser::add()によりフラグを追加し、parser::parse()を呼び出します。実行例です。
> ./a.out --help usage: ./a.out [options] ... options: -h, --hoge hoge flag with no value -m, --moge moge flag with int value (int [=123]) --help print help > ./a.out --moge=777 -h there is hoge flag moge value: 777 > ./a.out --moge=huga option value is invalid: --moge=huga usage: ./a.out [options] ... options: -h, --hoge hoge flag with no value -m, --moge moge flag with int value (int [=123]) --help print help
マニュアル
parser::add(const string &name, char short_name, const string &description)
値を持たないフラグを定義します。フルネーム、短縮名、フラグの説明、の順です。短縮名に0を指定すると、短縮名なしになります。
template void parser::add(const std::string &name, char short_name=0, const std::string &desc="", bool need=true, const T def=T())
値を持つフラグを定義します。必須なのは、フルネーム、短縮名、フラグの説明(と、テンプレートパラメータである型)です。オプショナルな引き数として、そのフラグが必須か(必須ならば、コマンドラインで与えられないときにparseがエラーになります)と、フラグ値が与えられなかったときのデフォルトの値があります。短縮名を0にすると短縮名なしになるのは上と同じです。
template void parser::add(const std::string &name, char short_name=0, const std::string &desc="", bool need=true, const T def=T(), F reader=F())
上と同じく、値を持つフラグを定義します。値に対するカスタムreaderをセットできます。上のメソッドでは、デフォルトのreaderとして、lexical_cast
bool parser::parse(int argc, char *argv[])
コマンドライン引き数を解析します。mainの引き数をそのまま渡します。失敗したらfalse、成功したらtrueが返ります。失敗した場合、parser::error()で具体的なエラーメッセージが取得できます。
bool parser::exist(const string &name)
コマンドライン引き数に与えられたフラグが存在していたかを返します。parser::parse()した後に使います。
template const T &parser::get(const std::string &name)
与えられたフラグの値を返します。parser::parse()した後に使います。フラグ名が不正(addされていない)、もしくは型がaddしたときとかみ合わない場合、cmdline::cmdline_error例外が投げられます。
const std::vector &parser::rest()
コマンドライン引き数のうち、コマンドラインオプションと認識されなかった引き数が格納される配列が返されます。オプションのほかにファイル名などを引き数として取りたい場合などに使えます。
std::string parser::error()
一つ目のエラーメッセージを返します。
std::string parser::error_full()
すべてのエラーメッセージを返します。
std::string parser::usage()
usageを返します。
void parser::footer(const std::string &f)
usageが返す文字列のusageの行の後ろに文字列を追加できます。
void parser::set_progam_name(const std::string &name)
usageのusageの行に表示されるプログラム名をセットできます。この関数でセットしない場合、プログラム名としてはargv[0]が使われます。
カスタムreader
デフォルトでは、フラグの値を読むのに、lexical_cast(のような自前のもの)が使われます。このため、add
p.add<int>("hoge", 'h', "int value (100 - 999)", cmdline::range(100, 999)); p.add<string>("moge", 'm', "one of abd, def, ghi", cmdline::oneof<string>("abc", "def", "ghi"));
関数合成的な演算子を用意して、ごりごりと合成できるほうがいいかなとも思いましたが、独自の演算子を定義して、それを覚えてもらうのもよくないかなと思ってやめました。とにかく覚えること少なくて、ぬるく使えるように。