fix(ui): skip "Press Enter" pause when user backs out of subcommand
Build / bun-build (push) Successful in 5m42s

This commit is contained in:
2026-06-16 14:49:00 +08:00
parent f2c53dce65
commit d01d6a38b5
8 changed files with 21 additions and 12 deletions
+4
View File
@@ -15,6 +15,7 @@ import { setColorEnabled } from "./src/terminal";
import { BOLD, GREEN, CYAN, DIM, RESET } from "./src/terminal";
import { isStdinTTY, initTTY } from "./src/tty";
import { showBanner } from "./src/brand";
import { SKIP_WAIT } from "./src/menu";
// ── Interactive Menu (mole-style) ─────────────────────────────────────
@@ -153,6 +154,9 @@ async function dispatchAndWait(item: MenuItem, wasRaw: boolean): Promise<number>
process.stdin.pause();
process.stdout.write("\x1b[2J\x1b[H"); // clear screen
const result = await dispatchMenuAction(item.key);
if (result === (SKIP_WAIT as unknown as number)) {
return 0; // user explicitly backed out — skip "Press Enter" and return directly
}
await waitForEnter();
return result;
}
+2 -2
View File
@@ -10,7 +10,7 @@ import {
commit,
} from "../git";
import { selectFiles } from "../selector";
import { BACK } from "../menu";
import { BACK, SKIP_WAIT } from "../menu";
import { collectProjectContext } from "../context";
import { buildPrompt, SYSTEM_PROMPT } from "../prompt";
import { generateCommitMessage } from "../ai";
@@ -221,7 +221,7 @@ export async function handleCommit(args: ParsedArgs): Promise<number> {
console.log(` ${GREEN()}Auto-staged ${unstagedFiles.length} file(s).${RESET()}`);
} else {
const selected = await selectFiles(stagedFiles, unstagedFiles);
if (selected === BACK) return 0;
if (selected === BACK) return SKIP_WAIT as unknown as number;
if (selected.length > 0) {
await stageFiles(selected);
console.log(` ${GREEN()}Staged ${selected.length} file(s).${RESET()}`);
+2 -1
View File
@@ -1,6 +1,7 @@
import { loadConfig, saveConfig } from "../config";
import { BOLD, GREEN, YELLOW, CYAN, RED, DIM, RESET } from "../terminal";
import { isStdinTTY } from "../tty";
import { SKIP_WAIT } from "../menu";
import type { Config } from "../types";
import type { ParsedArgs } from "../cli";
@@ -323,7 +324,7 @@ export async function handleConfig(args: ParsedArgs): Promise<number> {
// gai config (no args) → interactive
if (positional.length === 0) {
const result = await interactiveConfig();
return result === "back" ? 0 : 0;
return result === "back" ? (SKIP_WAIT as unknown as number) : 0;
}
console.error(`\n ${RED()}Error: Unknown config subcommand: ${positional[0]}${RESET()}`);
+2 -2
View File
@@ -1,7 +1,7 @@
import { loadConfig } from "../config";
import { isGitRepo, getStagedDiff, getUnstagedFiles, getRepoRoot, stageFiles } from "../git";
import { selectFiles } from "../selector";
import { BACK } from "../menu";
import { BACK, SKIP_WAIT } from "../menu";
import { collectProjectContext } from "../context";
import { EXPLAIN_SYSTEM_PROMPT, buildExplainPrompt } from "../prompt";
import { callAI } from "../ai";
@@ -52,7 +52,7 @@ export async function handleExplain(args: ParsedArgs): Promise<number> {
const unstagedFiles = await getUnstagedFiles();
if (unstagedFiles.length > 0) {
const selected = await selectFiles([], unstagedFiles);
if (selected === BACK) return 0;
if (selected === BACK) return SKIP_WAIT as unknown as number;
if (selected.length > 0) {
await stageFiles(selected);
console.log(` ${GREEN()}Staged ${selected.length} file(s).${RESET()}`);
+3 -3
View File
@@ -4,7 +4,7 @@ import { isGitRepo, getRepoRoot } from "../git";
import { collectProjectContext } from "../context";
import { PR_SYSTEM_PROMPT, buildPRPrompt } from "../prompt";
import { generatePRMessage } from "../ai";
import { BACK, selectOne } from "../menu";
import { BACK, SKIP_WAIT, selectOne } from "../menu";
import {
getDefaultBranch,
getBranchName,
@@ -68,7 +68,7 @@ export async function handlePR(args: ParsedArgs): Promise<number> {
if (!platform) {
const hostname = (await getRemoteHostname()) || "unknown";
const chosen = await selectPlatform(hostname);
if (chosen === BACK) return 0;
if (chosen === BACK) return SKIP_WAIT as unknown as number;
if (!chosen) {
console.log(" Aborted.");
return 0;
@@ -98,7 +98,7 @@ export async function handlePR(args: ParsedArgs): Promise<number> {
items: [{ label: "Back", value: "back" as const }],
});
if (choice === null) process.exit(0);
return 0;
return SKIP_WAIT as unknown as number;
}
console.log(` ${commits.length} commit${commits.length > 1 ? "s" : ""} on this branch`);
+2 -2
View File
@@ -1,7 +1,7 @@
import { loadConfig } from "../config";
import { isGitRepo, getStagedDiff, getUnstagedFiles, getRepoRoot, stageFiles } from "../git";
import { selectFiles } from "../selector";
import { BACK } from "../menu";
import { BACK, SKIP_WAIT } from "../menu";
import { collectProjectContext } from "../context";
import { REVIEW_SYSTEM_PROMPT, buildReviewPrompt } from "../prompt";
import { callAI } from "../ai";
@@ -61,7 +61,7 @@ export async function handleReview(args: ParsedArgs): Promise<number> {
const unstagedFiles = await getUnstagedFiles();
if (unstagedFiles.length > 0) {
const selected = await selectFiles([], unstagedFiles);
if (selected === BACK) return 0;
if (selected === BACK) return SKIP_WAIT as unknown as number;
if (selected.length > 0) {
await stageFiles(selected);
console.log(` ${GREEN()}Staged ${selected.length} file(s).${RESET()}`);
+2 -2
View File
@@ -1,7 +1,7 @@
import { loadConfig } from "../config";
import { isGitRepo, getStagedDiff, getUnstagedFiles, stageFiles } from "../git";
import { selectFiles } from "../selector";
import { BACK } from "../menu";
import { BACK, SKIP_WAIT } from "../menu";
import {
SUGGEST_SYSTEM_PROMPT,
buildSuggestBranchPrompt,
@@ -58,7 +58,7 @@ export async function handleSuggest(args: ParsedArgs): Promise<number> {
const unstagedFiles = await getUnstagedFiles();
if (unstagedFiles.length > 0) {
const selected = await selectFiles([], unstagedFiles);
if (selected === BACK) return 0;
if (selected === BACK) return SKIP_WAIT as unknown as number;
if (selected.length > 0) {
await stageFiles(selected);
console.log(` ${GREEN()}Staged ${selected.length} file(s).${RESET()}`);
+4
View File
@@ -15,6 +15,10 @@ const BACKSPACE = "\x7f";
export const BACK = Symbol("prompt-back");
export type PromptBack = typeof BACK;
// Sent by command handlers to skip the "Press Enter to return" wait in the
// interactive menu when the user explicitly backed out of a sub-menu.
export const SKIP_WAIT = Symbol("skip-wait");
export interface Choice<T> {
label: string;
value: T;