singleSelect<T> static method

T? singleSelect<T>({
  1. required String title,
  2. required List<T> options,
  3. int? defaultIndex = 0,
  4. FallbackLabelBuilder<T>? labelBuilder,
  5. bool returnDefaultOnEndOfInput = true,
})

Reads a one-based single selection.

defaultIndex is zero-based. Empty input returns that default item when it is in range, otherwise null. End-of-input follows the same policy unless returnDefaultOnEndOfInput is false, in which case it returns null.

Implementation

static T? singleSelect<T>({
  required String title,
  required List<T> options,
  int? defaultIndex = 0,
  FallbackLabelBuilder<T>? labelBuilder,
  bool returnDefaultOnEndOfInput = true,
}) {
  if (options.isEmpty) return null;

  final normalizedDefault = _normalizeDefaultIndex(
    defaultIndex,
    options.length,
  );

  while (true) {
    _writeOptions(title, options, labelBuilder);

    final suffix =
        normalizedDefault == null ? '' : ' [${normalizedDefault + 1}]';
    TerminalContext.output.write(
      'Select 1-${options.length}$suffix: ',
    );

    final line = TerminalContext.input.readLineSync();
    if (line == null) {
      return returnDefaultOnEndOfInput
          ? normalizedDefault == null
              ? null
              : options[normalizedDefault]
          : null;
    }
    if (line.trim().isEmpty) {
      return normalizedDefault == null ? null : options[normalizedDefault];
    }

    final selected = int.tryParse(line.trim());
    if (selected != null && selected >= 1 && selected <= options.length) {
      return options[selected - 1];
    }

    _writeError('Enter a number from 1 to ${options.length}.');
  }
}