Skip to content

Commit f0a5ed3

Browse files
committed
Change opt.anyUnits and opt.relative to use transform instead of parse actions
1 parent 233cfd2 commit f0a5ed3

4 files changed

Lines changed: 54 additions & 14 deletions

File tree

docs/guide.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ int main(int argc, char * argv[]) {
987987
.parse([](auto & cli, auto & opt, const string & val) {
988988
int tmp = *opt; // save the old value
989989
if (!opt.parseValue(val)) // parse the new value into opt
990-
return cli.badUsage(opt, val);
990+
return cli.badUsage(opt);
991991
*opt *= tmp; // multiply old and new together
992992
});
993993
if (!cli.parse(argc, argv))

libs/dimcli/cli.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,12 @@ struct Cli::Config {
191191
shared_ptr<locale> defLoc = make_shared<locale>();
192192
shared_ptr<locale> numLoc = make_shared<locale>("");
193193

194+
// Opt* and value actively being parsed, referenced servicing action
195+
// callbacks.
194196
Cli::OptBase * curOpt = {};
197+
string originalValue;
195198
string newValue;
199+
196200
int exitCode = kExitOk;
197201
string errMsg;
198202
string errDetail;
@@ -780,7 +784,7 @@ void Cli::newValue(const string & value) {
780784
if (parseBool(v, value)) {
781785
m_cfg->newValue = v ? "1" : "0";
782786
} else {
783-
badUsage(opt, value);
787+
badUsage(opt);
784788
}
785789
}
786790
}
@@ -1232,20 +1236,19 @@ void Cli::defParseAction(Cli & cli, OptBase & opt, const string & val) {
12321236

12331237
string desc;
12341238
writeChoicesDetail(&desc, opt.m_choiceDescs);
1235-
cli.badUsage(opt, val, desc);
1239+
cli.badUsage(opt, nullptr, desc);
12361240
}
12371241

12381242
//===========================================================================
12391243
// static
12401244
void Cli::argSrcFileRelAction(Cli & cli, OptBase & opt, const string & rel) {
1241-
string val = rel;
12421245
#ifdef DIMCLI_LIB_FILESYSTEM
12431246
if (opt.srcType() == ArgSrc::kFile) {
12441247
auto p = fs::u8path(opt.srcName()).parent_path() / rel;
1245-
val = (char *) p.generic_u8string().c_str();
1248+
string val = (char *) p.generic_u8string().c_str();
1249+
cli.newValue(val);
12461250
}
12471251
#endif
1248-
defParseAction(cli, opt, val);
12491252
}
12501253

12511254
//===========================================================================
@@ -2624,6 +2627,7 @@ Cli & Cli::resetValues() & {
26242627
for (auto && opt : m_cfg->opts)
26252628
opt->reset();
26262629
m_cfg->curOpt = {};
2630+
m_cfg->originalValue.clear();
26272631
m_cfg->newValue.clear();
26282632
m_cfg->parseExit = false;
26292633
m_cfg->exitCode = kExitOk;
@@ -2674,7 +2678,17 @@ void Cli::badUsage(
26742678
const string & detail
26752679
) {
26762680
string prefix = "Invalid '" + opt.from() + "' value";
2677-
return badUsage(prefix, value, detail);
2681+
badUsage(prefix, value, detail);
2682+
}
2683+
2684+
//===========================================================================
2685+
void Cli::badUsage(
2686+
const OptBase & opt,
2687+
nullptr_t,
2688+
const string & detail
2689+
) {
2690+
string prefix = "Invalid '" + opt.from() + "' value";
2691+
badUsage(prefix, m_cfg->originalValue, detail);
26782692
}
26792693

26802694
//===========================================================================
@@ -2747,6 +2761,7 @@ bool Cli::parseValue(
27472761
return false;
27482762
}
27492763
if (ptr) {
2764+
m_cfg->originalValue = ptr;
27502765
m_cfg->newValue = ptr;
27512766
m_cfg->curOpt = &opt;
27522767
opt.doTransforms(*this);
@@ -2756,10 +2771,12 @@ bool Cli::parseValue(
27562771
if (!parseAborted())
27572772
opt.doChecks(*this);
27582773
} else {
2774+
m_cfg->originalValue.clear();
27592775
m_cfg->newValue.clear();
27602776
opt.assignImplicit();
27612777
opt.doChecks(*this);
27622778
}
2779+
m_cfg->originalValue.clear();
27632780
m_cfg->newValue.clear();
27642781
return !parseAborted();
27652782
}

libs/dimcli/cli.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,15 @@ class DIMCLI_LIB_DECL Cli {
594594
const std::string & detail = {}
595595
);
596596

597+
// Intended for use from transform, parse, and check actions. Calls
598+
// cli.badUsage(opt, value, detail) with value set to the string value
599+
// being parsed. Outside of parsing an empty string is used for the value.
600+
void badUsage(
601+
const OptBase & opt,
602+
std::nullptr_t value = nullptr,
603+
const std::string & detail = {}
604+
);
605+
597606
// Calls cli.badUsage with "Out of range" message and the low and high in
598607
// the detail.
599608
template <typename A, typename T>
@@ -2324,7 +2333,7 @@ A & Cli::OptShim<A, T>::anyUnits(InputIt first, InputIt last, int flags) {
23242333
} else {
23252334
units.insert(first, last);
23262335
}
2327-
return parse([units, flags](auto & cli, auto & opt, auto & val) {
2336+
return transform([units, flags](auto & cli, auto & opt, auto & val) {
23282337
long double dval;
23292338
bool success = true;
23302339
if (!opt.withUnits(dval, cli, val, units, flags))
@@ -2344,10 +2353,7 @@ A & Cli::OptShim<A, T>::anyUnits(InputIt first, InputIt last, int flags) {
23442353
assert(success // LCOV_EXCL_LINE
23452354
&& "Internal dimcli error: convert double to string failed.");
23462355
}
2347-
if (!opt.parseValue(sval)) {
2348-
success = false;
2349-
cli.badUsage(opt, val);
2350-
}
2356+
cli.newValue(sval);
23512357
});
23522358
}
23532359

@@ -2396,7 +2402,7 @@ A & Cli::OptShim<A, T>::prompt(const std::string & msg, int flags) {
23962402
template <typename A, typename T>
23972403
A & Cli::OptShim<A, T>::resolve(ArgSrc::Type srcType) {
23982404
if (srcType == ArgSrc::kFile)
2399-
parse(Cli::argSrcFileRelAction).valueDesc("FILE");
2405+
transform(Cli::argSrcFileRelAction).valueDesc("FILE");
24002406
return static_cast<A &>(*this);
24012407
}
24022408

tests/cli/clitest.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2617,7 +2617,11 @@ static void unitsTests() {
26172617
"Error: Invalid 'V' value: 1B\n"
26182618
"Units symbol 'B' not recognized.\n"
26192619
);
2620+
}
26202621

2622+
{
2623+
cli = {};
2624+
auto & dbls = cli.optVec<double>("[V]");
26212625
dbls.siUnits("b", cli.fUnitBinaryPrefix);
26222626
EXPECT_PARSE(cli, "1k 1ki");
26232627
EXPECT_EQUAL(dbls[0], 1024);
@@ -2627,7 +2631,11 @@ static void unitsTests() {
26272631
Error: Invalid 'V' value: 1000m
26282632
Units symbol 'm' not recognized.
26292633
)");
2634+
}
26302635

2636+
{
2637+
cli = {};
2638+
auto & dbls = cli.optVec<double>("[V]");
26312639
dbls.siUnits("b", cli.fUnitInsensitive);
26322640
EXPECT_PARSE(cli, "1 1b 1B 1kB 1Kb");
26332641
EXPECT_EQUAL(dbls[0], 1);
@@ -2640,8 +2648,12 @@ Units symbol 'm' not recognized.
26402648
Error: Invalid 'V' value: 1000u
26412649
Units symbol 'u' not recognized.
26422650
)");
2651+
}
26432652

2644-
// with fUnitRequire
2653+
// with fUnitRequire
2654+
{
2655+
cli = {};
2656+
auto & dbls = cli.optVec<double>("[V]");
26452657
dbls.siUnits("b", cli.fUnitRequire);
26462658
EXPECT_PARSE(cli, "1b 1kb");
26472659
EXPECT_EQUAL(dbls[0], 1);
@@ -2664,6 +2676,11 @@ Units symbol 'k' not recognized.
26642676
EXPECT_ERR(cli, "Error: Invalid 'V' value: kb\n");
26652677
EXPECT_PARSE(cli, "1x23kb", false);
26662678
EXPECT_ERR(cli, "Error: Invalid 'V' value: 1x23kb\n");
2679+
}
2680+
2681+
{
2682+
cli = {};
2683+
auto & dbls = cli.optVec<double>("[V]");
26672684
dbls.siUnits("", cli.fUnitRequire);
26682685
EXPECT_PARSE(cli, "1k");
26692686
EXPECT_EQUAL(dbls[0], 1000);

0 commit comments

Comments
 (0)