Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

args-parser is a small C++ header-only library for parsing command line arguments.

NotificationsYou must be signed in to change notification settings

igormironchik/args-parser

Repository files navigation

License: MIT

This isargs-parser.

args-parser is a small C++ header-only library for parsing command line arguments.

Syntax

  • An argument starts with two dashes. For example--argument.
  • A flag starts with one dash. For example-b.
  • If an argument has a value, then the value can be specified after a space or after an equal sign.For example--argument value and--argument=value.
  • Flags without values can be combined into one block. For example-abc defines three flags-a,-b and-c.
  • The last flag in a flags' block can have a value. For example-abc=value. And here, flag-c will have the valuevalue.
  • MultiArg class provides the ability to define more than one value for an argument. These typesof arguments can be specified more than once in the command line. And the resulted valueof the argument will beStringList.
  • Command class can be used to define command in command line interface.Command is the argument without dash/dashes at the beginning,add for example.
  • Command can has children arguments or even subcommands.
  • Inargs-parser groups can be used to group arguments into groups to check theirdefinitions after parsing, so if constraint of group will be violatedexception will be thrown.
  • args-parser providesHelp argument that provides help printing.Helpuses-h, --help arguments.Help can receive value with nameof argument or command to print help about. IfHelp receives the nameof a command as the value, then the name of a subcommand or a child argumentcan also be provided as the next value, to get help about the subcommand/child argument.
  • Ifargs-parser don't know about argument in command line interface it providesinformation about possible arguments if some misspelling was in commandline interface. Ifargs-parser can't assume anything about entered argument itwill just say about unknown argument through the exception and parsing willfail.
  • WithCmdLine::HandlePositionalArguments option provided toCmdLineconstructor,args-parser will handle positional arguments, these are such argumentsthat can't be parsed with provided arguments, flags, commands and stay at the endof the command line. Be careful with combiningMultiArg and positional arguments,becauseMultiArg can eat almost everything that is not a valid argument.

Different types of strings.

Since version4.0.0args-parser can be built with different strings -std::string,std::wstring andQString.

  • To buildargs-parser withstd::wstring support defineARGS_WSTRING_BUILD
  • To buildargs-parser withQString support defineARGS_QSTRING_BUILD
  • If nothing was defined thenargs-parser will be build withstd::string.

Different types of list of strings.

args-parser extensively uses list of string in internal structures and to returnvalues of arguments outside. In the code this isStringListtype defined inargs-parser/types.hpp. By default underlying type isstd::vector orQVector when building with Qt that can be changedtostd::list,QLinkedList orstd::deque,QList.

  • DefineARGS_LIST to buildargs-parser withstd::list,QLinkedListasStringList
  • DefineARGS_DEQUE to buildargs-parser withstd::deque,QListasStringList

Q/A

Why not to add description, long description, etc. into constructors of arguments,so it will be possible to initialize argument in one line?

  • This is impossible because constructors will be ambiguous but you can useauxiliary API that allows to define arguments in one line of code.

How can I addargs-parser to my project?

  • The simplest way is just copyargs-parser directory with headers to any location inyour project. With CMake you can clone entireargs-parser project somewhere in yourproject and just doadd_subdirectory(), if you will do so you have toadd include directory path to your project withinclude_directories( ${args-parser_INCLUDE_DIRECTORIES} ).

  • You can clone/downloadargs-parser, build and install it with CMake. In thiscase it will be possible to usefind_package( args-parser ) inCMakeLists.txt ofyour project.

  • You can useConan package manager.

Why should I use this library?

  • There are tons of libraries for parsing command line arguments on theInternet. Butargs-parser also provides the possibility to define commands, like

    git add -Agit commitgit push

    Help output is very user-friendly.

    If you need only simple arguments in style--do-it <value> then possiblyyou will find another library more useful for you, but who knows...

How to print help programmatically?

  • For those, who use old style syntax the answer should be on the plate, as developercan look at the code ofHelp class, that implements help argument. But for those, whoprefer one-line syntax the answer can be not so evident, but it's so too. It doesn't matterwhat syntax you use, new (one-line) syntax is just a wrapper for old one. I.e. line:

    cmd.addHelp(true, argv[0 ],"This application just show power of the Args help." );

    Is just a wrapper around ofHelp class. For printing helpargs-parser usesHelpPrinter class. So developer can use it for printing help in some rare cases,as:

    HelpPrinter printer;printer.setExecutable( argv[0 ] );printer.setAppDescription("This application just show power of the Args help." );printer.setLineLength( length );printer.setCmdLine( cmd );printer.print( outStream() );

Why doesn'targs-parser provide bindings of variables to arguments?

  • This is a question of why doesn'targs-parser provide validators? It's the same.I decided that this aspect is very application specific. There is no need for such libraryto do any conversions of arguments' values, to bind them to some variables. This willdo API very complex only. I know what you will say: this is very nice feature, it helps...Really? How often and how much it helped you? Arguments parser should handle the stringthat user provided to the application, it should separate arguments, commands, values,store it in internal state of parser, and allow to developer just write someifoperators to choose branch of the program logic. What will give you, as to developer,if values will be bind to concrete variables? Will not you write the same code withifoperators? So why I should do the library more complex?

Why don't you provide comparisons with other CLI libraries?

  • I found only one library at GitHub that can compete withargs-parser, and this isCLI11. And here is the question of the taste more.ButCLI11 can handle commands as usual arguments, it's doesn't matter how much timesthey present in command line, whereasargs-parser handles commands as commands. Theirsapproach possibly more flexible, but when I designedargs-parser I thought on commandsas on some action to do in application's logic, whereas arguments are for data. I can dothe same, but is it needed?

    CLI11 has possibility to set formatter of the help,args-parser allow to setcustomHelpPrinterIface on theHelp argument. But who and when will do it?And I believe that help inargs-parser is a little better than inCLI11.

    CLI11 works more with callbacks, whereasargs-parser uses hierarchy ofclasses with polymorphism. Inargs-parser you can inherit from any argument'sclass, override methods you need and receive something very application specific.And again, this is more question of taste.

    Uh, oh, I found one more interesting arguments parsing library, This isTaywee/Args. Guys, this is a question of taste.And, as said inCLI11 documentation aboutTaywee/Args,args-parser asCLI11 less verbose.Taywee/Args has benchmark to compare performance withTCLAP andboost::program_options., I want to say thatargs-parser 2 timesfaster thanTaywee/Args, dry numbers says thatTyawee/Args runs 0.635314second, whereasargs-parser runs 0.346813 second.

    What I want to say about minuses ofargs-parseris that I don't support otherdelimiter characters than- for flags and-- for arguments.

Changelog

VersionChanges
6.3.4Fixed issue withMSVC when globally defined::Command class was detected as friend ofArgIface instead ofArgs::Command
6.3.3Minor fix for compilation with-Werror=shadow
6.3.2Fixed multiple definitions when included from different compile units.
6.3.1Improved performance. Added possibility to set positional arguments string for the help. Added benchmark.
6.3.0Added possibility to handle positional arguments.
6.2.0.1Ready for use with Qt6.
6.2.0.0Allowed to inherit from some classes. AddedaddArg() methods into API.
6.1.1.1Added possibility to set up custom help printer in help argument.
6.1.1.0Improved API with new syntax, now it's impossible to mess with end() methods. Fixed issue with printing help of global argument under command.
6.1.0.0Added possibility to addCommand into groups.
6.0.0.0In this version was removedArgAsCommand class, and was added fully-featured support for sub-commands, that can be created withCommand class, i.e.Command can hasCommand as child. So it's possible to create such CLI asgit submodule update --init --recursive.

Example

First of all you must know that practically all classes of theargs-parser throws exceptions on errorsand there is one specific exceptions that inform you about that that help was shown. This specificexception (HelpHasBeenPrintedException) is needed for processing program's logic that usually stopsexecution at this point.

Since version5.0.0args-parser provides two API: the old one and auxiliary APIthat allows to define arguments in one line of code. Let's look.

One-line syntax with commands

// args-parser include.#include<args-parser/all.hpp>usingnamespaceArgs;intmain(int argc,char ** argv ){try {    CmdLinecmd( argc, argv, CmdLine::CommandIsRequired );    cmd.addCommand("add", ValueOptions::NoValue,true,"Add file." )        .addCommand("file", ValueOptions::ManyValues,false,"File name.","","","fn" )        .end()      .end()      .addCommand("delete", ValueOptions::NoValue,true,"Delete file." )        .addCommand("file", ValueOptions::ManyValues,false,"File name.","","","fn" )        .end()      .end()      .addHelp(true, argv[0 ],"This application just show power of the args-parser help." );    cmd.parse();if( cmd.isDefined("file" ) )for(constauto & fn : cmd.values("file" ) )outStream() << fn <<"\n";  }catch(const HelpHasBeenPrintedException & )  {return0;  }catch(const BaseException & x )  {outStream() << x.desc() <<"\n";return1;  }return0;}

One-line syntax with arguments

#include<args-parser/all.hpp>usingnamespaceArgs;voidprocess(bool b,const std::string & value ){outStream() <<"Boolean:" << b <<" , value:\"" << value <<"\"\n";}intmain(int argc,char ** argv ){try {    CmdLinecmd( argc, argv );    cmd.addArgWithFlagAndName('b',"bool",false,false,"Boolean flag","Boolean flag, used without value" )      .addArgWithFlagAndName('v',"value",true,false,"With value","Argument with value","","VAL" )      .addHelp(true, argv[0 ],"CLI with boolean and value." );    cmd.parse();bool b =false;    std::string value;if( cmd.isDefined("-b" ) )      b =true;if( cmd.isDefined("-v" ) )      value = cmd.value("-v" );process( b, value );  }catch(const HelpHasBeenPrintedException & )  {return0;  }catch(const BaseException & x )  {outStream() << x.desc() <<"\n";return1;  }return0;}

And with the old syntax

// args-parser include.#include<args-parser/all.hpp>// C++ include.#include<iostream>intmain(int argc,char ** argv ){try {/*      We create Args::CmdLine instance for parsing      command line arguments.*/    Args::CmdLinecmd( argc, argv );/*      And create our arguments.*//*      This is argument with flag "-o" and name "--host".      He is with value and required.*/    Args::Arghost('o',"host",// Argument is with value.true,// Argument is required.true );// Set description of the argument.    host.setDescription("Host. Can be\"localhost\",\"any\" or regular IP." );// We can specify long description too.    host.setLongDescription("Host. This argument told to the application""where to open socket for communication." );    Args::Argport('p',"port",true,true );    port.setDescription("Port number to create socket." );/*      This argument have name "--timeout" only.      He is with value but optional.*/    Args::Argtimeout("timeout",true );// This argument want to specify value specifier in the help. Let's do it.    timeout.setValueSpecifier("ms" );    timeout.setDescription("Timeout before new messages will be sent""in milliseconds." );/*      We create help now.*/    Args::Help help;// Set executable name to the help printer.    help.setExecutable( argv[0 ] );// And set description of the application.    help.setAppDescription("This application just show""the power of args-parser." );/*      Now add our argument to the command line.*/    cmd.addArg( host );    cmd.addArg( port );    cmd.addArg( timeout );    cmd.addArg( help );/*      Now parse our arguments.*/    cmd.parse();if( timeout.isDefined() )auto timeoutValue = timeout.value();  }catch(const Args::HelpHasBeenPrintedException & )  {return0;  }catch(const Args::BaseException & x )  {    std::cout << x.what() <<"\n";return1;  }return0;}

Help output for the example with the old syntax.

This application just show the power of args-parser.USAGE: sample.help.exe -s, --host <arg> -p, --port <arg> [ -h, --help <arg> ]       [ --timeout <ms> ]REQUIRED: -s, --host <arg>   Host. Can be "localhost", "any" or regular IP. -p, --port <arg>   Port number to create socket.OPTIONAL: -h, --help <arg>   Print this help.     --timeout <ms> Timeout before new messages will be sent in milliseconds.

That's it. Use it and enjoy it. Good luck.

About

args-parser is a small C++ header-only library for parsing command line arguments.

Topics

Resources

Stars

Watchers

Forks

Contributors4

  •  
  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp