32 #ifndef FSC_ARGPARSER_HEADER
33 #define FSC_ARGPARSER_HEADER
35 #include "ArgParser/poly_type.hpp"
36 #include "ArgParser/boost_any.hpp"
37 #include "ArgParser/fsc_except.hpp"
51 std::string get_progname(std::string pwd_name) {
52 auto pos = pwd_name.rfind(
"/");
53 if(pos == std::string::npos)
56 pwd_name.erase(0, pos+1);
59 std::string get_pwd(std::string pwd_name, std::string
const & cwd) {
60 auto pos = pwd_name.rfind(
"/");
61 if(pos == std::string::npos)
64 pwd_name.erase(pos, pwd_name.size());
66 return cwd +
"/" + pwd_name;
68 std::vector<std::string> split_clean(std::string
const & str) {
69 std::stringstream iss(str);
70 return std::vector<std::string>{std::istream_iterator<std::string>{iss}
71 , std::istream_iterator<std::string>{}};
85 using map_type = std::map<std::string, poly_type>;
87 using vec_type = std::vector<U>;
88 using size_type = vec_type<poly_type>::size_type;
106 ArgParser(
int const & argc,
char * argv[]): cwd_(getcwd(NULL, 0))
107 , pwd_(detail::get_pwd(argv[0], cwd_))
108 , progname_(detail::get_progname(argv[0])) {
109 vec_type<std::string> arg;
110 for(
int i = 1; i < argc; ++i)
111 arg.push_back(argv[i]);
121 explicit ArgParser(std::string
const & cline): cwd_(getcwd(NULL, 0))
124 parse_(detail::split_clean(cline));
132 poly_type
const &
operator[](std::string
const & key)
const {
133 if(n_args_.find(key) == n_args_.end())
134 throw std::runtime_error(
"ArgParser error: named argument '" + key +
"' not found");
135 return n_args_.at(key);
145 throw std::runtime_error(
"ArgParser error: free argument '" + std::to_string(key) +
"' not found");
156 T
get(std::string
const & key, T
const &
def)
const {
158 return n_args_.at(key);
169 std::string
get(std::string
const & key,
char const *
def)
const {
170 return get<std::string>(key,
def);
181 T
get(size_type
const & pos, T
const &
def)
const {
183 return f_args_.at(pos);
195 std::string
get(size_type
const & pos,
char const *
def)
const {
196 return get<std::string>(pos,
def);
202 std::string
const &
cwd() const noexcept {
210 std::string
const &
pwd()
const {
212 throw std::runtime_error(
"ArgParser error: pwd not set");
222 throw std::runtime_error(
"ArgParser error: progname not set");
228 return f_args_.size();
236 bool is_set(std::string
const & key)
const noexcept {
237 return inflag_(key) or innamed_(key);
244 bool is_set(size_type
const & pos)
const noexcept {
257 void def(std::string
const & key, T
const &
def) {
259 setnamed_(key, poly_type(def));
267 void def(std::string
const & key) {
291 for(
auto const & it: rhs.n_args_) {
292 std::string key = it.first;
293 poly_type val = it.second;
294 setnamed_(key, val, overwrite);
298 f_args_ = rhs.f_args_;
301 for(
auto const & it: rhs.flags_) {
308 progname_ = rhs.progname_;
319 bool parse_file(std::string
const & filename,
bool const & overwrite =
true) {
320 vec_type<std::string> arg;
321 std::ifstream ifs(filename, std::ios_base::in);
322 std::string res =
"";
324 std::stringstream buffer;
325 buffer << ifs.rdbuf();
340 os <<
"=======ArgParser=======" << std::endl;
341 os <<
"free_args:" << std::endl;
342 for(
auto const & it: f_args_)
343 os <<
" " << it << std::endl;
344 os <<
"named_args:" << std::endl;
345 for(
auto const & it: n_args_)
346 os <<
" " << it.first <<
" \t" << it.second << std::endl;
347 os <<
"flags:" << std::endl;
348 for(
auto const & it: flags_)
349 os <<
" " << it << std::endl;
350 os <<
"special member:" << std::endl;
351 os <<
" cwd \t" << cwd_ << std::endl;
352 os <<
" pwd \t" << pwd_ << std::endl;
353 os <<
" progname \t" << progname_;
356 enum arg_type {named_m_stick, named_m, named_mm, named_eq, free, flag_m, flag_mm, named_m_eq, named_mm_eq, invalid};
357 inline bool inflag_(std::string
const & flag)
const noexcept {
358 return std::find(flags_.begin(), flags_.end(), flag) != flags_.end();
360 inline bool innamed_(std::string
const & key)
const noexcept {
361 return n_args_.find(key) != n_args_.end();
363 void setflag_(std::string
const & flag) {
365 std::cout <<
"ArgParser warning: setting flag '" << flag <<
"' for a second time has no effect" << std::endl;
368 throw cat_on_your_keyboard_error(
"ArgParser error: there cannot be a flag and named argument with the same name '" + flag +
"'");
369 flags_.push_back(flag);
373 void setnamed_(std::string
const & key, T
const & val,
bool const & overwrite =
true) {
376 std::cout <<
"ArgParser warning: named argument '" << key <<
"' is overwritten (" << n_args_[key] <<
" -> " << val <<
")" << std::endl;
381 throw cat_on_your_keyboard_error(
"ArgParser error: there cannot be a flag and named argument with the same name '" + key +
"'");
385 arg_type find_type_(vec_type<std::string>
const & arg, uint
const & idx)
const {
386 if(idx >= arg.size())
389 if(arg[idx][0] ==
'-') {
390 if(arg[idx][1] ==
'-') {
391 if(arg[idx].find(
"=") != std::string::npos)
393 else if(find_type_(arg, idx+1) == free)
398 if(arg[idx].size() == 2) {
399 if(find_type_(arg, idx+1) == free)
404 if(arg[idx][2] ==
'=')
407 return named_m_stick;
411 if(arg[idx].find(
"=") != std::string::npos)
417 void parse_(vec_type<std::string>
const & arg) {
418 for(uint i = 0; i < arg.size(); ++i) {
419 auto t = find_type_(arg, i);
421 std::string arg1 = arg[i];
422 std::string help =
"";
427 help.push_back(arg1[1]);
429 setnamed_(help, str_to_type_(poly_type(arg1)));
436 setnamed_(arg1, str_to_type_(poly_type(arg[i+1])));
444 pos = arg1.find(
"=");
446 help.erase(0, pos + 1);
447 arg1.erase(pos, arg1.size());
448 setnamed_(arg1, str_to_type_(poly_type(help)));
451 f_args_.push_back(str_to_type_(poly_type(arg1)));
464 poly_type str_to_type_(poly_type
const & a) {
470 ival = std::stoi(val, & ipos);
476 dval = std::stod(val, & dpos);
477 return poly_type(dval);
480 if(ipos == val.size())
481 return poly_type(ival);
482 else if(dpos == val.size())
483 return poly_type(dval);
485 return poly_type(val);
489 vec_type<poly_type> f_args_;
490 vec_type<std::string> flags_;
493 std::string progname_;
497 std::ostream & operator<<(std::ostream & os, ArgParser
const & arg) {
509 #endif //FSC_ARGPARSER_HEADER
void print(S &os) const noexcept
prints the argument parser in a verbose form
std::string const & pwd() const
returns the program working directory
bool is_set(std::string const &key) const noexcept
check if flag or named argument is set
std::string const & progname() const
returns the program name
poly_type const & operator[](std::string const &key) const
get named argument if set
void def(std::string const &key, T const &def)
set a named argument if not already set
ArgParser() noexcept
default constructor
bool is_set(size_type const &pos) const noexcept
check if free argument is set
std::string const & cwd() const noexcept
returns the current working directory
void def(std::string const &key)
set a flag
ArgParser(std::string const &cline)
string constructor
ArgParser(int const &argc, char *argv[])
construct from command line
an argument parser that does not require registration.
bool parse_file(std::string const &filename, bool const &overwrite=true)
read a file, parse the content and merge into this
poly_type const & operator[](size_type const &key) const
get free argument if set
void merge(ArgParser const &rhs, bool const &overwrite=true) noexcept
merge two argument parsers
size_type freeargc() const noexcept
returns the number of free arguments