fix(ui): add 'Press Enter to return' pause after subcommand completes
After a subcommand returns (especially 'Nothing to commit' cases), the menu no longer immediately redraws and hides the message. Instead, the user sees the subcommand output plus a 'Press Enter to return to menu' prompt, giving them time to read the result before returning.
This commit is contained in:
@@ -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> {
|
async function showMenu(): Promise<number> {
|
||||||
if (!isStdinTTY()) {
|
if (!isStdinTTY()) {
|
||||||
console.error("Error: Interactive menu requires a TTY. Use --help for usage.");
|
console.error("Error: Interactive menu requires a TTY. Use --help for usage.");
|
||||||
@@ -163,14 +190,8 @@ async function showMenu(): Promise<number> {
|
|||||||
|
|
||||||
// Enter
|
// Enter
|
||||||
if (raw === "\r" || raw === "\n") {
|
if (raw === "\r" || raw === "\n") {
|
||||||
const item = MENU_ITEMS[cursor]!;
|
const result = await dispatchAndWait(MENU_ITEMS[cursor]!, wasRaw);
|
||||||
showCursor();
|
|
||||||
process.stdin.setRawMode(wasRaw === true);
|
|
||||||
process.stdin.pause();
|
|
||||||
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
|
|
||||||
const result = await dispatchMenuAction(item.key);
|
|
||||||
if (result !== 0) return result;
|
if (result !== 0) return result;
|
||||||
// Return to menu
|
|
||||||
hideCursor();
|
hideCursor();
|
||||||
if (wasRaw !== true) process.stdin.setRawMode(true);
|
if (wasRaw !== true) process.stdin.setRawMode(true);
|
||||||
process.stdin.resume();
|
process.stdin.resume();
|
||||||
@@ -193,12 +214,7 @@ async function showMenu(): Promise<number> {
|
|||||||
if (idx < MENU_ITEMS.length) {
|
if (idx < MENU_ITEMS.length) {
|
||||||
cursor = idx;
|
cursor = idx;
|
||||||
renderMenu(banner, cursor);
|
renderMenu(banner, cursor);
|
||||||
const item = MENU_ITEMS[idx]!;
|
const result = await dispatchAndWait(MENU_ITEMS[idx]!, wasRaw);
|
||||||
showCursor();
|
|
||||||
process.stdin.setRawMode(wasRaw === true);
|
|
||||||
process.stdin.pause();
|
|
||||||
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
|
|
||||||
const result = await dispatchMenuAction(item.key);
|
|
||||||
if (result !== 0) return result;
|
if (result !== 0) return result;
|
||||||
hideCursor();
|
hideCursor();
|
||||||
if (wasRaw !== true) process.stdin.setRawMode(true);
|
if (wasRaw !== true) process.stdin.setRawMode(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user