Add --undefok support
Some other arg parsing libraries support an `--undefok` option which
suppresses the error that would normally surface if an unknown flag or
option is passed.
For example: https://gflags.github.io/gflags/#special
Add built in support, unconditionally, for `--undefok` in the parser.
The `undefok` option always supports multiple values and comma separated
values.
If an option named `undefok` is added to the `ArgParser` it will
override this behavior. It isn't possible to implement this behavior in
the calling code because the `callback` for when an option is parsed is
not triggered until after all arguments are parsed. Allowing the calling
code to override the `undefok` option, even though it can't implement
the expected semantics, retains backwards compatibility in the unlikely
case there are existing uses of that name.
- Add an `_undefok` field to `Parser` to track the names that suppressed
as options are parsed. Only the top level parser in a `parent` chain
will handle `undefok`.
- When parsing an otherwise unknown option named `undefok`, parse the
value and store in the allowed `_undefok` set.
- When parsing an otherwise unknown option with any other name already
in `_undefok`, silently drop it, along with any `=value` portion.
This implementation has the following limitations:
- The `--undefok` option must be passed _before_ the unknown option. If
the arguments come in the other order it will still fail.
- The unknown option must either be a flag, or must use the
`--name=value` syntax. If it is passed as `--name value` then the
value will show in `argResults.rest`. This could cause the argument to
get misinterpreted by the app.
diff --git a/lib/src/parser.dart b/lib/src/parser.dart
index 25497be..02c0dd4 100644
--- a/lib/src/parser.dart
+++ b/lib/src/parser.dart
@@ -34,6 +34,8 @@
/// The accumulated parsed options.
final Map<String, dynamic> results = <String, dynamic>{};
+ final _undefok = <String>{};
+
Parser(this.commandName, this.grammar, this.args,
[this.parent, List<String>? rest]) {
if (rest != null) this.rest.addAll(rest);
@@ -66,7 +68,8 @@
if (command != null) {
validate(rest.isEmpty, 'Cannot specify arguments before a command.');
var commandName = args.removeFirst();
- var commandParser = Parser(commandName, command, args, this, rest);
+ var commandParser =
+ Parser(commandName, command, args, this, rest);
try {
commandResults = commandParser.parse();
@@ -284,8 +287,24 @@
setFlag(results, option, false);
} else {
// Walk up to the parent command if possible.
- validate(parent != null, 'Could not find an option named "$name".');
- return parent!.parseLongOption();
+ if (parent != null) {
+ return parent!.parseLongOption();
+ }
+ if (name == 'undefok') {
+ args.removeFirst();
+ if (value == null) {
+ validate(args.isNotEmpty, 'Missing argument for "--undefok".');
+ value = current;
+ args.removeFirst();
+ }
+ _undefok.addAll(value.split(','));
+ return true;
+ }
+ if (_undefok.contains(name)) {
+ args.removeFirst();
+ return true;
+ }
+ validate(false, 'Could not find an option named "$name".');
}
return true;