|
28 | 28 | #include <functional> |
29 | 29 | #include <iostream> |
30 | 30 | #include <limits> |
31 | | -#include <string> |
| 31 | +#include <optional> |
32 | 32 | #include <stdexcept> |
| 33 | +#include <string> |
33 | 34 |
|
34 | 35 | #if defined(CMAKE) && __has_include("config.h") |
35 | 36 | # include "config.h" |
@@ -245,6 +246,12 @@ class Tool { |
245 | 246 |
|
246 | 247 | /** Returns & consumes the next arg, or fails if there are none. */ |
247 | 248 | 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 | + } |
248 | 255 | if ( !_argTokenizer.hasArgument() ) failMisuse(litecore::stringprintf("Missing argument: expected %s", what)); |
249 | 256 | std::string arg = _argTokenizer.argument(); |
250 | 257 | _argTokenizer.next(); |
@@ -294,39 +301,54 @@ class Tool { |
294 | 301 | virtual void processFlags(std::initializer_list<FlagSpec> specs) { |
295 | 302 | while ( true ) { |
296 | 303 | std::string flag = peekNextArg(); |
297 | | - if ( !flag.starts_with('-') || flag.size() > 20 ) return; |
| 304 | + if ( !flag.starts_with('-') ) return; |
298 | 305 | _argTokenizer.next(); |
299 | 306 |
|
300 | 307 | if ( flag == "--" ) return; // marks end of flags |
301 | 308 |
|
302 | | - bool handled; |
303 | 309 | 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; |
321 | 314 | } |
| 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; |
322 | 344 | } |
323 | 345 | } |
324 | 346 | } |
325 | 347 |
|
326 | 348 | /** Subroutine of processFlags; looks up one flag and calls its handler, or returns false. */ |
327 | 349 | virtual bool processFlag(const std::string& flag, const std::initializer_list<FlagSpec>& specs) { |
328 | 350 | for ( auto& spec : specs ) { |
329 | | - if ( flag == std::string(spec.flag) ) { |
| 351 | + if ( flag == spec.flag ) { |
330 | 352 | spec.handler(); |
331 | 353 | return true; |
332 | 354 | } |
@@ -363,4 +385,5 @@ class Tool { |
363 | 385 | std::string _toolPath; |
364 | 386 | std::string _name; |
365 | 387 | ArgumentTokenizer _argTokenizer; |
| 388 | + std::optional<std::string> _flagArg; |
366 | 389 | }; |
0 commit comments