pick static method

String? pick(
  1. String parameterName, {
  2. String? description,
})

Shows an interactive menu to select a boolean value. Returns the selected value ('true' or 'false') or null if cancelled.

Implementation

static String? pick(String parameterName, {String? description}) {
  const values = ['false', 'true'];
  int selectedIndex = 0; // Start with false selected (index 0)

  // Helper function to display the menu
  void displayMenu() {
    print('');
    print('Select value for ${colors.blue}$parameterName${colors.reset}:');
    if (description != null && description.isNotEmpty) {
      print('${colors.gray}$description${colors.reset}');
    }
    print('');

    for (var i = 0; i < values.length; i++) {
      final value = values[i];
      final isSelected = i == selectedIndex;

      // Build display string - no trailing spaces for non-selected
      String display = isSelected ? '    ${colors.green}$i. $value ✓${colors.reset}' : '    $i. $value';

      print(display);
    }

    print('');
    print('${colors.gray}Use arrows to navigate, 0/f for false, 1/t for true${colors.reset}');
    print('${colors.gray}Enter to confirm, Esc to cancel${colors.reset}');
  }

  // Display initial menu
  displayMenu();

  // Enable raw mode to detect arrow keys and ESC
  stdin.echoMode = false;
  stdin.lineMode = false;

  while (true) {
    final charCode = stdin.readByteSync();

    // ESC key (27) - check if it's part of arrow key sequence
    if (charCode == 27) {
      // Sleep briefly to see if more bytes are coming (for arrow keys)
      sleep(Duration(milliseconds: 10));

      // Check if there's more input (arrow keys send ESC[A/B/C/D)
      if (stdin.hasTerminal) {
        try {
          // Try to read next byte without blocking
          final bytesAvailable = stdin.readByteSync();

          if (bytesAvailable == 91) {
            // '[' character - this is an arrow key sequence
            final arrowChar = stdin.readByteSync();

            // Arrow Up (65 = 'A')
            if (arrowChar == 65) {
              selectedIndex = (selectedIndex - 1 + values.length) % values.length;
              // Clear screen and redraw
              _clearScreen(values.length + 6);
              displayMenu();
              continue;
            }

            // Arrow Down (66 = 'B')
            if (arrowChar == 66) {
              selectedIndex = (selectedIndex + 1) % values.length;
              // Clear screen and redraw
              _clearScreen(values.length + 6);
              displayMenu();
              continue;
            }
          }
        } catch (e) {
          // No more bytes available - it's just ESC key
        }
      }

      // Just ESC key - cancel
      stdin.echoMode = true;
      stdin.lineMode = true;
      print('\n${colors.yellow}Cancelled${colors.reset}');
      return null;
    }

    // Enter key (10 or 13) - execute selected option
    if (charCode == 10 || charCode == 13) {
      stdin.echoMode = true;
      stdin.lineMode = true;
      print('');
      return values[selectedIndex];
    }

    // '0' key (48) or 'f' key (102) or 'F' key (70) - select false
    if (charCode == 48 || charCode == 102 || charCode == 70) {
      stdin.echoMode = true;
      stdin.lineMode = true;
      print('');
      return 'false';
    }

    // '1' key (49) or 't' key (116) or 'T' key (84) - select true
    if (charCode == 49 || charCode == 116 || charCode == 84) {
      stdin.echoMode = true;
      stdin.lineMode = true;
      print('');
      return 'true';
    }
  }
}