cbx function

List<String> cbx(
  1. String message,
  2. List<String> keys,
  3. List<String> startingKeys
)

Implementation

List<String> cbx(
  String message,
  List<String> keys,
  List<String> startingKeys,
) {
  final selected = startingKeys;
  var hereIdx = 0;

  var needsClear = false;
  void writeIt() {
    if (needsClear) {
      for (var i = 0; i <= keys.length; i++) {
        prompts.goUpOneLine();
        prompts.clearLine();
      }
    } else {
      needsClear = true;
    }
    print(message);
    keys.asMap().forEach((index, option) {
      final isSelected = selected.contains(option);
      final isHere = index == hereIdx;
      final text = ' ${isSelected ? '♦' : '♢'} $option';
      final color = isHere ? ansi.cyan : ansi.darkGray;
      print(color.wrap(text));
    });
  }

  final oldEchoMode = stdin.echoMode;
  final oldLineMode = stdin.lineMode;
  while (true) {
    int ch;
    writeIt();

    try {
      stdin.lineMode = stdin.echoMode = false;
      ch = stdin.readByteSync();

      if (ch == ascii.$esc) {
        ch = stdin.readByteSync();
        if (ch == ascii.$lbracket) {
          ch = stdin.readByteSync();
          if (ch == ascii.$A) {
            // Up key
            hereIdx--;
            if (hereIdx < 0) {
              hereIdx = keys.length - 1;
            }
            writeIt();
          } else if (ch == ascii.$B) {
            // Down key
            hereIdx++;
            if (hereIdx >= keys.length) {
              hereIdx = 0;
            }
            writeIt();
          }
        }
      } else if (ch == ascii.$lf) {
        // Enter key pressed - submit
        return selected;
      } else if (ch == ascii.$space) {
        // Space key pressed - selected/unselect
        final key = keys[hereIdx];
        if (selected.contains(key)) {
          selected.remove(key);
        } else {
          selected.add(key);
        }
        writeIt();
      }
    } finally {
      stdin.lineMode = oldLineMode;
      stdin.echoMode = oldEchoMode;
    }
  }
}