promptAny method

List<String> promptAny(
  1. String? message, {
  2. String separator = ',',
})

Prompts user for a free-form list of responses.

This method requires a terminal to be attached to stdout. See https://api.dart.dev/stable/dart-io/Stdout/hasTerminal.html.

Implementation

List<String> promptAny(String? message, {String separator = ','}) {
  _stdin
    ..echoMode = false
    ..lineMode = false;

  final delimeter = '$separator ';
  var rawString = '';

  _stdout.write('$message ');

  while (true) {
    final key = _readKey();
    final isEnterOrReturnKey = key.controlChar == ControlCharacter.ctrlJ ||
        key.controlChar == ControlCharacter.ctrlM;
    final isDeleteOrBackspaceKey =
        key.controlChar == ControlCharacter.delete ||
            key.controlChar == ControlCharacter.backspace ||
            key.controlChar == ControlCharacter.ctrlH;

    if (isEnterOrReturnKey) break;

    if (isDeleteOrBackspaceKey) {
      if (rawString.isNotEmpty) {
        if (rawString.endsWith(delimeter)) {
          _stdout.write('\b\b\x1b[K');
          rawString = rawString.substring(0, rawString.length - 2);
        } else {
          _stdout.write('\b\x1b[K');
          rawString = rawString.substring(0, rawString.length - 1);
        }
      }
      continue;
    }

    if (key.char == separator) {
      _stdout.write(delimeter);
      rawString += delimeter;
    } else {
      _stdout.write(key.char);
      rawString += key.char;
    }
  }

  if (rawString.endsWith(delimeter)) {
    rawString = rawString.substring(0, rawString.length - 2);
  }

  final results = rawString.isEmpty ? <String>[] : rawString.split(delimeter);
  const clearLine = '\u001b[2K\r';
  _stdout.write(
    '$clearLine$message ${styleDim.wrap(lightCyan.wrap('$results'))}\n',
  );

  _stdin
    ..lineMode = true
    ..echoMode = true;
  return results;
}