Lightweight C++ command line option parser

Overview

Build Status

Release versions

Note that master is generally a work in progress, and you probably want to use a tagged release version.

Version 3 breaking changes

If you have used version 2, there are a couple of breaking changes in (the as yet unreleased, current master) version 3 that you should be aware of. If you are new to cxxopts you can skip this section.

The parser no longer modifies its arguments, so you can pass a const argc and argv and expect them not to be changed.

The ParseResult object no longer depends on the parser. So it can be returned from a scope outside the parser and still work. Now that the inputs are not modified, ParseResult stores a list of the unmatched arguments. These are retrieved like follows:

auto result = options.parse(argc, argv);
result.unmatched(); // get the unmatched arguments

Quick start

This is a lightweight C++ option parser library, supporting the standard GNU style syntax for options.

Options can be given as:

--long
--long=argument
--long argument
-a
-ab
-abc argument

where c takes an argument, but a and b do not.

Additionally, anything after -- will be parsed as a positional argument.

Basics

#include <cxxopts.hpp>

Create a cxxopts::Options instance.

cxxopts::Options options("MyProgram", "One line description of MyProgram");

Then use add_options.

options.add_options()
  ("d,debug", "Enable debugging") // a bool parameter
  ("i,integer", "Int param", cxxopts::value<int>())
  ("f,file", "File name", cxxopts::value<std::string>())
  ("v,verbose", "Verbose output", cxxopts::value<bool>()->default_value("false"))
  ;

Options are declared with a long and an optional short option. A description must be provided. The third argument is the value, if omitted it is boolean. Any type can be given as long as it can be parsed, with operator>>.

To parse the command line do:

auto result = options.parse(argc, argv);

To retrieve an option use result.count("option") to get the number of times it appeared, and

result["opt"].as<type>()

to get its value. If "opt" doesn't exist, or isn't of the right type, then an exception will be thrown.

Note that the result of options.parse should only be used as long as the options object that created it is in scope.

Unrecognised arguments

You can allow unrecognised arguments to be skipped. This applies to both positional arguments that are not parsed into another option, and -- arguments that do not match an argument that you specify. This is done by calling:

options.allow_unrecognised_options();

and in the result object they are retrieved with:

result.unmatched()

Exceptions

Exceptional situations throw C++ exceptions. There are two types of exceptions: errors defining the options, and errors when parsing a list of arguments. All exceptions derive from cxxopts::OptionException. Errors defining options derive from cxxopts::OptionSpecException and errors parsing arguments derive from cxxopts::OptionParseException.

All exceptions define a what() function to get a printable string explaining the error.

Help groups

Options can be placed into groups for the purposes of displaying help messages. To place options in a group, pass the group as a string to add_options. Then, when displaying the help, pass the groups that you would like displayed as a vector to the help function.

Positional Arguments

Positional arguments can be optionally parsed into one or more options. To set up positional arguments, call

options.parse_positional({"first", "second", "last"})

where "last" should be the name of an option with a container type, and the others should have a single value.

Default and implicit values

An option can be declared with a default or an implicit value, or both.

A default value is the value that an option takes when it is not specified on the command line. The following specifies a default value for an option:

cxxopts::value<std::string>()->default_value("value")

An implicit value is the value that an option takes when it is given on the command line without an argument. The following specifies an implicit value:

cxxopts::value<std::string>()->implicit_value("implicit")

If an option had both, then not specifying it would give the value "value", writing it on the command line as --option would give the value "implicit", and writing --option=another would give it the value "another".

Note that the default and implicit value is always stored as a string, regardless of the type that you want to store it in. It will be parsed as though it was given on the command line.

Boolean values

Boolean options have a default implicit value of "true", which can be overridden. The effect is that writing -o by itself will set option o to true. However, they can also be written with various strings using =value. There is no way to disambiguate positional arguments from the value following a boolean, so we have chosen that they will be positional arguments, and therefore, -o false does not work.

std::vector<T> values

Parsing of list of values in form of an std::vector<T> is also supported, as long as T can be parsed. To separate single values in a list the definition CXXOPTS_VECTOR_DELIMITER is used, which is ',' by default. Ensure that you use no whitespaces between values because those would be interpreted as the next command line option. Example for a command line option that can be parsed as a std::vector<double>:

--my_list=1,-2.1,3,4.5

Options specified multiple times

The same option can be specified several times, with different arguments, which will all be recorded in order of appearance. An example:

--use train --use bus --use ferry

this is supported through the use of a vector of value for the option:

options.add_options()
  ("use", "Usable means of transport", cxxopts::value<std::vector<std::string>>())

Custom help

The string after the program name on the first line of the help can be completely replaced by calling options.custom_help. Note that you might also want to override the positional help by calling options.positional_help.

Example

Putting all together:

int main(int argc, char** argv)
{
    cxxopts::Options options("test", "A brief description");

    options.add_options()
        ("b,bar", "Param bar", cxxopts::value<std::string>())
        ("d,debug", "Enable debugging", cxxopts::value<bool>()->default_value("false"))
        ("f,foo", "Param foo", cxxopts::value<int>()->default_value("10"))
        ("h,help", "Print usage")
    ;

    auto result = options.parse(argc, argv);

    if (result.count("help"))
    {
      std::cout << options.help() << std::endl;
      exit(0);
    }
    bool debug = result["debug"].as<bool>();
    std::string bar;
    if (result.count("bar"))
      bar = result["bar"].as<std::string>();
    int foo = result["foo"].as<int>();

    return 0;
}

Linking

This is a header only library.

Requirements

The only build requirement is a C++ compiler that supports C++11 features such as:

  • regex
  • constexpr
  • default constructors

GCC >= 4.9 or clang >= 3.1 with libc++ are known to work.

The following compilers are known not to work:

  • MSVC 2013

TODO list

  • Allow unrecognised options.
Issues
  • options.help({}) doesn't show positional arguments sometimes

    options.help({}) doesn't show positional arguments sometimes

    Code sample:

    int main(int argc, char *argv[]) {
        try {
            cxxopts::Options options(argv[0], "Sample");
            options.positional_help("<Extra args>");
            
            options.add_options()
            ("s,set", "Set whatever.", cxxopts::value<std::vector<std::string>>())
            ("h,help", "Print help and exit.")
            ;
           
            options.parse(argc, argv);
            options.parse_positional({"file", "remove-label", "set-label"});
           
            // help
            if (options.count("help")) {
            cout << options.help({""}) << std::endl;
            exit(0);
            }
        } catch (const cxxopts::OptionException& e) {
            cout << "error parsing options: " << e.what() << std::endl;
            exit(-1);
            }
        return 0;
    }
    

    Expected: Show the "set" option in the help. Actual: Show only "help" option.

    opened by assapir 19
  • Compiler error when calling parse function with mutable argv

    Compiler error when calling parse function with mutable argv

    Since #99 was merged (I’m using cxxopts 2.1.0 now), simple usage examples like the following fail:

    #include <cxxopts.hpp>
    
    int main(int argc, char *argv[])
    {
    	cxxopts::Options options("test");
    	options.parse(argc, argv);
    
    	return 0;
    }
    

    with the error message (g++ 7.3.1):

    test.cpp: In function ‘int main(int, char**)’:
    test.cpp:6:26: error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
      options.parse(argc, argv);
                              ^
    In file included from test.cpp:1:0:
    cxxopts.hpp:1642:1: note:   initializing argument 2 of ‘cxxopts::ParseResult cxxopts::Options::parse(int&, const char**&)’
     Options::parse(int& argc, const char**& argv)
     ^~~~~~~
    test.cpp:6:26: error: cannot bind rvalue ‘(const char**)argv’ to ‘const char**&’
      options.parse(argc, argv);
    

    The reason is that char *argv[] (or char **argv) cannot be implicitly converted to const char **, which is used in all parse function signatures.

    I know that #99 added the const qualifier for a reason. I like the idea suggested by @vladimirgamalyan in #91 to turn const char **&argv in the parse function signatures into const char * const *&argv. However, I think that’s not possible right now, because argv is modified by cxxopts such as in:https://github.com/jarro2783/cxxopts/blob/0fe1dc892bcbef48b3911510209c7033f31ce05e/include/cxxopts.hpp#L1681

    Still, I think that this should be addressed, because int main(int argc, char *argv[]) is a standard main function signature, which should be supported by cxxopts. If that’s not feasible, it would be good to mention this in the readme at least :slightly_smiling_face:.

    opened by pluehne 17
  • Making sure that the library can compile without warnings even when crazy pedantic flags are set

    Making sure that the library can compile without warnings even when crazy pedantic flags are set

    We use cxxopts in simdjson since some of our users get upset if they get warnings (sometimes calling these warnings 'bugs').

    We can disable the warnings on our end, but it might be nicer for everyone if cxxopts was also "warning free". This PR should help.

    It does two things:

    • It adds the "{}" suffix to class-type attributes that are not explicitly initialized by all constructors. This effectively makes sure that they are initialized with a default constructor.
    • It disables some specific GCC warning for the duration of the definition/declaration of a class.

    None of these changes should impact the performance or the functionality of the library.

    Note that it is not my claim that I am fixing defects. This is purely to save time in the long term by not getting warnings.

    cc @jkeiser


    This change is Reviewable

    opened by lemire 14
  • Improve formatting of help descriptions

    Improve formatting of help descriptions

    • new function: cxxopts::Option::set_width(size_t width) Set the size of a helpline.
    • new function: cxxopts::Option::set_tab_expansion() Expand the tabs in descriptions. The tabsize 8 chars, base is start of description. The descriptions are not disturbed by adding additional options.
    • Allow newlines \n nad tabs \t in descriptions.

    Other changes (last commit/new commit):

    • 1453/1471: size_t for OPTION_LONGEST and OPTION_DESC_GAP. This prevents the static cast in 2086/2140.
    • 2088/2142: in case of small width the value of "width - longest - OPTION_DEC_GAP" becomes negative. Because size_t is unsigned the result is a big number, and the width of the column of the descriptions is not shortened.
    • new 2143: When the given width is too small, it is set to longest + OPTION_DESC_GAP + 10
    • new 1570: A long description is broken into multiple lines, and the iterator lastSpace remembers the begin of the last word. But when the iterator current reaches the end of line, the whole string from iterator is printed, which in soome cases is too long. Thats why one blank is added to the description to trigger the handling of lastSpace. Accordingly in 1574/1627 the line is shortened by one char.

    This change is Reviewable

    opened by wgahr123 13
  • No support for short name argument with no space before value

    No support for short name argument with no space before value

    getopt supports the following syntax [link]:

    % testopt -cfoo
    aflag = 0, bflag = 0, cvalue = foo
    

    However cxxopts throws option_requires_argument_exception for the same construction.

    enhancement 
    opened by Qartar 13
  • error parsing options: Option ├óΓé¼╦£t├óΓé¼Γäó does not exist

    error parsing options: Option ‘t’ does not exist

    I get a strange strings when running this code without a valid option:

     options.add_options("")
    	("a,aaaa", "aaaa type", cxxopts::value<std::string>()->default_value("bbbb"), "bbbb or cccc")
    			("h,help", "Print help");
    	options.parse(argc, argv);
    	if (options.count("help"))
    	{
    		std::cout << options.help({ "", "Group" }) << std::endl;
    		exit(0);
    	}
    
    
    

    Build is on Windows with MSVC community 15

    opened by mulderp 12
  • Default and implicit values

    Default and implicit values

    This patch add support for default values and implicit values.

    They can be used like that:

      ("o,output", "Output file", cxxopts::value<std::string>()->default_value("a.out")->implicit_value("b.def"))
    

    You can specify either the default value or the implicit value or both. I took the same model as was done in Boost Program Options.

    While implementing this, I was wondering if the class Value was really useful, I think it would be better to directly expose default_value (renamed it to standard_value), don't you think ? It would make the code easier and it would remove the virtuality of the functions.

    I tried not to screw you code style, but my editor is not configured for that, so I may have made some mistakes on that side.

    opened by wichtounet 12
  • MACRO min/max under WINDOWS

    MACRO min/max under WINDOWS

    C:\dev\workspace\z_eph\tool\utils\cxxopts.hpp(1342): error C2589: '(': illegal token on right side of '::' 
    C:\dev\workspace\z_eph\tool\utils\cxxopts.hpp(1342): error C2062: type 'unknown-type' unexpected 
    C:\dev\workspace\z_eph\tool\utils\cxxopts.hpp(1342): error C2059: syntax error: ')' 
    C:\dev\workspace\z_eph\tool\utils\cxxopts.hpp(1346): error C2589: '(': illegal token on right side of '::' 
    C:\dev\workspace\z_eph\tool\utils\cxxopts.hpp(1346): error C2062: type 'unknown-type' unexpected 
    C:\dev\workspace\z_eph\tool\utils\cxxopts.hpp(1346): error C2059: syntax error: ')' 
    
    

    the errors related with min and max in the library cxxopts.hpp:

                longest = std::max(longest, stringLength(s));
                format.push_back(std::make_pair(s, String()));
            }
    
            longest = std::min(longest, static_cast<size_t>(OPTION_LONGEST));
    
    

    the problem (Windows specifics) usually related with that there are macro definitions for min and max. this (below) solves the problem :

    image

    I'll perform some tests and if this woks okay and will raise a PR with WINDOWS only ifdef

    invalid 
    opened by amigo421 11
  • Support not-failing with unknown options

    Support not-failing with unknown options

    Loggers should have a flag which, when set, has them not fail when encountering unknown options, but rather merely collecting them appropriately and making them accessible after parsing. This feature would be independent of whether secondary parsing is supported by the Options class or not.

    This is important in particular for the case of computational work being necessary, using the values of some command-line arguments, to determine a secondary set of command-line-settable options (e.g. by reading from some file or loading a dyanmic library and so on.)

    opened by eyalroz 10
  • MSVC warnings

    MSVC warnings

    There are several warnings when compiling with MSVC (toolset v140 = VS2015):

    1. ..\cxxopts.hpp(528): warning C4146: unary minus operator applied to unsigned type, result still unsigned

    The context:

          if (negative)
          {
            if (!is_signed)
            {
              throw argument_incorrect_type(text);
            }
            value = -result; // <<< warning C4146
          }
          else
          {
            value = result;
          }
    
    1. ..\cxxopts.hpp(442): warning C4018: '>': signed/unsigned mismatch The context:
          template <typename T>
          struct SignedCheck<T, true>
          {
            template <typename U>
            void
            operator()(bool negative, U u, const std::string& text)
            {
              if (negative)
              {
                if (u > U(-std::numeric_limits<T>::min())) // <<< warning C4018
                {
                  throw argument_incorrect_type(text);
                }
              }
              else
              {
                if (u > std::numeric_limits<T>::max())
                {
                  throw argument_incorrect_type(text);
                }
              }
            }
          };
    
    bug 
    opened by Anton-V-K 10
  • Use cmake interface library

    Use cmake interface library

    This PR uses cmake's interface library feature:

    An INTERFACE library target does not directly create build output, though it may have properties set on it and it may be installed, exported and imported.

    This makes it easier to include the header only library in a cmake project. After using add_subdirectory on the cxxopts directory, one simply needs to include cxxopts in their target_link_libraries, which will allow the user's target to inherit the properties of the cxxopts header library (see changes to example and test).

    Two things:

    (1) I updated the cmake required version to 3.1, but this may not be necessary (I believe it is necessary for target_sources, which is not available in 2.8.12, but not sure if you need target_sources for this to work).

    (2) The Unicode support is confusing. I did a git grep and couldn't find any other use for CXXOPTS_LINKER_LIBRARIES. CXXOPTS_USE_UNICODE_HELP would also make more sense as an option instead of a cached variable, and then target_compile_definitions can be used to enable CXXOPTS_USE_UNICODE in the header. With this PR making it an interface library, other projects that link with cxxopts should inheret CXXOPTS_USE_UNICODE as well. For now I left this untouched since I don't know if I'm missing something important.


    This change is Reviewable

    opened by mariobadr 10
  • pkg-config file is broken when CMAKE_INSTALL_INCLUDEDIR is absolute

    pkg-config file is broken when CMAKE_INSTALL_INCLUDEDIR is absolute

    opened by alexshpilkin 0
  • Parse command line arguments as a std::string

    Parse command line arguments as a std::string

    A straightforward implementation for #329. Works fine for enabling local program to be called from browser via system protocols. Known limitation includes no bash variable and wildcard expansion. Haven't tested for corner cases.


    This change is Reviewable

    opened by huangzonghao 2
  • Parsing command line arguments as a std::string

    Parsing command line arguments as a std::string

    Wondering if there is any plan to add cxxopt::Options::parser(int argc, std::string argv) into the library, or accept a pull request for this function.

    I think a good reason to include this feature in the library is to deal with protocol calls from browser or other applications where all the input arguments are passed in as a long string in url format. And currently I am running a pre-parser to convert the string to char** argv, but I think it would be good to have the library parse the string directly.

    opened by huangzonghao 1
  • Fixed cmake lib install path in case of empty CMAKE_LIBRARY_ARCHITECTURE

    Fixed cmake lib install path in case of empty CMAKE_LIBRARY_ARCHITECTURE

    In case CMAKE_LIBRARY_ARCHITECTURE is empty (e.g. on NixOS), the replace pattern for CMAKE_INSTALL_LIBDIR_ARCHIND would replace all slashes in CMAKE_INSTALL_LIBDIR path. The best way would be to leave that path as is.


    This change is Reviewable

    opened by yl3dy 0
  • Doesn't wrap `help_string` if it's too long

    Doesn't wrap `help_string` if it's too long

    I have

    cxxopts::Options optionParser("my_program", "long string...");
    

    where "long string..." is quite long (more than 80 characters). I expect it to be wrapped across multiple lines, but cxxopts just prints it as-is, without wrapping.

    opened by alex65536 8
  • arguments() contains empty keys when existing short-only options

    arguments() contains empty keys when existing short-only options

    When use a short-only options name, ParseResult::arguments.key() will be empty string, because only long_name will be insert into m_sequential in parse_option:

    // line 2164~2178
    inline
    void
    OptionParser::parse_option
    (
      const std::shared_ptr<OptionDetails>& value,
      const std::string& /*name*/,
      const std::string& arg
    )
    {
      auto hash = value->hash();
      auto& result = m_parsed[hash];
      result.parse(value, arg);
    
      m_sequential.emplace_back(value->long_name(), arg); // empty key could be insert into m_sequential when option is short-only name.
    }
    

    Also, arguments_string() will output parse results with no name like (where I set short-only option n=16 and m=8):

     = 16
     = 8
    help = false (default)
    long = false (default)
    

    Possible solution: Add essential_name() to OptionsDetails, which return long name, or short name when long name is empty. And use these as key in m_sequential and m_defaults

    Maybe I will create a PR to solve these.

    opened by ldeng-ustc 0
Releases(v3.0.0)
  • v3.0.0(May 2, 2022)

    This is a major new release. The most significant change is that the parser now returns an object with the parse result, and does not modify argc or argv. The result object does not depend on the parser, so the following is now possible:

    auto result = options.parse(argc, argv);
    return result;
    

    What's Changed

    Changed

    • Only search for a C++ compiler in CMakeLists.txt.
    • Allow for exceptions to be disabled.
    • Fix duplicate default options when there is a short and long option.
    • Add CXXOPTS_NO_EXCEPTIONS to disable exceptions.
    • Fix char parsing for space and check for length.
    • Change argument type in Options::parse from char** to const char**.
    • Refactor parser to not change its arguments.
    • ParseResult doesn't depend on a reference to the parser.
    • Fixed several warnings and code quality issues.
    • Improved formatting for help descriptions.
    • Improve integer parsing.

    Added

    • A list of unmatched arguments is available in ParseResult.
    • Support single letter options with argument attached.
    • Use if it is present.

    Bug Fixes

    • Fix missing option name in exception.
    Source code(tar.gz)
    Source code(zip)
CLI11 is a command line parser for C++11 and beyond that provides a rich feature set with a simple and intuitive interface.

CLI11: Command line parser for C++11 What's new • Documentation • API Reference CLI11 is a command line parser for C++11 and beyond that provides a ri

null 2.1k May 10, 2022
A simple to use, composable, command line parser for C++ 11 and beyond

Lyra A simple to use, composing, header only, command line arguments parser for C++ 11 and beyond. Obtain License Standards Stats Tests License Distri

Build Frameworks Group 337 May 8, 2022
Tiny command-line parser for C / C++

tinyargs Another commandline argument parser for C / C++. This one is tiny, source only, and builds cleanly with -Wall -pedantic under C99 and C++11 o

Erik Agsjö 5 Nov 11, 2021
led is a line-oriented text editor in command line

led is a line-oriented text editor in command line. This editor is similar to the standard program on unix systems - GNU ed. But i'm not going to make an exact clone of that program, it's just a pet project.

Artem Mironov 9 Mar 4, 2022
LwSHELL is lightweight, platform independent, command line shell for embedded systems.

LwSHELL is lightweight, platform independent, command line shell for embedded systems. It targets communication with embedded systems from remote terminal to quickly send commands and the retrieve data from the device.

Tilen Majerle 47 May 6, 2022
udmp-parser: A Windows user minidump C++ parser library.

udmp-parser: A Windows user minidump C++ parser library. This is a cross-platform (Windows / Linux / OSX / x86 / x64) C++ library that parses Windows

Axel Souchet 86 May 1, 2022
A library for interactive command line interfaces in modern C++

cli A cross-platform header only C++14 library for interactive command line interfaces (Cisco style) Features Header only Cross-platform (linux and wi

Daniele Pallastrelli 782 May 9, 2022
A single header C++ library for parsing command line arguments and options with minimal amount of code

Quick Arg Parser Tired of unwieldy tools like getopt or argp? Quick Arg Parser is a single header C++ library for parsing command line arguments

null 44 Feb 21, 2022
CLIp is a clipboard emulator for a command line interface written in 100% standard C only. Pipe to it to copy, pipe from it to paste.

CLIp v2 About CLIp is a powerful yet easy to use and minimal clipboard manager for a command line environment, with no dependencies or bloat. Usage Sy

A.P. Jo. 12 Sep 18, 2021
pbr2gltf2 is a command line tool for converting PBR images to a glTF 2.0 material.

pbr2gltf2 is a command line tool for converting PBR images to a glTF 2.0 material. The tool is detecting depending on the filename, which PBR information is stored. It swizzles the images and does reassign the channels to a glTF 2.0 image. The tool stores the images plus a minimal, valid glTF 2.0 file containing the required material, textures and images.

UX3D GmbH 22 Jan 11, 2022
null 76 Apr 18, 2022
A command-line tool to display colorful distro information.

sjfetch A command-line tool to display colorful distro information.

Fikret Musk 6 Apr 6, 2022
Toybox: all-in-one Linux command line.

Toybox: all-in-one Linux command line.

Rob Landley 1.6k May 3, 2022
Simple command line tool that processes image files using the FidelityFX Super Resolution (FSR) or Contrast Adaptive Sharpening (CAS) shader systems.

Simple command line tool that processes image files using the FidelityFX Super Resolution (FSR) or Contrast Adaptive Sharpening (CAS) shader systems.

GPUOpen Effects 164 May 3, 2022
Command-line flag parsing in C

flag.h Inspired by Go's flag module: https://pkg.go.dev/flag WARNING! The design of the library is not finished and may be a subject to change. Quick

Tsoding 34 May 1, 2022
A command line tool with no external dependencies to print information about an X server instance.

xinfo A command line tool with no external dependencies to print information about an X server instance. Building and running To build the code in thi

Jean-Michel Gorius 6 Jan 13, 2022
Windows command line program for Spleeter, written in pure C, no need of Python.

SpleeterMsvcExe is a Windows command line program for Spleeter, which can be used directly. It is written in pure C language, using ffmpeg to read and write audio files, and using Tensorflow C API to make use of Spleeter models. No need to install Python environment, and it does not contain anything related to Python.

Wudi 146 May 4, 2022
easy to use, powerful & expressive command line argument parsing for modern C++ / single header / usage & doc generation

clipp - command line interfaces for modern C++ Easy to use, powerful and expressive command line argument handling for C++11/14/17 contained in a sing

André Müller 872 May 11, 2022
Parse command line arguments by defining a struct

Parse command line arguments by defining a struct Quick Start #include <structopt/app.hpp> struct Options { // positional argument // e.g., .

Pranav 389 May 11, 2022