fix(ui): skip "Press Enter" pause when user backs out of subcommand
Build / bun-build (push) Successful in 5m42s
Build / bun-build (push) Successful in 5m42s
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()}`);
|
||||
|
||||
@@ -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()}`);
|
||||
|
||||
@@ -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
@@ -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`);
|
||||
|
||||
@@ -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()}`);
|
||||
|
||||
@@ -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()}`);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user