Давеча на глаза попалась информация о двух новых библиотеках для работы с аргументами командной строки в современном C++. Поскольку в G+ ленте нет возможности поиска по своим же собственным постам (что печально), то зафиксирую информацию об этих библиотеках в блоге, дабы было проще найти при случае. Сразу скажу, я эти библиотеки пока не использовал, даже в код не заглядывал. Но судя по тому, что видно на поверхности, выглядит очень вкусно.
Итак, первая библиотека -- Clara от автора отличного инструмента для TDD и BDD в C++, Catch/Catch2 (с недавних пор библиотека называется именно Catch2). Clara изначально развивалась внутри Catch, но при подготовке Catch2 ее выделили в отдельный проект. Получается, что Clara является более-менее проверенной библиотекой, все-таки Catch2 используется весьма активно. Плюс работает на разных платформах и с разными компиляторами. Но, с другой стороны, документация пока оставляет желать много лучшего.
Пример того, как может выглядеть работа с Clara я выдрал из unit-тестов для нее:
using namespace clara;
struct TestOpt {
std::string processName;
std::string fileName;
int number = 0;
int index = 0;
bool flag = false;
std::string firstPos;
std::string secondPos;
std::vector<std::string> unpositional;
auto makeCli() -> Parser {
return ExeName( processName )
| Opt( fileName, "filename" )
["-o"]["--output"]
( "specifies output file" )
| Opt( number, "an integral value" )
["-n"]
| Opt( [&]( int i ) {
if (i < 0 || i > 10)
return ParserResult::runtimeError("index must be between 0 and 10");
else {
index = i;
return ParserResult::ok( ParseResultType::Matched );
}
}, "index" )
["-i"]
( "An index, which is an integer between 0 and 10, inclusive" )
| Opt( flag )
["-f"]
( "A flag" )
| Arg( firstPos, "first arg" )
( "First position" )
| Arg( secondPos, "second arg" )
( "Second position" );
}
};
|
Здесь метод TestOpt::makeCli как раз и создает парсер аргументов командной строки, который сохраняет разобранные значения внутри экземпляра структуры TestOpt.
Как и положено такого рода инструментам Clara автоматически генерирует usage-string, который можно отобразить пользователю.
Второй инструмент -- это clipp. Так же header-only, так же ему достаточно только стандартной библиотеки современного C++. Средства описания аргументов командной строки похожи на таковые в Clara, но, как мне показалось, здесь все более продвинуто:
#include <iostream>
#include "clipp.h"
using namespace clipp;
using std::cout;
using std::string;
int main(int argc, char* argv[]) {
bool rec = false, utf16 = false;
string infile = "", fmt = "csv";
auto cli = (
value("input file", infile),
option("-r", "--recursive").set(rec).doc("convert files recursively"),
option("-o") & value("output format", fmt),
option("-utf16").set(utf16).doc("use UTF-16 encoding")
);
if(!parse(argc, argv, cli)) cout << make_man_page(cli, argv[0]);
// ...
}
|
Если с аргументами что-то не так, то можно автоматически сгенерировать вот такой текст:
SYNOPSIS
convert <input file> [-r] [-o <output format>] [-utf16]
OPTIONS
-r, --recursive convert files recursively
-utf16 use UTF-16 encoding
Библиотека использует перегрузку операторов, что позволяет записывать вот такие-вот DSL-и:
auto cli = (
option("-b") % "activates b" >> b,
option("-c", "--noc") % "deactivates c" >> set(c,false),
option("--hi") % "says hi" >> []{cout << "hi!\n";} );
|
Вообще, документация оставляет самые приятные впечатления. А вот по поводу кода на Reddit-е высказали замечания. С которыми автор библиотеки согласился и пояснил, что разработка еще не завершена и, например, под MSVC он пока особо ничего не проверял. Так что дока хорошая, а вот либа еще сырая. Хотя желание попробовать вызывает.