menu.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. const readline = require("readline");
  2. const menu = (choices, label) => {
  3. let selectedIndex = 0;
  4. const clearMenu = () => {
  5. readline.moveCursor(process.stdout, 0, -choices.length);
  6. readline.clearScreenDown(process.stdout);
  7. };
  8. const renderMenu = () => {
  9. choices.forEach((choice, index) => {
  10. if (index === selectedIndex) {
  11. console.log(`> ${choice}`);
  12. } else {
  13. console.log(` ${choice}`);
  14. }
  15. });
  16. };
  17. // Refactored to use a direction parameter for cleaner code
  18. function updateSelectedIndex(direction) {
  19. if (direction === "up") {
  20. selectedIndex = (selectedIndex - 1 + choices.length) % choices.length;
  21. } else if (direction === "down") {
  22. selectedIndex = (selectedIndex + 1) % choices.length;
  23. }
  24. clearMenu();
  25. renderMenu();
  26. }
  27. const handleKeyPress = (resolve) => (str, key) => {
  28. if (key.name === "up" || key.name === "down") {
  29. updateSelectedIndex(key.name);
  30. } else if (key.name === "return") {
  31. rl.close();
  32. resolve(choices[selectedIndex]);
  33. }
  34. };
  35. const rl = readline.createInterface({
  36. input: process.stdin,
  37. output: process.stdout,
  38. terminal: true,
  39. });
  40. return new Promise((resolve, reject) => {
  41. console.log(label);
  42. readline.emitKeypressEvents(process.stdin);
  43. if (process.stdin.isTTY) process.stdin.setRawMode(true);
  44. renderMenu();
  45. rl.input.on("keypress", handleKeyPress(resolve));
  46. });
  47. };
  48. exports.menu = menu;