Skip to content

Commit 9a099dc

Browse files
committed
Flag parser now supports --flag=value
During parsing the `=value` part is removed from the flag name, and a call to `nextArg()` in a handler will return that value.
1 parent 7a46221 commit 9a099dc

File tree

1 file changed

+44
-21
lines changed

1 file changed

+44
-21
lines changed

tool_support/Tool.hh

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
#include <functional>
2929
#include <iostream>
3030
#include <limits>
31-
#include <string>
31+
#include <optional>
3232
#include <stdexcept>
33+
#include <string>
3334

3435
#if defined(CMAKE) && __has_include("config.h")
3536
# include "config.h"
@@ -245,6 +246,12 @@ class Tool {
245246

246247
/** Returns & consumes the next arg, or fails if there are none. */
247248
std::string nextArg(const char* what) {
249+
if (_flagArg) {
250+
// This is the part after the `=` while handling a flag of the form `--flag=value`
251+
std::string arg = std::move(*_flagArg);
252+
_flagArg = std::nullopt;
253+
return arg;
254+
}
248255
if ( !_argTokenizer.hasArgument() ) failMisuse(litecore::stringprintf("Missing argument: expected %s", what));
249256
std::string arg = _argTokenizer.argument();
250257
_argTokenizer.next();
@@ -294,39 +301,54 @@ class Tool {
294301
virtual void processFlags(std::initializer_list<FlagSpec> specs) {
295302
while ( true ) {
296303
std::string flag = peekNextArg();
297-
if ( !flag.starts_with('-') || flag.size() > 20 ) return;
304+
if ( !flag.starts_with('-') ) return;
298305
_argTokenizer.next();
299306

300307
if ( flag == "--" ) return; // marks end of flags
301308

302-
bool handled;
303309
try {
304-
handled = processFlag(flag, specs);
305-
} catch ( std::exception const& x ) { fail("in flag " + flag + ": " + x.what()); }
306-
307-
if ( !handled ) {
308-
// Flags all subcommands accept:
309-
if ( flag == "--help" ) {
310-
usage();
311-
exit(0);
312-
} else if ( flag == "--verbose" || flag == "-v" ) {
313-
++_verbose;
314-
} else if ( flag == "--color" ) {
315-
enableColor();
316-
} else if ( flag == "--version" ) {
317-
std::cout << _name << " " << TOOLS_VERSION_STRING << std::endl << std::endl;
318-
exit(0);
319-
} else {
320-
fail(std::string("Unknown flag ") + flag);
310+
if (auto [f, arg] = litecore::split2(flag, "="); !arg.empty()) {
311+
// Flag of the form `--flag=value`; treat `value` as the next arg during parsing
312+
flag = f;
313+
_flagArg = arg;
321314
}
315+
316+
bool handled;
317+
try {
318+
handled = processFlag(flag, specs);
319+
} catch ( std::exception const& x ) { fail("in flag " + flag + ": " + x.what()); }
320+
321+
if ( !handled ) {
322+
// Flags all subcommands accept:
323+
if ( flag == "--help" ) {
324+
usage();
325+
exit(0);
326+
} else if ( flag == "--verbose" || flag == "-v" ) {
327+
++_verbose;
328+
} else if ( flag == "--color" ) {
329+
enableColor();
330+
} else if ( flag == "--version" ) {
331+
std::cout << _name << " " << TOOLS_VERSION_STRING << std::endl << std::endl;
332+
exit(0);
333+
} else {
334+
fail(std::string("Unknown flag ") + flag);
335+
}
336+
}
337+
338+
if (_flagArg) // arg portion of flag wasn't consumed by handler
339+
fail("Flag " + flag + " does not take an argument");
340+
341+
} catch (...) {
342+
_flagArg = std::nullopt;
343+
throw;
322344
}
323345
}
324346
}
325347

326348
/** Subroutine of processFlags; looks up one flag and calls its handler, or returns false. */
327349
virtual bool processFlag(const std::string& flag, const std::initializer_list<FlagSpec>& specs) {
328350
for ( auto& spec : specs ) {
329-
if ( flag == std::string(spec.flag) ) {
351+
if ( flag == spec.flag ) {
330352
spec.handler();
331353
return true;
332354
}
@@ -363,4 +385,5 @@ class Tool {
363385
std::string _toolPath;
364386
std::string _name;
365387
ArgumentTokenizer _argTokenizer;
388+
std::optional<std::string> _flagArg;
366389
};

0 commit comments

Comments
 (0)