feat: overhaul CLI with new AI commands and mole-style menu #6
@@ -130,6 +130,33 @@ async function dispatchMenuAction(key: string): Promise<number> {
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForEnter(): Promise<void> {
|
||||
const D = DIM();
|
||||
const R = RESET();
|
||||
process.stdout.write(`\n ${D}Press Enter to return to menu...${R}`);
|
||||
// Read a line from stdin (works in cooked mode — blocks until Enter)
|
||||
await new Promise<void>((resolve) => {
|
||||
const onData = (data: Buffer) => {
|
||||
process.stdin.removeListener("data", onData);
|
||||
resolve();
|
||||
};
|
||||
process.stdin.on("data", onData);
|
||||
// Resume stdin in case it was paused
|
||||
process.stdin.resume();
|
||||
});
|
||||
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
|
||||
}
|
||||
|
||||
async function dispatchAndWait(item: MenuItem, wasRaw: boolean): Promise<number> {
|
||||
showCursor();
|
||||
process.stdin.setRawMode(wasRaw === true);
|
||||
process.stdin.pause();
|
||||
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
|
||||
const result = await dispatchMenuAction(item.key);
|
||||
await waitForEnter();
|
||||
return result;
|
||||
}
|
||||
|
||||
async function showMenu(): Promise<number> {
|
||||
if (!isStdinTTY()) {
|
||||
console.error("Error: Interactive menu requires a TTY. Use --help for usage.");
|
||||
@@ -163,14 +190,8 @@ async function showMenu(): Promise<number> {
|
||||
|
||||
// Enter
|
||||
if (raw === "\r" || raw === "\n") {
|
||||
const item = MENU_ITEMS[cursor]!;
|
||||
showCursor();
|
||||
process.stdin.setRawMode(wasRaw === true);
|
||||
process.stdin.pause();
|
||||
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
|
||||
const result = await dispatchMenuAction(item.key);
|
||||
const result = await dispatchAndWait(MENU_ITEMS[cursor]!, wasRaw);
|
||||
if (result !== 0) return result;
|
||||
// Return to menu
|
||||
hideCursor();
|
||||
if (wasRaw !== true) process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
@@ -193,12 +214,7 @@ async function showMenu(): Promise<number> {
|
||||
if (idx < MENU_ITEMS.length) {
|
||||
cursor = idx;
|
||||
renderMenu(banner, cursor);
|
||||
const item = MENU_ITEMS[idx]!;
|
||||
showCursor();
|
||||
process.stdin.setRawMode(wasRaw === true);
|
||||
process.stdin.pause();
|
||||
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
|
||||
const result = await dispatchMenuAction(item.key);
|
||||
const result = await dispatchAndWait(MENU_ITEMS[idx]!, wasRaw);
|
||||
if (result !== 0) return result;
|
||||
hideCursor();
|
||||
if (wasRaw !== true) process.stdin.setRawMode(true);
|
||||
|
||||
Reference in New Issue
Block a user