{"id":40641162,"url":"https://github.com/mmahnic/argumentum","last_synced_at":"2026-01-21T08:05:23.152Z","repository":{"id":51311290,"uuid":"162010647","full_name":"mmahnic/argumentum","owner":"mmahnic","description":"C++ command line parsing library","archived":false,"fork":false,"pushed_at":"2023-08-31T18:35:02.000Z","size":613,"stargazers_count":184,"open_issues_count":1,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2023-11-07T19:53:46.365Z","etag":null,"topics":["argparse","args","argument-parser","argv","command-line","cpp","cpp17","header-only","library","options","optparse","parser"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mmahnic.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-16T14:44:37.000Z","updated_at":"2023-11-01T15:33:27.000Z","dependencies_parsed_at":"2023-02-18T10:01:03.561Z","dependency_job_id":null,"html_url":"https://github.com/mmahnic/argumentum","commit_stats":null,"previous_names":[],"tags_count":7,"template":null,"template_full_name":null,"purl":"pkg:github/mmahnic/argumentum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmahnic%2Fargumentum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmahnic%2Fargumentum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmahnic%2Fargumentum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmahnic%2Fargumentum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mmahnic","download_url":"https://codeload.github.com/mmahnic/argumentum/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmahnic%2Fargumentum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28629922,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["argparse","args","argument-parser","argv","command-line","cpp","cpp17","header-only","library","options","optparse","parser"],"created_at":"2026-01-21T08:05:22.391Z","updated_at":"2026-01-21T08:05:23.146Z","avatar_url":"https://github.com/mmahnic.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/mmahnic/argumentum.svg?branch=master)](https://app.travis-ci.com/mmahnic/argumentum)\n\n# Argumentum / Argparse\n\nArgumentum is a C++ library for writing command-line program interfaces. The parameters that a\nprogram supports are registered in an instance of `arument_parser`, the main library class.\n`argument_parser` processes the input arguments, checks that they are valid and converts them to C++\nvariables. It also generates help and usage messages when requested.\n\nThe parsed values are stored in normal C++ variables. Support for numeric types, `std::string`,\n`std::vector` and `std::optional` is built into the parser. Any type that can be converted from\n`string` with a constructor or an assignment operator can also be used. Other types of values are\nsupported with parsing actions. The library requires a C++17 compiler.\n\nThe library is loosely based on the Python argparse module. It covers most functionality of Python argparse. \n\n## Building\n\nThe library can be built as a static library or used as header-only.\nSee [Building and consuming the library](doc/building.md).\n\n## A basic example\n\nIn this example the program accepts integers and finds the largest one.  If the\noption `--sum` is passed to the program, the numbers are summed, instead.\n(Compare with [Python argparse](https://docs.python.org/3/library/argparse.html#example).)\n\n```c++\n#include \u003cclimits\u003e\n#include \u003cargumentum/argparse.h\u003e\n#include \u003cnumeric\u003e\n#include \u003cvector\u003e\n\nusing namespace std;\nusing namespace argumentum;\n\nint main( int argc, char** argv )\n{\n   vector\u003cint\u003e numbers;\n   bool isSum = false;\n\n   auto parser = argument_parser{};\n   auto params = parser.params();\n   parser.config().program( argv[0] ).description( \"Accumulator\" );\n   params.add_parameter( numbers, \"N\" ).minargs( 1 ).metavar( \"INT\" ).help( \"Integers\" );\n   params.add_parameter( isSum, \"--sum\", \"-s\" )\n         .nargs( 0 )\n         .help( \"Sum the integers (default: find the max)\" );\n\n   if ( !parser.parse_args( argc, argv, 1 ) )\n      return 1;\n\n   auto mmax = []( auto\u0026\u0026 a, auto\u0026\u0026 b ) { return max( a, b ); };\n   auto acc = isSum ? accumulate( numbers.begin(), numbers.end(), 0 )\n                    : accumulate( numbers.begin(), numbers.end(), INT_MIN, mmax );\n   cout \u003c\u003c acc \u003c\u003c \"\\n\";\n   return 0;\n}\n```\n\nThe basic example can be run like this:\n\n```shell\n$ basic 1 3 2\n3\n\n$ basic --sum 1 3 2\n6\n\n$ basic\nusage: basic [--sum] [--help] INT [INT ...]\n\nAccumulator\n\npositional arguments:\n  INT        Integers\n\noptional arguments:\n  -s, --sum  Sum the integers (default: find the max)\n  -h, --help Display this help message and exit.\n```\n\nThe program can read command line arguments from one or more files.  Each line of the file contains\none argument and the files can be nested.\n\n```shell\n$ cat numbers.opt\n1\n2\n3\n4\n\n$ basic @numbers.opt\n4\n\n$ basic --sum @numbers.opt @numbers.opt\n20\n\n$ cat summany.opt\n--sum\n@numbers.opt\n@numbers.opt\n@numbers.opt\n\n$ basic @summany.opt\n30\n```\n\n## Target values\n\nThe parser parses input strings and stores the parsed results in target values\nwhich are ordinary C++ variables.  The target values must outlive the parser\nbecause the parser stores target value references. On the other hand, the\nparser can be destroyed after parsing is done.\n\nThe supported types of target values are:\n\n- C++ numeric types, `bool`, `std::string`,\n- any type that has a constructor that accepts `std::string`,\n- any type that has an `operator=` that accepts `std::string`,\n- any type `T` for which a converter `argumentum::from_string\u003cT\u003e::convert` exists,\n- `std::vector` of simple target values.\n\nIf information about whether a value was set or not is needed, `std::optional` can be used:\n\n```c++\n   std::optional\u003cstd::string\u003e str;\n   params.add_parameter( str, \"-s\" ).maxargs( 1 );\n\n   // ... parser.parse_args ...\n\n   if ( !str )\n      std::cout \u003c\u003c \"The option -s was not used.\\n\";\n   else\n      std::cout \u003c\u003c \"The option -s was set with value '\" \u003c\u003c *str \u003c\u003c \"' .\\n\";\n```\n\nAdditional types can be supported through parsing actions like in the examples below.\n\n\n## Using custom actions to process options\n\nThe same example implemented with an action and a default value.  Instead of deciding on an action\nto take after the parser has done its work (`auto acc = isSum...`), we can store the algorithm to\nuse and the initial value with a function defined in `.action()`:\n\n```c++\n#include \u003cclimits\u003e\n#include \u003cargumentum/argparse.h\u003e\n#include \u003cnumeric\u003e\n#include \u003cvector\u003e\n\nusing namespace std;\nusing namespace argumentum;\n\nint main( int argc, char** argv )\n{\n   vector\u003cint\u003e numbers;\n   auto max = []( int a, int b ) { return std::max( a, b ); };\n   auto sum = []( int a, int b ) { return a + b; };\n   std::pair\u003cstd::function\u003cint( int, int )\u003e, int\u003e operation;\n\n   auto parser = argument_parser{};\n   auto params = parser.params();\n   parser.config().program( argv[0] ).description( \"Accumulator\" );\n   params.add_parameter( numbers, \"N\" ).minargs( 1 ).metavar( \"INT\" ).help( \"Integers\" );\n   params.add_parameter( operation, \"--sum\", \"-s\" )\n         .nargs( 0 )\n         .absent( std::make_pair( max, INT_MIN ) )\n         .action( [\u0026]( auto\u0026 target, const std::string\u0026 value ) {\n            target = std::make_pair( sum, 0 );\n         } )\n         .help( \"Sum the integers (default: find the max)\" );\n\n   if ( !parser.parse_args( argc, argv, 1 ) )\n      return 1;\n\n   auto acc = accumulate( numbers.begin(), numbers.end(), operation.second, operation.first );\n   cout \u003c\u003c acc \u003c\u003c \"\\n\";\n   return 0;\n}\n```\n\nThe `target` of the `.action()` is the variable we defined in `add_parameter`, in this case\n`operation`.  The `value` is ignored.  When `--sum` is used, the operation will be set to `sum()`\nwith the initial value 0.  If `--sum` is not present, the operation will be set to the defuault\n(`absent()`) value `max()` with the initial value `INT_MIN`.\n\n\n## Storing options in structures\n\nIn simple programs target variables can be declared in the function where parameters are defined and\narguments parsed.  In larger programs it is more convenient to store target variables in one or more\nstructures.  This is the same example rewritten so that it stores options in a structure:\n\n```c++\n#include \u003cclimits\u003e\n#include \u003cargumentum/argparse.h\u003e\n#include \u003cnumeric\u003e\n#include \u003cvector\u003e\n\nusing namespace std;\nusing namespace argumentum;\n\nclass AccumulatorOptions : public argumentum::Options\n{\npublic:\n   vector\u003cint\u003e numbers;\n   std::pair\u003cstd::function\u003cint( int, int )\u003e, int\u003e operation;\n\nprotected:\n   void add_parameters( ParameterConfig\u0026 params ) override\n   {\n      auto max = []( int a, int b ) { return std::max( a, b ); };\n      auto sum = []( int a, int b ) { return a + b; };\n\n      params.add_parameter( numbers, \"N\" ).minargs( 1 ).metavar( \"INT\" ).help( \"Integers\" );\n      params.add_parameter( operation, \"--sum\", \"-s\" )\n            .nargs( 0 )\n            .absent( std::make_pair( max, INT_MIN ) )\n            .action( [\u0026]( auto\u0026 target, const std::string\u0026 value ) {\n               target = std::make_pair( sum, 0 );\n            } )\n            .help( \"Sum the integers (default: find the max)\" );\n   }\n};\n\nvoid execute( AccumulatorOptions\u0026 opt )\n{\n   auto acc = accumulate(\n         opt.numbers.begin(), opt.numbers.end(), opt.operation.second, opt.operation.first );\n   cout \u003c\u003c acc \u003c\u003c \"\\n\";\n}\n\nint main( int argc, char** argv )\n{\n   auto parser = argument_parser{};\n   auto params = parser.params();\n   parser.config().program( argv[0] ).description( \"Accumulator\" );\n\n   auto pOptions = std::make_shared\u003cAccumulatorOptions\u003e();\n   params.add_parameters( pOptions );\n\n   if ( !parser.parse_args( argc, argv, 1 ) )\n      return 1;\n\n   execute( *pOptions );\n   return 0;\n}\n```\n\n\n## Using subcommands\n\nWhen a program becomes even more complex it can be subdivided into commands that often act as\nindependent programs.  We can rewrite the above example with commands.  The main change is that the\nclass `AccumulatorOptions` is now derived from `CommandOptions` which has the method `execute` that\nwe use to execute the selected command.  \n\n```C++\n#include \u003cclimits\u003e\n#include \u003cargumentum/argparse.h\u003e\n#include \u003cnumeric\u003e\n#include \u003cvector\u003e\n\nusing namespace std;\nusing namespace argumentum;\n\nclass AccumulatorOptions : public argumentum::CommandOptions\n{\npublic:\n   vector\u003cint\u003e numbers;\n   std::pair\u003cstd::function\u003cint( int, int )\u003e, int\u003e operation;\n\n   void execute( const ParseResults\u0026 res )\n   {\n      auto acc = accumulate( \n         numbers.begin(), numbers.end(), operation.second, operation.first );\n      cout \u003c\u003c acc \u003c\u003c \"\\n\";\n   }\n\nprotected:\n   void add_parameters( ParameterConfig\u0026 params ) override\n   {\n     // ... same as above\n   }\n};\n\nclass CmdEchoOptions : public argumentum::CommandOptions\n{\npublic:\n   vector\u003cint\u003e numbers;\n\npublic:\n   void execute( const ParseResult\u0026 res ) override\n   {\n      for ( auto n : numbers )\n         cout \u003c\u003c n \u003c\u003c \" \";\n      cout \u003c\u003c \"\\n\";\n   }\n\nprotected:\n   void add_parameters( ParameterConfig\u0026 params ) override\n   {\n      params.add_parameter( numbers, \"N\" ).minargs( 1 ).metavar( \"INT\" ).help( \"Integers\" );\n   };\n};\n\n\nint main( int argc, char** argv )\n{\n   auto parser = argument_parser{};\n   auto params = parser.params();\n   parser.config().program( argv[0] ).description( \"Accumulator\" );\n   params.add_command\u003cCmdAccumulatorOptions\u003e( \"fold\" ).help( \"Accumulate integer values.\" );\n   params.add_command\u003cCmdEchoOptions\u003e( \"echo\" ).help( \"Echo integers from the command line.\" );\n\n   auto res = parser.parse_args( argc, argv, 1 );\n   if ( !res )\n      return 1;\n\n   auto pcmd = res.commands.back();\n   if ( !pcmd )\n      return 1;\n\n   pcmd-\u003eexecute( res );\n   return 0;\n}\n```\n\nCommand options are instantiated and added to the parser only when the appropriate command is\nselected with an argument.  The chain of instantiated subcommands is stored in\n`ParseResults::commands`.  Typically we execute only the last instantiated (the \"deepest\")\nsubcommand.\n\nIf a program has global options that we want to access from a command, we have to instantiate\ncommand options in advance and set a link in command options to global options.  In this case it is\nmost convenient to store global options in an Options structure.  Even though we add an instance of\ncommand options to the parser, the actual options will be registered with the parser only when the\ncommand is activated by the arguments.\n\nIn the following example AccumulatorOptions need access to global options.  Only the added and\nmodified methods are shown:\n\n```C++\nclass GlobalOptions : public argumentum::Options\n{\npublic:\n   int logLevel = 0;\n   void add_parameters( ParameterConfig\u0026 params ) override\n   {\n      params.add_parameter( logLevel, \"--loglevel\" ).nargs( 1 );\n   }\n};\n\nclass AccumulatorOptions : public argumentum::CommandOptions\n{\n   std::shared_ptr\u003cGloblaOptions\u003e mpGlobal;\npublic:\n   AccumulatorOptions( std::string_view name, std::shared_ptr\u003cGloblaOptions\u003e pGlobal )\n      : CommandOptions( name )\n      , mpGlobal( pGlobal )\n  {}\n\n  void execute( const ParseResults\u0026 res )\n  {\n     if ( mpGlobal \u0026\u0026 mpGlobal-\u003elogLevel \u003e 0 )\n       cout \u003c\u003c \"Accumulating \" \u003c\u003c numbers.size() \u003c\u003c \" numbers\\n\";\n\n     auto acc = accumulate(\n        numbers.begin(), numbers.end(), operation.second, operation.first );\n     cout \u003c\u003c acc \u003c\u003c \"\\n\";\n  }\n};\n\nint main( int argc, char** argv )\n{\n   auto parser = argument_parser{};\n   auto params = parser.params();\n   parser.config().program( argv[0] ).description( \"Accumulator\" );\n\n   auto pGlobal = std::make_shared\u003cGlobalOptions\u003e();\n   auto pAccumulator = std::make_shared\u003cCmdAccumulatorOptions\u003e( \"fold\", pGlobal );\n\n   params.add_parameters( pGlobal );\n   params.add_command( pAccumulator ).help( \"Accumulate integer values.\" );\n   params.add_command\u003cCmdEchoOptions\u003e( \"echo\" ).help( \"Echo integers from the command line.\" );\n\n   auto res = parser.parse_args( argc, argv, 1 );\n   if ( !res )\n      return 1;\n\n   auto pcmd = res.commands.back();\n   if ( !pcmd )\n      return 1;\n\n   pcmd-\u003eexecute( res );\n   return 0;\n}\n```\n\n## Forwarding arguments to a subprocess\n\nIf an option has the setting `.forward(true)` it can capture a list of arguments that can be\nforwarded to a subprocess or processed differently.  Forwarding works only with long options.  The\ntarget value of such an option should be a list of strings that will hold the arguments to forward.\n\nThe arguments to forward are part of the option.  They are a comma separated list that is separated\nfrom the option name with a comma.  In the following example we pass arguments for the subprocess\n`ls` with `--dir,\u003carguments\u003e`, for example `--dir,--color=auto,-la,--recursive`.  The arguments are\nstored in `lsoptions` and passed to `ls` with the `system()` call.\n\n```c++\n#include \u003cargumentum/argparse.h\u003e\n#include \u003cstring\u003e\n#include \u003cvector\u003e\n\nusing namespace std;\nusing namespace argumentum;\n\nint main( int argc, char** argv )\n{\n   vector\u003cstring\u003e lsoptions;\n\n   auto parser = argument_parser{};\n   auto params = parser.params();\n   parser.config().program( argv[0] ).description( \"Lister\" );\n   params.add_parameter( lsoptions, \"--dir\" ).forward(true);\n         .help( \"The parameters to forward to ls.\" );\n\n   if ( !parser.parse_args( argc, argv, 1 ) )\n      return 1;\n\n   auto join( []( const vector\u003cstring\u003e\u0026 words ) {\n     std::accumulate( words.begin(), words.end(), \"\", []( auto\u0026\u0026 a, auto\u0026\u0026 s ) {\n       return a.empty() ? s : a + \" \" + s;\n     } );\n   } );\n\n   system( \"ls \" + join( lsoptions ) );\n   return 0;\n}\n```\n\n\nWhen two consecutive commas are present in a forward-option, a single comma becomes a part of a\nforwarded argument.  Each pair of commas in the option generates a comma in the argument.  When an\nodd number of commas is present, the escaped commas belong to the first forwarded argument while the\nsecond argument starts after the last comma:\n\n- `--linker,-Wl,,-rpath,,.`  generates `{ \"-Wl,-rpath,.\" }`.\n- `--linker,-Wl,,-rpath,-Wl,,.` generates `{ \"-Wl,-rpath\", \"-Wl,.\" }`.\n- `--test,a,,,,,b` generates `{ \"a,,\", \"b\" }`.\n- `--test,a  --test,,,,b` generates `{ \"a\", \",,b\" }`.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmahnic%2Fargumentum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmmahnic%2Fargumentum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmahnic%2Fargumentum/lists"}