Args.parse constructor

Args.parse(
  1. List<String> args
)

Implementation

factory Args.parse(List<String> args) {
  // --no-<key> should be false under <key>
  // --<key> should be true under <key>
  // --key=value should be value under key
  final mapped = <String, dynamic>{};
  final rest = <String>[];

  void add(String rawKey, dynamic rawValue) {
    final key = switch (rawKey.split('--')) {
      [final key] => key,
      [_, final key] => key,
      _ => throw ArgumentError('Invalid key: $rawKey'),
    };

    final value = switch (rawValue) {
      final String string
          when string.contains(RegExp(r'^".*"$')) ||
              string.contains(RegExp(r"^'.*'$")) =>
        string.substring(1, string.length - 1),
      final value => value,
    };

    if (mapped[key] case null) {
      mapped[key] = value;
      return;
    }

    // add to existing list of values
    // ignore: strict_raw_type
    if (mapped[key] case final Iterable list) {
      mapped[key] = list.followedBy([value]);
      return;
    }

    // starts a new list
    mapped[key] = [mapped[key], value];
  }

  for (var i = 0; i < args.length; i++) {
    final arg = args[i];

    if (!arg.startsWith('--')) {
      rest.add(arg);
      continue;
    }

    if (arg.split('=') case [final key, final value]) {
      add(key, value);
      continue;
    }

    if (arg.split('--no-') case [_, final key]) {
      mapped[key] = false;
      continue;
    }

    final key = arg.substring(2);

    if (i + 1 < args.length) {
      if (args[i + 1] case final String value when !value.startsWith('--')) {
        add(key, value);
        i++;
        continue;
      }
    }

    mapped[key] = true;
  }

  return Args(args: mapped, rest: rest);
}