select<T> method

T select<T>(
  1. String question,
  2. List<T> options, {
  3. required String label(
    1. T
    ),
  4. String describe(
    1. T
    )?,
  5. int defaultIndex = 0,
})

Asks the user to pick one of options from a numbered list.

Numbered selection rather than typed names: it cannot be misspelled, and it shows every valid answer without the user having to know them.

Implementation

T select<T>(
  String question,
  List<T> options, {
  required String Function(T) label,
  String Function(T)? describe,
  int defaultIndex = 0,
}) {
  _logger.logInfo('${ColorizeLogger.bold('?')} $question');
  for (var i = 0; i < options.length; i++) {
    final marker = i == defaultIndex ? '›' : ' ';
    final description = describe?.call(options[i]);
    _logger.logInfo(
      '  $marker ${i + 1}) ${label(options[i])}'
      '${description == null ? '' : '  ${ColorizeLogger.dim(description)}'}',
    );
  }

  while (true) {
    stdout.write(
      '  ${ColorizeLogger.dim('1-${options.length} (${defaultIndex + 1})')} ',
    );
    final answer = _readLine().trim();
    if (answer.isEmpty) return options[defaultIndex];

    final index = int.tryParse(answer);
    if (index != null && index >= 1 && index <= options.length) {
      return options[index - 1];
    }
    _logger.logWarning('enter a number between 1 and ${options.length}');
  }
}