UNPKG

openai-cli-unofficial

Version:

A powerful OpenAI CLI Coding Agent built with TypeScript

124 lines 4.98 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.InteractiveMenu = exports.GeminiStyleMenu = void 0; const prompts_1 = require("@inquirer/prompts"); const chalk_1 = __importDefault(require("chalk")); class GeminiStyleMenu { static async show(options) { // 使用新的@inquirer/prompts的select const choices = options.choices.map(choice => ({ name: this.formatChoice(choice, false), value: choice.value, description: choice.description })); const result = await (0, prompts_1.select)({ message: options.message, choices }); return result; } static formatChoice(choice, isSelected) { const circle = isSelected ? '●' : '○'; const textColor = isSelected ? chalk_1.default.cyan : chalk_1.default.white; const circleColor = isSelected ? chalk_1.default.cyan : chalk_1.default.gray; let formatted = `${circleColor(circle)} ${textColor(choice.name)}`; if (choice.description) { formatted += chalk_1.default.gray(` - ${choice.description}`); } return formatted; } } exports.GeminiStyleMenu = GeminiStyleMenu; // 扩展inquirer的样式 class InteractiveMenu { static async show(options) { console.log(chalk_1.default.white(options.message)); console.log(); let selectedIndex = 0; const choices = options.choices; let isFirstRender = true; const renderMenu = () => { return choices.map((choice, index) => { const isSelected = index === selectedIndex; const circle = isSelected ? chalk_1.default.cyan('●') : chalk_1.default.gray('○'); const text = isSelected ? chalk_1.default.cyan.bold(choice.name) : chalk_1.default.white(choice.name); const description = choice.description ? (isSelected ? chalk_1.default.cyan(` ${choice.description}`) : chalk_1.default.gray(` ${choice.description}`)) : ''; return ` ${circle} ${text}${description}`; }); }; const showMenu = () => { if (!isFirstRender) { // 隐藏光标,减少闪烁 process.stdout.write('\x1B[?25l'); // 移动到菜单开始位置 process.stdout.write('\x1B[' + choices.length + 'A'); // 清除从当前位置到屏幕末尾的内容 process.stdout.write('\x1B[0J'); } // 批量渲染所有菜单项 const menuLines = renderMenu(); process.stdout.write(menuLines.join('\n') + '\n'); if (!isFirstRender) { // 显示光标 process.stdout.write('\x1B[?25h'); } isFirstRender = false; }; return new Promise((resolve) => { // 隐藏光标以减少闪烁 process.stdout.write('\x1B[?25l'); // 初始显示 showMenu(); const stdin = process.stdin; if (stdin.isTTY) { stdin.setRawMode(true); } stdin.resume(); stdin.setEncoding('utf8'); const cleanup = () => { stdin.removeListener('data', keyHandler); if (stdin.isTTY) { try { stdin.setRawMode(false); } catch (error) { // 忽略错误 } } stdin.pause(); // 恢复光标显示 process.stdout.write('\x1B[?25h'); }; const keyHandler = (key) => { switch (key) { case '\u001B[A': // 上箭头 selectedIndex = selectedIndex > 0 ? selectedIndex - 1 : choices.length - 1; showMenu(); break; case '\u001B[B': // 下箭头 selectedIndex = selectedIndex < choices.length - 1 ? selectedIndex + 1 : 0; showMenu(); break; case '\r': // 回车 case '\n': cleanup(); console.log(); resolve(choices[selectedIndex].value); break; case '\u0003': // Ctrl+C cleanup(); process.exit(); break; } }; stdin.on('data', keyHandler); }); } } exports.InteractiveMenu = InteractiveMenu; //# sourceMappingURL=menu.js.map