Skip to content

Commit d98aaf0

Browse files
committed
better Args handling of individual char switches
1 parent a14f9a7 commit d98aaf0

File tree

3 files changed

+138
-38
lines changed

3 files changed

+138
-38
lines changed

kit/args/args.cpp

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ void Args :: analyze()
1818
if(boost::starts_with(arg, "--"))
1919
{
2020
if(arg.length()==2)
21-
after_sep = true;
21+
after_sep = true; // empty -- is a separator
2222

2323
if(!after_sep)
2424
{
@@ -34,14 +34,74 @@ void Args :: analyze()
3434
if(!value.empty())
3535
if(!m_Values.insert({key,value}).second)
3636
throw exception(); // failed to insert
37+
38+
m_Switches.insert(remove_dashes(key)); // insert key as switch
39+
}
40+
else
41+
{
42+
m_Switches.insert(remove_dashes(arg)); // just a switch, --test is test
3743
}
3844
}
3945
}
40-
else if(not boost::starts_with(arg, "-"))
46+
else if(boost::starts_with(arg, "-")) // only one dash? (above check is two)
47+
{
48+
string flags = arg.substr(1); // remove one dash
49+
for(auto&& ch: flags)
50+
m_Switches.insert(string()+ch); // add chars separately
51+
}
52+
else
53+
{
54+
// no - or --, assume its a filename
4155
m_Filenames.push_back(arg);
56+
}
4257
}
4358
}
4459

60+
string Args :: remove_dashes(string s, bool* success) // static
61+
{
62+
if(success)
63+
*success = false;
64+
65+
if(boost::starts_with(s,"--"))
66+
{
67+
s = s.substr(2);
68+
if(success)
69+
*success = true;
70+
}
71+
else if(boost::starts_with(s,"-"))
72+
{
73+
s = s.substr(1);
74+
if(success)
75+
*success = true;
76+
}
77+
return s;
78+
}
79+
80+
bool Args :: has(std::string op) const
81+
{
82+
bool removed;
83+
string flag = remove_dashes(op, &removed);
84+
if(not removed)
85+
return kit::has(m_Args, op);
86+
87+
if(not flag.empty())
88+
return kit::has(m_Switches, flag);
89+
90+
assert(false);
91+
}
92+
93+
bool Args :: has(char ch, std::string op) const
94+
{
95+
if(boost::starts_with(op, "--"))
96+
op = op.substr(2); // remove --
97+
else if(boost::starts_with(op, "-"))
98+
op = op.substr(1);
99+
auto flag = string()+ch;
100+
return (kit::has(m_Switches, flag) ||
101+
(not op.empty() && kit::has(m_Switches, op))
102+
);
103+
}
104+
45105
void Args :: schema(std::string docstring)
46106
{
47107
if(docstring.empty())

kit/args/args.h

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <vector>
55
#include <map>
66
#include <string>
7+
#include <set>
78
#include "../kit.h"
89
#include <boost/algorithm/string.hpp>
910
#include <boost/format.hpp>
@@ -66,9 +67,12 @@ class Args
6667
return true;
6768
return false;
6869
}
69-
bool has(const std::string& s) const {
70-
return kit::has(m_Args, s);
71-
}
70+
71+
// [OLD]
72+
//bool has(const std::string& s) const {
73+
// return kit::has(m_Args, s);
74+
//}
75+
7276
bool has_before(
7377
const std::string& match, const std::string& sep
7478
) const {
@@ -227,16 +231,26 @@ class Args
227231
}
228232
}
229233

230-
// tests for a switch and its associated char
231-
bool has(char c, std::string s) const {
232-
assert(not boost::starts_with(s, "--"));
233-
return has(c) || has(std::string("--")+s);
234-
}
235-
bool has(char c) const {
236-
std::string chs = chars();
237-
return chs.find(c) != std::string::npos;
238-
}
239-
// returns string containing all provided char switches
234+
// [OLD] tests for a switch and its associated char
235+
//bool has(char c, std::string s) const {
236+
// if(boost::starts_with(s, "--"))
237+
// s = s.substr(2); // remove --
238+
// else if(boost::starts_with(s, "-"))
239+
// s = s.substr(1);
240+
// if(has(c) || has(std::string("--")+s)
241+
// return true;
242+
// if(option(c,s))
243+
// return true;
244+
// return false;
245+
//}
246+
247+
// [DEPRECATED]
248+
//bool has(char c) const {
249+
// std::string chs = chars();
250+
// return chs.find(c) != std::string::npos;
251+
//}
252+
253+
// [DEPRECATED] returns string containing all provided char switches
240254
std::string chars() const {
241255
std::string r;
242256
for(auto&& a: m_Args)
@@ -288,8 +302,13 @@ class Args
288302
m_Filename = fn;
289303
}
290304

305+
bool has(std::string op) const;
306+
bool has(char ch, std::string full = std::string()) const;
307+
291308
private:
292309

310+
static std::string remove_dashes(std::string s, bool* success = nullptr);
311+
293312
struct Schema
294313
{
295314
std::vector<std::string> allowed;
@@ -305,6 +324,12 @@ class Args
305324
std::map<std::string, std::string> m_Values;
306325
std::string m_Filename;
307326
boost::optional<Schema> m_Schema;
327+
328+
// all options broken down separately
329+
// ./program -abc --test
330+
// will contain -a, -b, -c, and --test
331+
// use has() to check this
332+
std::set<std::string> m_Switches;
308333
};
309334

310335
#endif

tests/args.test.cpp

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,20 @@ TEST_CASE("Args","[args]") {
2929
SECTION("has") {
3030
// empty
3131
Args args;
32-
REQUIRE(not args.has("foobar"));
32+
REQUIRE(not args.has("foo"));
33+
REQUIRE(not args.has("-f"));
34+
REQUIRE(not args.has("--foobar"));
3335

3436
// single arg
35-
args = Args(vector<string>{"foobar"});
36-
REQUIRE(args.has("foobar"));
37-
REQUIRE(not args.has("foo"));
37+
args = Args(vector<string>{"--foobar"});
38+
REQUIRE(args.has("--foobar"));
39+
REQUIRE(not args.has("--foo"));
3840

3941
// multiple args
40-
args = Args(vector<string>{"foo", "bar"});
41-
REQUIRE(args.has("foo"));
42-
REQUIRE(args.has("bar"));
43-
REQUIRE(not args.has("baz"));
42+
args = Args(vector<string>{"--foo", "--bar"});
43+
REQUIRE(args.has("--foo"));
44+
REQUIRE(args.has("--bar"));
45+
REQUIRE(not args.has("--baz"));
4446

4547
// switches
4648
args = Args();
@@ -52,25 +54,38 @@ TEST_CASE("Args","[args]") {
5254
REQUIRE(args.has('v', "verbose")); // single char
5355
REQUIRE(not args.has('n', "nope"));
5456

55-
// multiple char switches
56-
args = Args(vector<string>{"-abc"}, "-a -b -c");
57-
REQUIRE(args.has('a', "achar"));
58-
REQUIRE(args.has('b', "bchar"));
59-
REQUIRE(args.has('c', "cchar"));
60-
args = Args(vector<string>{"-ac"}, "-a -b -c");
61-
REQUIRE(args.has('a', "achar"));
62-
REQUIRE(not args.has('b', "bchar"));
63-
REQUIRE(args.has('c', "cchar"));
57+
// multiple char switches (not combined)
58+
//args = Args(vector<string>{"-abc"}, "-a -b -c");
59+
//REQUIRE(args.has('a', "achar"));
60+
//REQUIRE(args.has('b', "bchar"));
61+
//REQUIRE(args.has('c', "cchar"));
62+
//args = Args(vector<string>{"-ac"}, "-a -b -c");
63+
//REQUIRE(args.has('a', "achar"));
64+
//REQUIRE(not args.has('b', "bchar"));
65+
//REQUIRE(args.has('c', "cchar"));
6466
}
6567

68+
SECTION("option") {
69+
Args args;
70+
args = Args(vector<string>{"-abc", "-d", "--go"});
71+
REQUIRE(args.has('a'));
72+
REQUIRE(args.has("-a"));
73+
REQUIRE(args.has('b', "berry"));
74+
REQUIRE(args.has('c'));
75+
REQUIRE(args.has('d', "door"));
76+
REQUIRE(not args.has('e'));
77+
REQUIRE(not args.has('f', "foo"));
78+
REQUIRE(args.has('g', "go"));
79+
}
80+
6681
SECTION("any") {
6782
Args args;
68-
args = Args(vector<string>{"foo", "bar"});
69-
REQUIRE(not args.any({"bin"}));
70-
REQUIRE(not args.any({"bin","baz"}));
71-
REQUIRE(args.any({"bar","bin"}));
72-
REQUIRE(args.any({"bin","bar"}));
73-
REQUIRE(args.any({"foo","bar"}));
83+
args = Args(vector<string>{"--foo", "--bar"});
84+
REQUIRE(not args.any({"--bin"}));
85+
REQUIRE(not args.any({"--bin","--baz"}));
86+
REQUIRE(args.any({"--bar","--bin"}));
87+
REQUIRE(args.any({"--bin","--bar"}));
88+
REQUIRE(args.any({"--foo","--bar"}));
7489
}
7590

7691
SECTION("key-value") {

0 commit comments

Comments
 (0)