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;