Skip to content

[config] Named Option Group limitation+suggestion #70

@indraneel12

Description

@indraneel12

Premise

The Package Documentation claims that Named Option groups are supported:

Package Documentation Image

Problem

Part of its implementation doc mentions "[name] might be used as group header in usage information" (emphasis mine):

Function Documentation Image

I'm not sure how the current package implementation lays any road to get the Option Name displayed in Usage information, while "might be" suggests there exists some case where the desired behavior is achieved. The name property exists, but how/whether does it reach the usage output?

Workaround

Possibly, this problem indicates a potential limitation of the current implementation:

void addOptionsToParser(
  final Iterable<OptionDefinition> argNameOpts,
  final ArgParser argParser,
) {
  for (final opt in argNameOpts) {
    opt.option._addToArgParser(argParser);
  }
}

As of now, I have overcome this problem by adding the package locally and editing only the aforementioned function like so:

void addOptionsToParser(
  final Iterable<OptionDefinition> argNameOpts,
  final ArgParser argParser,
) {
  final optionGroups = <OptionGroup, List<OptionDefinition>>{};
  final grouplessOptions = <OptionDefinition>[];
  for (final opt in argNameOpts) {
    final group = opt.option.group;
    if (group != null) {
      optionGroups.update(
        group,
        (final value) => [...value, opt],
        ifAbsent: () => [opt],
      );
    } else {
      grouplessOptions.add(opt);
    }
  }
  for (final opt in grouplessOptions) {
    opt.option._addToArgParser(argParser);
  }
  final nAnonymousGroup = optionGroups.keys
      .where((final group) => group.name.trim().isEmpty)
      .length;
  var iAnonymousGroup = 0;
  optionGroups.forEach((final group, final options) {
    argParser.addSeparator(
      group.name.trim().isNotEmpty
          ? group.name
          : 'Option Group${nAnonymousGroup > 1 ? " ${++iAnonymousGroup}" : ""}',
    );
    for (final opt in options) {
      opt.option._addToArgParser(argParser);
    }
  });
}

Features:

  • all non-empty (based on full whitespace) Group Names are shown as-is in Usage
  • all empty Group Names are altered to a count-based default group-name within Usage
  • all Groupless Options are shown first (in an unnamed section)
  • relative order of all Options within a Group is preserved
  • relative order of all Groups is preserved

Suggestion

I like the overall inherit-and-improve facilities available from this package. Akin to how the package delegates run and runCommand, wouldn't it be nice to have a similar design approach towards addOptionsToParser? For example, a separate base/abstract function (somewhere as deemed appropriate by the package designers) that handles this group-logic separately, which can be overridden by the user without affecting the original intention of adding options to the parser:

...
program reaches addOptionsToParser(...)
    [handle private code]
    call overridableFunctionForThisTask(...)
    if all options were not added, throw an Error e.g. StateError
    [handle private code]
program continues
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions