Alice
Alice Long optIons C++ Extractor is a command line parser for use with C++. Alice makes it easy to fetch a command line options, without the need for converting strings to the desired type. Alice also provides automatic help text generation, as well as the ability to export the command line in JSON format.
Obtaining Alice
The source for the latest Alice can be obtained by cloning the git repository
git clone https://github.com/milasudril/alice
To compile it, Maike is required, as well as a C++-14 complient compiler. The library can be installed by using the supplied install script:
maike ./install.sh --prefix=/home/bob
or if root
maike sudo ./install.sh
Since /usr/local
is the default prefix, Alice will be installed there.
Using Alice
An application that uses Alice needs to link to libalice
. Using Maike, the "Hello, World" application looks like
//@ { //@ "targets": //@ [{ //@ "name":"hello","type":"application" //@ ,"dependencies":[{"ref":"alice","rel":"external"}] //@ }] //@ } #include <alice/alice.hpp> ALICE_OPTION_DESCRIPTOR(OptionDescriptor ,{"Category","option-name","Option description","string",Alice::Option::Multiplicity::ZERO_OR_ONE}); int main(int argc,char** argv) { try { Alice::CommandLine<OptionDescriptor> cmdline(argc,argv); // Use the command line object. See test.cpp for more info. cmdline.help(1); } catch(const Alice::ErrorMessage& msg) { fprintf(stderr,"Command line error: %s\n",msg.data); return -1; } return 0; }
Since Alice requires C++14, additional options may be needed to the compiler. When using Maike, set the field cxxversion_min in the project configuration file to a value greater than or equal to 201402 to ensure that C++14 features are enabled.
The file test.cpp
contains a minimal example demonstrating Alice's features. Since Maike will store all targets in the __targets
directory, it can be run by executing
__targets/test
from the Alice source directory. The command
__targets/test --help
shows a description of the command line.
Creating a type alias
Alice uses quite technical names for data types. While this works well for generating the placeholder help text for the test application, it is probably not what an end user expects to see. If a built-in type is used to represent the value of a parameter, but its name is inappropriate, it is possible to define a type alias by inheriting from the corresponding version of MakeType
.
namespace Alice { template<> struct MakeType<Stringkey("length")>:public MakeType<Stringkey("double")> {}; }
Then, it is possible to use length
instead of double
in the option descriptor. If a length
needs another explanation than a double
, the description can be overrided:
namespace Alice { template<> struct MakeType<Stringkey("length")>:public MakeType<Stringkey("double")> { static constexpr const char* descriptionGet() noexcept {return "The length measured in meters";} }; }
Defining custom types
Alice can also be extended by defining custom types. For example, there might be an option that accepts Hatter
objects.
struct Hatter { std::string name; double madness; };
To add the Hatter
type, first specialize the MakeType
struct as above:
namespace Alice { template<> struct MakeType<Stringkey("hatter")> { typedef Hatter Type; static constexpr const char* descriptionGet() noexcept { return "A Hatter is entered as a pair `name,madness` where " "name is a string, and madness is a value greater than or equal to zero."; } }; }
If the print method is ever called on the command line object, add a specialization of `Alice::print`
namespace Alice { template<> void print<Hatter>(const Hatter& hatter,FILE* dest) { fprintf(dest,"{\"name\":"); print(hatter.name,dest); fprintf(dest,",\"madness\":"); print(hatter.madness,dest); fprintf(dest,"}\n"); } }
Finally, implement a parser, that converts a std::string
to a Hatter
, this takes more effort
(see test.cpp
), but below is a stub, that can be used as a starting point:
namespace Alice { template<class ErrorHandler> struct MakeValue<Hatter,ErrorHandler> { static Hatter make_value(const std::string& str); }; template<class ErrorHandler> Hatter MakeValue<Hatter,ErrorHandler>::make_value(const std::string& str) { Hatter ret; // Convert `str` into a Hatter somehow... return std::move(ret); } }