Skip to content
gershnik edited this page Apr 3, 2022 · 4 revisions

General

The basic structure of using Argum parser is as follows

  • Create a parser
  • Configure it, providing callbacks for options and positional arguments
  • Parse command line and handle possible exceptions

If you want to use exceptions (see Error reporting mode and Error Handling), the basic scaffolding looks something like this

#include <argum/parser.h>
//or #include "argum.h" if you use a single header distribution
//or import Argum; if you use module distribution

//This is for output below - feel free to use something else
#include <iostream>

//everything in Argum library is in this namespace. 
using namespace Argum;

int main(int argc, char * argv[]) {

    Parser parser; //create with default settings

    /* configuration goes here */

    try {
        //parse the arguments starting from argv[1] (if exists)
        parser.parse(argc, argv);
    } catch (ParsingException & ex) {
        //all parsing issues are reported via classes derived from ParsingException
        //message() contains human readable message
        std::cerr << ex.message() << '\n';
        //print the formatted usage string. The argument to formatUsage 
        //is the name of our program to start the usage string
        std::cerr << parser.formatUsage(argc ? argv[0] : "prog") << '\n';
        return EXIT_FAILURE;
    }
}

If you use expected values then the last part would be

    //parse the arguments starting from argv[1] (if exists)
    auto result = parser.parse(argc, argv);
    if (auto error = result.error()) {
        //error is a shared_ptr to ParsingException 
        //all error classes are derived from ParsingException
        //message() contains human readable message
        std::cerr << error->message() << '\n';
        //print the formatted usage string. The argument to formatUsage 
        //is the name of our program to start the usage string
        std::cerr << parser.formatUsage(argc ? argv[0] : "prog") << '\n';
        return EXIT_FAILURE;
    }

Assuming this code has been compiled into an application named prog following are the results of running it:

$ ./prog
$ ./prog --help
unrecognized option: --help
Usage: ./prog
$ ./prog foo
unexpected argument: foo
Usage: ./prog

As you can see, the program accepts no command line arguments at all. Note, that unlike some other parsers, Argum does not automatically add --help option. You can see how to add it on the Adding Help page.

This example demonstrates the basics of handling errors and displaying usage information to the user. All errors produced during parsing are reported via classes derived from ParsingException (itself a subclass of std::exception). These errors are thrown in exception mode or returned in the Expected return value. See Handling Errors for more details.

We handle the error by printing the error message and the program's short usage string. Note that we have to pass the name of our program to formatUsage. It does not make any assumptions of what the name you want printed is or whether it should be taken from argv[0]. It is common to use argv[0] but it is not the only choice - some people prefer to hardcode the name.

IMPORTANT: if you want to use argv[0] never assume that argc > 0 and so argv[0] is valid. See this vulnerability for gory details of what can happen if you do.

In addition to standard what() method that can be used to display error information ParsingException also has the message() method, used above. The difference between the two is that message() returns a string_view and has a wchar_t counterpart. Here is the same code for Windows wmain() that uses wchar_t throughout.

int wmain(int argc, wchar_t * argv[]) {

    WParser parser;

    try {
        parser.parse(argc, argv);
    } catch (WParsingException & ex) {
        std::wcerr << ex.message() << L'\n';
        std::wcerr << parser.formatUsage(argc ? argv[0] : L"prog") << L'\n';
        return EXIT_FAILURE;
    }
}

Note the W prefix on Parser and ParsingException. Argum follows the same pattern as std::string/std::wstring in this respect. Most of the examples in this wiki are using narrow chars for simplicity. You can always convert them to wchar_t by simple substitution of W prefixes and adding L to strings.

Further Reading

Error Handling
Thread Safety
Adding Help
Defining Options
Positional Arguments