Skip to content

Commit ff327e9

Browse files
author
Jesse
committed
fix quoted text
1 parent 190c48a commit ff327e9

2 files changed

Lines changed: 81 additions & 50 deletions

File tree

argparse.h

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919

2020
#include <algorithm>
2121
#include <cctype>
22+
#include <cstring>
2223
#include <iomanip>
2324
#include <iostream>
2425
#include <locale>
2526
#include <numeric>
26-
#include <regex>
2727
#include <sstream>
2828
#include <stdexcept>
2929
#include <string>
@@ -61,8 +61,8 @@ class ArgumentParser {
6161

6262
bool is_help() { return _help; }
6363

64-
void print_help(char *f) {
65-
std::cout << "Usage: " << f << " [options]" << std::endl;
64+
void print_help() {
65+
std::cout << "Usage: " << _bin << " [options]" << std::endl;
6666
std::cout << "Options:" << std::endl;
6767
for (auto &a : _arguments) {
6868
std::string name = a._name;
@@ -74,28 +74,44 @@ class ArgumentParser {
7474
}
7575

7676
void parse(int argc, char *argv[]) {
77+
_bin = argv[0];
7778
if (argc > 1) {
78-
std::vector<std::string> argsvec(argv + 1, argv + argc);
79-
std::string argstr =
80-
std::accumulate(argsvec.begin(), argsvec.end(), std::string(),
81-
[](std::string a, std::string b) {
82-
return a + " " + std::string(b);
83-
});
84-
std::vector<std::string> split_args = _split(argstr, "^-|\\s-");
85-
std::vector<std::string> arg_parts;
8679
std::string name;
87-
for (auto &split_arg : split_args) {
88-
std::vector<std::string> arg_parts = _split(split_arg, "\\s+");
89-
name = _trim_copy(arg_parts[0]);
90-
if (name.empty()) continue;
91-
if (name[0] == '-') {
92-
_add_variable(name, arg_parts, argv);
80+
std::vector<std::string> arg_parts;
81+
std::vector<std::string> free_args;
82+
auto push_arg = [&name, &arg_parts, this]() {
83+
if (!name.empty()) {
84+
if (name[0] == '-') {
85+
_add_variable(name, arg_parts);
86+
} else {
87+
for (char c : name) {
88+
_add_variable(std::string(1, c), arg_parts);
89+
}
90+
}
91+
arg_parts.clear();
92+
}
93+
};
94+
for (int i = 1; i < argc; i++) {
95+
if (std::strlen(argv[i]) == 0) {
96+
continue;
97+
} else if (argv[i][0] == '-') {
98+
push_arg();
99+
if (i == argc - 1) {
100+
name = &(argv[i][1]);
101+
push_arg();
102+
} else {
103+
name = &(argv[i][1]);
104+
}
105+
} else if (name.empty()) {
106+
free_args.push_back(argv[i]);
93107
} else {
94-
for (auto c : name) {
95-
_add_variable(std::string(1, c), arg_parts, argv);
108+
arg_parts.push_back(argv[i]);
109+
if (i == argc - 1) {
110+
push_arg();
96111
}
97112
}
98113
}
114+
_add_variable("", free_args);
99115
}
100116
if (!_help) {
101117
for (auto &a : _arguments) {
@@ -116,11 +132,14 @@ class ArgumentParser {
116132

117133
template <typename T>
118134
std::vector<T> getv(const std::string &name) {
119-
std::string argstr = get<std::string>(name);
135+
std::vector<std::string> argstr = getv<std::string>(name);
120136
std::vector<T> v;
121-
std::istringstream in(argstr);
122-
std::copy(std::istream_iterator<T>(in), std::istream_iterator<T>(),
123-
std::back_inserter(v));
137+
for (auto &s : argstr) {
138+
std::istringstream in(s);
139+
T t;
140+
in >> t;
141+
v.push_back(t);
142+
}
124143
return v;
125144
}
126145

@@ -145,24 +164,15 @@ class ArgumentParser {
145164
bool _required;
146165
};
147166
inline void _add_variable(std::string name,
148-
std::vector<std::string> &arg_parts, char *argv[]) {
167+
std::vector<std::string> &arg_parts) {
149168
if (name == "h" || name == "-help") {
150169
_help = true;
151-
print_help(argv[0]);
170+
print_help();
152171
}
153172
_ltrim(name, [](int c) { return c != (int)'-'; });
154173
name = _delimit(name);
155174
if (_pairs.find(name) != _pairs.end()) name = _pairs[name];
156-
std::string val;
157-
if (arg_parts.size() > 1) {
158-
val = std::accumulate(arg_parts.begin() + 1, arg_parts.end(),
159-
std::string(), [](std::string a, std::string b) {
160-
return _trim_copy(a) + " " + _trim_copy(b);
161-
});
162-
} else {
163-
val = "";
164-
}
165-
_variables[name] = val;
175+
_variables[name] = arg_parts;
166176
}
167177
static std::string _delimit(const std::string &name) {
168178
return std::string(std::min(name.size(), (size_t)2), '-').append(name);
@@ -184,13 +194,6 @@ class ArgumentParser {
184194
out = std::string("\"").append(out).append("\"");
185195
return out;
186196
}
187-
static std::vector<std::string> _split(const std::string &input,
188-
const std::string &regex) {
189-
// passing -1 as the submatch index parameter performs splitting
190-
std::regex re(regex);
191-
std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last;
192-
return {first, last};
193-
}
194197
static bool _not_space(int ch) { return !std::isspace(ch); }
195198
static inline void _ltrim(std::string &s, bool (*f)(int) = _not_space) {
196199
s.erase(s.begin(), std::find_if(s.begin(), s.end(), f));
@@ -219,17 +222,22 @@ class ArgumentParser {
219222
}
220223

221224
std::string _desc;
225+
std::string _bin;
222226
bool _help;
223227
std::vector<Argument> _arguments;
224-
std::unordered_map<std::string, std::string> _variables;
228+
std::unordered_map<std::string, std::vector<std::string>> _variables;
225229
std::unordered_map<std::string, std::string> _pairs;
226230
};
227231
template <>
228232
inline std::string ArgumentParser::get<std::string>(const std::string &name) {
229233
std::string t = _delimit(name);
230234
if (_pairs.find(t) != _pairs.end()) t = _pairs[t];
231235
auto v = _variables.find(t);
232-
if (v != _variables.end()) return v->second;
236+
if (v != _variables.end()) {
237+
return std::accumulate(
238+
v->second.begin(), v->second.end(), std::string(),
239+
[](std::string a, std::string b) { return a + " " + b; });
240+
}
233241
return "";
234242
}
235243
template <>
@@ -239,7 +247,12 @@ inline bool ArgumentParser::get<bool>(const std::string &name) {
239247
template <>
240248
inline std::vector<std::string> ArgumentParser::getv<std::string>(
241249
const std::string &name) {
242-
std::string argstr = get<std::string>(name);
243-
return _split(argstr, "\\s");
250+
std::string t = _delimit(name);
251+
if (_pairs.find(t) != _pairs.end()) t = _pairs[t];
252+
auto v = _variables.find(t);
253+
if (v != _variables.end()) {
254+
return v->second;
255+
}
256+
return std::vector<std::string>();
244257
}
245258
#endif

example.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@
1414
* Author: Jesse Laning
1515
*/
1616

17-
#include <iostream>
1817
#include "argparse.h"
1918

19+
#include <iostream>
20+
#include <iterator>
21+
2022
int main(int argc, char* argv[]) {
21-
// run as: [program name] -a 1 -sdfl --flag -v 1 2.7 3 4 9 8.12 87 6
23+
// run as: [program name] "0 -c" abc -a 1 -sdfl --flag -v 1 2.7 3 4 9 8.12 87
24+
// [program name] -sdfv 1 -o "C:\Users\User Name\Directory - Name\file.dat"
25+
// "C:\Users\User Name 2\Directory 2 - Name 2\file2.dat"
2226
ArgumentParser parser("Argument parser example");
2327
parser.add_argument("-a", "an integer");
2428
parser.add_argument("-s", "an combined flag", true);
@@ -27,21 +31,35 @@ int main(int argc, char* argv[]) {
2731
parser.add_argument("--flag", "a flag");
2832
parser.add_argument("-v", "a vector", true);
2933
parser.add_argument("-l", "--long", "a long argument", false);
34+
parser.add_argument("-o", "input files", false);
3035
try {
3136
parser.parse(argc, argv);
3237
} catch (const ArgumentParser::ArgumentNotFound& ex) {
3338
std::cout << ex.what() << std::endl;
3439
return 0;
3540
}
3641
if (parser.is_help()) return 0;
37-
std::cout << parser.get<int>("a") << std::endl;
42+
std::cout << "a: " << parser.get<int>("a") << std::endl;
3843
std::cout << "flag: " << std::boolalpha << parser.get<bool>("flag")
3944
<< std::endl;
4045
std::cout << "d: " << std::boolalpha << parser.get<bool>("d") << std::endl;
4146
std::cout << "long flag: " << std::boolalpha << parser.get<bool>("l")
4247
<< std::endl;
4348
auto v = parser.getv<double>("v");
49+
std::cout << "v: ";
4450
std::copy(v.begin(), v.end(), std::ostream_iterator<double>(std::cout, " "));
45-
if (v.size()) std::cout << std::endl;
51+
double sum;
52+
for (auto& d : v) sum += d;
53+
std::cout << " sum: " << sum << std::endl;
54+
auto f = parser.getv<std::string>("o");
55+
std::cout << "o: ";
56+
std::copy(f.begin(), f.end(),
57+
std::ostream_iterator<std::string>(std::cout, " | "));
58+
std::cout << std::endl;
59+
f = parser.getv<std::string>("");
60+
std::cout << "free args: ";
61+
std::copy(f.begin(), f.end(),
62+
std::ostream_iterator<std::string>(std::cout, " "));
63+
std::cout << std::endl;
4664
return 0;
4765
}

0 commit comments

Comments
 (0)