Giter Club home page Giter Club logo

cmdline's Introduction

cmdline: A simple command line parser for C++

About

This is a simple command line parser for C++.

  • Easy to use
  • Only one header file
  • Automatic type check

Sample

Here show sample usages of cmdline.

Normal usage

This is an example of simple usage.

// include cmdline.h
#include "cmdline.h"

int main(int argc, char *argv[])
{
  // create a parser
  cmdline::parser a;

  // add specified type of variable.
  // 1st argument is long name
  // 2nd argument is short name (no short name if '\0' specified)
  // 3rd argument is description
  // 4th argument is mandatory (optional. default is false)
  // 5th argument is default value  (optional. it used when mandatory is false)
  a.add<string>("host", 'h', "host name", true, "");

  // 6th argument is extra constraint.
  // Here, port number must be 1 to 65535 by cmdline::range().
  a.add<int>("port", 'p', "port number", false, 80, cmdline::range(1, 65535));

  // cmdline::oneof() can restrict options.
  a.add<string>("type", 't', "protocol type", false, "http", cmdline::oneof<string>("http", "https", "ssh", "ftp"));

  // Boolean flags also can be defined.
  // Call add method without a type parameter.
  a.add("gzip", '\0', "gzip when transfer");

  // Run parser.
  // It returns only if command line arguments are valid.
  // If arguments are invalid, a parser output error msgs then exit program.
  // If help flag ('--help' or '-?') is specified, a parser output usage message then exit program.
  a.parse_check(argc, argv);

  // use flag values
  cout << a.get<string>("type") << "://"
       << a.get<string>("host") << ":"
       << a.get<int>("port") << endl;

  // boolean flags are referred by calling exist() method.
  if (a.exist("gzip")) cout << "gzip" << endl;
}

Here are some execution results:

$ ./test
usage: ./test --host=string [options] ...
options:
  -h, --host    host name (string)
  -p, --port    port number (int [=80])
  -t, --type    protocol type (string [=http])
      --gzip    gzip when transfer
  -?, --help    print this message
$ ./test -?
usage: ./test --host=string [options] ...
options:
  -h, --host    host name (string)
  -p, --port    port number (int [=80])
  -t, --type    protocol type (string [=http])
     --gzip    gzip when transfer
  -?, --help    print this message
$ ./test --host=github.com
http://github.com:80
$ ./test --host=github.com -t ftp
ftp://github.com:80
$ ./test --host=github.com -t ttp
option value is invalid: --type=ttp
usage: ./test --host=string [options] ...
options:
  -h, --host    host name (string)
  -p, --port    port number (int [=80])
  -t, --type    protocol type (string [=http])
      --gzip    gzip when transfer
  -?, --help    print this message
$ ./test --host=github.com -p 4545
http://github.com:4545
$ ./test --host=github.com -p 100000
option value is invalid: --port=100000
usage: ./test --host=string [options] ...
options:
  -h, --host    host name (string)
  -p, --port    port number (int [=80])
  -t, --type    protocol type (string [=http])
      --gzip    gzip when transfer
  -?, --help    print this message
$ ./test --host=github.com --gzip
http://github.com:80
gzip

Extra Options

  • rest of arguments

Rest of arguments are referenced by rest() method. It returns vector of string. Usualy, they are used to specify filenames, and so on.

for (int i = 0; i < a.rest().size(); i++)
  cout << a.rest()[i] << endl\;
  • footer

footer() method is add a footer text of usage.

...
a.footer("filename ...");
...

Result is:

$ ./test
usage: ./test --host=string [options] ... filename ...
options:
  -h, --host    host name (string)
  -p, --port    port number (int [=80])
  -t, --type    protocol type (string [=http])
      --gzip    gzip when transfer
  -?, --help    print this message
  • program name

A parser shows program name to usage message. Default program name is determin by argv[0]. set_program_name() method can set any string to program name.

Process flags manually

parse_check() method parses command line arguments and check error and help flag.

You can do this process mannually. bool parse() method parses command line arguments then returns if they are valid. You should check the result, and do what you want yourself.

(For more information, you may read test2.cpp.)

cmdline's People

Contributors

nanoant avatar tanakh avatar yuttie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmdline's Issues

How to handle multiple inputs within the same name?

cmdline state:

    run -m model.bin -i test_image000.raw test_image11111.raw test_image22222.raw -o result0 -a 0 -b 0 -c 0 -d 0 -e 0 -f n -g 0

    run -m model.bin -i test_image000.raw test_image11111.raw test_image22222.raw -o result0 result1 result2 result3 -a 0 -b 0 -c 0 -d 0 -e 0 -f n -g 0

    run -m model.bin -i test_image000.raw test_image11111.raw test_image22222.raw -o result0 -o result1 -o result2 -o result3 -a 0 -b 0 -c 0 -d 0 -e 0 -f n -g 0

    run -m model.bin -i test_image000.raw -i test_image11111.raw -i test_image22222.raw -o result -a 0 -b 0 -c 0 -d 0 -e 0 -f n -g 0

    run -m model.bin -i test_image000.raw -i test_image11111.raw -i test_image22222.raw -o result -a 0 -b 0 -c 0 -d 0 -e 0 -f n -g 0

    run -m model.bin -i test_image000.raw -i test_image11111.raw -i test_image22222.raw -o result0 -o result1 -o result2 -o result3 -a 0 -b 0 -c 0 -d 0 -e 0 -f n -g 0

How to handle this kind of situation?
By the way, I show multi types of format, Which format is suitable? thanks!

zsh does not support "-?"

Hello Tanakh,

When I enter ./a.out -?, the zsh tell me zsh: no matches found: -?

That make me think that -h is better than -?, so maybe it is a better idea to use -h as default help command. (as far as I know, many programme use -h but not -?)

Thank you.

Warning C4101 unreferenced local variable

Line 732 ->:

catch(const std::exception &e){
        return false;
      }

the parameter e is not used, thus MSVC may give a warning.

solution:

catch(const std::exception &e){
        std::cerr << "exception caught: " << e.what() << '\n';
        return false;
      }

MSVC confuse std::max with windows max macros

when i compiled cmdline in vs2016, i got the following error

1>cmdline.h(586) : error C2589: '(' : illegal token on right side of '::'
1>cmdline.h(586) : error C2143: syntax error : missing ';' before '::'

the solution is to use

max_width = (std::max)(max_width, (ordered[i]->name().length()));

to instead the line

max_width = std::max(max_width, (ordered[i]->name().length()));

this API parse_check(const string arg) not work

my example code is follow:
’‘’
cmdline::parser parser;
parser.add("loglevel", 'l', "0-critical, 1-err, 2-warn, 3-info, 4-debug, 5-trace", false, 1);
parser.parse_check("--loglevel");
auto t = parser.get("loglevel");
std::cout << "level:" << t << std::endl; // when set loglevel 5, but it always default value effect
auto log_level = (LogLevel)t;
std::cout << "log level: " << log_level <<std::endl;
InitLog(log_level);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
‘’‘

I built a bin as "test", when I execute the command "./test --gtest_filter=*.test1 --loglevel 5",
but the loglevel is always set to be default value 1
image

please check this problem, thx

Support for long description

It would be nice to be able to add a program description to usage. I mean this kind of output:

usage: ./test --host=string [options] ... 
options:
  -h, --host    host name (string)
  -p, --port    port number (int [=80])
  -t, --type    protocol type (string [=http])
      --gzip    gzip when transfer
  -?, --help    print this message
The program accepts on standard input newline-delimited string 
values denoting query arguments to be added to the output url. 
Example: 
  $ (echo a=1& echo b=2)| ./test --host=github.com -p 4545
  http://github.com:4545?a=1&b=2

I don't know whether is makes sense for Unix people, but it does on Windows.

Mysterious segfaults with cmdline with several arguments

cmdline appears to have some intrinsic limitation to the number of arguments it can process. I get

$ ./a.out 
Segmentation fault (core dumped)

with the following test program originating from HelFEM

#include "cmdline.h"
#include <vector>
#include <string>

int main(int argc, char **argv) {
  cmdline::parser parser;

  // full option name, no short option, description, argument required
  parser.add<std::string>("Z", 0, "nuclear charge", false, "H");
  parser.add<double>("Rmax", 0, "practical infinity in au", false, 40.0);
  parser.add<int>("grid", 0, "type of grid: 1 for linear, 2 for quadratic, 3 for polynomial, 4 for exponential", false, 4);
  parser.add<double>("zexp", 0, "parameter in radial grid", false, 2.0);
  parser.add<int>("nelem", 0, "number of elements", false, 5);
  parser.add<int>("Q", 0, "charge of system", false, 0);
  parser.add<int>("nnodes", 0, "number of nodes per element", false, 15);
  parser.add<int>("nquad", 0, "number of quadrature points", false, 0);
  parser.add<int>("maxit", 0, "maximum number of iterations", false, 500);
  parser.add<double>("convthr", 0, "convergence threshold", false, 1e-7);
  parser.add<std::string>("method", 0, "method to use", false, "lda_x");
  parser.add<double>("dftthr", 0, "density threshold for dft", false, 1e-12);
  parser.add<int>("restricted", 0, "spin-restricted orbitals", false, -1);
  parser.add<int>("primbas", 0, "primitive radial basis", false, 4);
  parser.add<double>("diiseps", 0, "when to start mixing in diis", false, 1e-2);
  parser.add<double>("diisthr", 0, "when to switch over fully to diis", false, 1e-3);
  parser.add<int>("diisorder", 0, "length of diis history", false, 5);
  parser.parse_check(argc, argv);

  // Get parameters
  double Rmax(parser.get<double>("Rmax"));
  int igrid(parser.get<int>("grid"));
  double zexp(parser.get<double>("zexp"));
  int maxit(parser.get<int>("maxit"));
  double convthr(parser.get<double>("convthr"));
  int restr(parser.get<int>("restricted"));
  int primbas(parser.get<int>("primbas"));
  // Number of elements
  int Nelem(parser.get<int>("nelem"));
  // Number of nodes
  int Nnodes(parser.get<int>("nnodes"));

  // Order of quadrature rule
  int Nquad(parser.get<int>("nquad"));
  double dftthr(parser.get<double>("dftthr"));

  // Nuclear charge
  std::string Z(parser.get<std::string>("Z"));
  int Q(parser.get<int>("Q"));
  double diiseps=parser.get<double>("diiseps");
  double diisthr=parser.get<double>("diisthr");
  int diisorder=parser.get<int>("diisorder");
  std::string method=parser.get<std::string>("method");
  
  std::vector<std::string> rcalc(2);
  rcalc[0]="unrestricted";
  rcalc[1]="restricted";

  printf("Running %s %s calculation with Rmax=%e and %i elements.\n",rcalc[restr].c_str(),method.c_str(),Rmax,Nelem);
  
  return 0;
}

The backtrace doesn't contain any useable information

(gdb) bt
#0  __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:96
#1  0x00007fdb436ba6de in __vfprintf_internal (s=0x7fdb43813780 <_IO_2_1_stdout_>, format=0x4103c8 "Running %s %s calculation with Rmax=%e and %i elements.\n", ap=ap@entry=0x7ffe86b3a540, 
    mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1645
#2  0x00007fdb436a52df in __printf (format=<optimized out>) at printf.c:33
#3  0x0000000000404c48 in main ()

but the code works if you comment out a variable!

Can not support std::vector<std::string> ?

#include <iostream>
#include <vector>
#include "cmdline.h"

int main(int argc, char** argv) {
  cmdline::parser parser;

  parser.add<std::vector<std::string>>("topics", 't', "topics to filter", true);

  parser.parse(argc, argv);

  std::vector<std::string> topics = parser.get<std::vector<std::string>>("topics");

  std::cout << "Topics to filter:" << std::endl;
  for (const auto& topic : topics) {
    std::cout << "- " << topic << std::endl;
  }

  return 0;
}

this code is compile error,how to support for std::vectorstd::string?

ABI dependency

Is it really required to depend on cxxabi.h? Non-gcc projects hit the wall here. Removed the problematic code regarding typename demangling. Interested in a contribution? One could provide a conditional compilation for this code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.