MADNESS 0.10.1
commandlineparser.h
Go to the documentation of this file.
1//
2// Created by Florian Bischoff on 2/10/21.
3//
4
5#ifndef MADNESS_COMMANDLINEPARSER_H
6#define MADNESS_COMMANDLINEPARSER_H
7
8#include<map>
9#include<algorithm>
10namespace madness {
11/// very simple command line parser
12
13/// parser reads out key/value pairs from the command line of the form
14/// `--key=val` or `--key`. By default values are case-folded so that
15/// chemistry-style enum knobs (e.g. `--xc=HF`, `--localize=BOYS`) match
16/// the lowercased `allowed_values` of `QCCalculationParametersBase`-derived
17/// classes.
18///
19/// Two accessors are exposed for retrieving values:
20/// * `value(key)` — case-folded value (back-compat). Use for enum-like
21/// chemistry parameters.
22/// * `value_raw(key)` — original-case value. Use for **paths and free-form
23/// identifiers** (archive filenames, JSON paths, …).
24///
25/// The bare-positional input-file form (e.g. `madness_app /Some/Path/in.in`)
26/// is also case-preserving — both `value("input")` and `value_raw("input")`
27/// return the path with original case.
29
30 std::map<std::string, std::string> keyval; // case-folded values
31 std::map<std::string, std::string> keyval_raw; // original-case values
32
36
37 // parse command line arguments
38 // mp2 --mp2='maxiter 10; freeze 1' --dft:maxiter=20 --Xmpi:debug=true
39 commandlineparser(int argc, char **argv) {
41 std::vector<std::string> allArgs_raw(argv, argv + argc);
42 allArgs_raw.erase(allArgs_raw.begin()); // first argument is the name of the binary
43 for (auto &a : allArgs_raw) {
44 // special treatment for the input file: no hyphens
47 std::replace_copy(a.begin(), a.end(), a.begin(), '=', ' ');
48 std::string key, val;
49 std::stringstream sa(a);
50 sa >> key;
51 val=a.substr(key.size());
52 if (key=="input") set_keyval("user_defined_input_file","1");
53 if (key=="prefix") set_keyval("user_defined_prefix","1");
54
55 // Path-like keys: keep case in BOTH maps so the back-compat
56 // `value("input"|"file")` form also returns the original case
57 // (already true today for "file"; extending to "input" so the
58 // bare-positional form `app /Some/Path/in.in` survives).
59 if (key=="file" || key=="input") {
60 set_keyval_keep_case(key,val);
61 } else {
62 set_keyval(key,val);
63 }
64 }
65 }
66
67 /// set default values from the command line
68 void set_defaults() {
69 keyval["input"]="input";
70 keyval["prefix"]="mad";
71// keyval["geometry"]="input_file";
72 }
73
74 void print_map() const {
75 for (auto&[key, val] : keyval) {
76 printf("%20s %20s \n", key.c_str(), val.c_str());
77 }
78 }
79
80 bool key_exists(std::string key) const {
81 return (keyval.count(tolower(key))==1);
82 }
83
84 std::string value(const std::string key) const {
85 std::string msg= "key not found: " + key;
86 MADNESS_CHECK_THROW(key_exists(key), msg.c_str());
87 return keyval.find(tolower(key))->second;
88 }
89
90 /// Original-case value lookup — use for paths and free-form identifiers
91 /// (archive filenames, JSON paths, etc.). For enum-like chemistry knobs
92 /// matched against `allowed_values`, prefer `value(key)` instead.
93 std::string value_raw(const std::string key) const {
94 std::string msg = "key not found: " + key;
95 MADNESS_CHECK_THROW(key_exists(key), msg.c_str());
96 auto it = keyval_raw.find(tolower(key));
97 if (it == keyval_raw.end()) {
98 // Defensive fallback for keys set via the default-constructor
99 // path (defaults), which only seed `keyval`. Return the
100 // case-folded version rather than throwing.
101 return keyval.find(tolower(key))->second;
102 }
103 return it->second;
104 }
105
106 void set_keyval(const std::string key, const std::string value) {
107 const std::string trimmed = trim_blanks(value);
108 keyval[tolower(key)] = tolower(trimmed);
109 keyval_raw[tolower(key)] = trimmed;
110 }
111
112 void set_keyval_keep_case(const std::string key, const std::string value) {
113 const std::string trimmed = trim_blanks(value);
114 keyval[tolower(key)] = trimmed;
115 keyval_raw[tolower(key)] = trimmed;
116 }
117
118public:
119
120 /// special option: the input file has no hyphens in front and is just a value
121 std::string check_for_input_file(std::string line) {
122 if (line[0]=='-') return line;
123 auto words=split(line,"=");
124 if (words.size()==1) line="input="+line;
125 return line;
126 }
127 /// make lower case
128 static std::string tolower(std::string s) {
129 std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); });
130 return s;
131 }
132
133 /// split a string s into a vector of strings, using delimiter
134
135 /// @param[in] s the string (pass by value!)
136 static std::vector<std::string> split(std::string s, const std::string delimiter) {
137 std::size_t pos = 0;
138 std::string token;
139 std::vector<std::string> result;
140 while ((pos = s.find(delimiter)) != std::string::npos) {
141 token = s.substr(0, pos);
142 result.push_back(token);
143 s.erase(0, pos + delimiter.length());
144 }
145 result.push_back(s);
146 return result;
147 }
148
149 static std::string remove_front_hyphens(const std::string arg) {
150 std::size_t first=arg.find_first_not_of('-');
151 return arg.substr(first);
152 }
153
154 static std::string remove_first_equal(const std::string arg) {
155 std::string result=arg;
156 const std::string item="=";
157 const std::string blank=" ";
158 auto it=std::find_first_of(result.begin(),result.end(),item.begin(),item.end());
159 std::replace(it,it+1,item.front(),blank.front());
160 return result;
161 }
162
163 /// remove all blanks
164 static std::string remove_blanks(const std::string arg) {
165 std::string str2 = arg;
166 str2.erase(std::remove_if(str2.begin(), str2.end(),
167 [](unsigned char x){return std::isspace(x);}),str2.end());
168 return str2;
169 }
170
171 /// remove blanks at the beginning and the end only
172 static std::string trim_blanks(const std::string arg) {
173 if (arg.size()==0) return arg;
174 std::size_t first=arg.find_first_not_of(' ');
175 std::size_t last=arg.find_last_not_of(' ');
176 return arg.substr(first,last-first+1);
177 }
178
179 static std::string base_name(std::string const & path, std::string const & delims = "/")
180 {
181 return path.substr(path.find_last_of(delims) + 1);
182 }
183
184 static std::string remove_extension(std::string const & filename)
185 {
186 std::size_t p=filename.find_last_of('.');
187 return p > 0 && p != std::string::npos ? filename.substr(0, p) : filename;
188 }
189
190};
191}
192#endif //MADNESS_COMMANDLINEPARSER_H
std::filesystem::path path
Definition InputWriter.cpp:3
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition tensor.h:2643
#define MADNESS_CHECK_THROW(condition, msg)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:207
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
static const char * filename
Definition legendre.cc:96
static const double a
Definition nonlinschro.cc:118
static const double c
Definition relops.cc:10
very simple command line parser
Definition commandlineparser.h:28
static std::string trim_blanks(const std::string arg)
remove blanks at the beginning and the end only
Definition commandlineparser.h:172
void set_keyval_keep_case(const std::string key, const std::string value)
Definition commandlineparser.h:112
std::string value(const std::string key) const
Definition commandlineparser.h:84
std::map< std::string, std::string > keyval_raw
Definition commandlineparser.h:31
void set_keyval(const std::string key, const std::string value)
Definition commandlineparser.h:106
bool key_exists(std::string key) const
Definition commandlineparser.h:80
std::map< std::string, std::string > keyval
Definition commandlineparser.h:30
std::string value_raw(const std::string key) const
Definition commandlineparser.h:93
static std::string base_name(std::string const &path, std::string const &delims="/")
Definition commandlineparser.h:179
static std::string tolower(std::string s)
make lower case
Definition commandlineparser.h:128
void set_defaults()
set default values from the command line
Definition commandlineparser.h:68
commandlineparser(int argc, char **argv)
Definition commandlineparser.h:39
static std::string remove_first_equal(const std::string arg)
Definition commandlineparser.h:154
static std::string remove_extension(std::string const &filename)
Definition commandlineparser.h:184
static std::string remove_blanks(const std::string arg)
remove all blanks
Definition commandlineparser.h:164
commandlineparser()
Definition commandlineparser.h:33
std::string check_for_input_file(std::string line)
special option: the input file has no hyphens in front and is just a value
Definition commandlineparser.h:121
void print_map() const
Definition commandlineparser.h:74
static std::string remove_front_hyphens(const std::string arg)
Definition commandlineparser.h:149
static std::vector< std::string > split(std::string s, const std::string delimiter)
split a string s into a vector of strings, using delimiter
Definition commandlineparser.h:136