feat: Implement delayed Ctrl+C exit prompt
This change introduces a small delay after the first Ctrl+C press, prompting the user to press Ctrl+C again to exit. This helps prevent accidental termination of the application. - Added `exitOnCtrlC={false}` to the Ink render options in `gemini.tsx` to enable custom Ctrl+C handling. - Implemented logic in `App.tsx` to: - Display "Press Ctrl+C again to exit." for 2 seconds after the first Ctrl+C. - Exit the application if Ctrl+C is pressed again during this period. - Revert to normal operation if the second Ctrl+C is not pressed within the timeout. - Defined a constant `CTRL_C_PROMPT_DURATION_MS` for the timeout duration.
This commit is contained in:
parent
7012c86336
commit
1468047081
|
@ -78,6 +78,7 @@ async function main() {
|
||||||
startupWarnings={startupWarnings}
|
startupWarnings={startupWarnings}
|
||||||
/>
|
/>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
|
{ exitOnCtrlC: false },
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ import { useLogger } from './hooks/useLogger.js';
|
||||||
import { StreamingContext } from './contexts/StreamingContext.js';
|
import { StreamingContext } from './contexts/StreamingContext.js';
|
||||||
import { useGitBranchName } from './hooks/useGitBranchName.js';
|
import { useGitBranchName } from './hooks/useGitBranchName.js';
|
||||||
|
|
||||||
|
const CTRL_C_PROMPT_DURATION_MS = 1000;
|
||||||
|
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
config: Config;
|
config: Config;
|
||||||
settings: LoadedSettings;
|
settings: LoadedSettings;
|
||||||
|
@ -77,18 +79,43 @@ export const App = ({
|
||||||
const [corgiMode, setCorgiMode] = useState(false);
|
const [corgiMode, setCorgiMode] = useState(false);
|
||||||
const [shellModeActive, setShellModeActive] = useState(false);
|
const [shellModeActive, setShellModeActive] = useState(false);
|
||||||
const [showErrorDetails, setShowErrorDetails] = useState<boolean>(false);
|
const [showErrorDetails, setShowErrorDetails] = useState<boolean>(false);
|
||||||
|
const [ctrlCPressedOnce, setCtrlCPressedOnce] = useState(false);
|
||||||
|
const ctrlCTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
|
|
||||||
const errorCount = useMemo(
|
const errorCount = useMemo(
|
||||||
() => consoleMessages.filter((msg) => msg.type === 'error').length,
|
() => consoleMessages.filter((msg) => msg.type === 'error').length,
|
||||||
[consoleMessages],
|
[consoleMessages],
|
||||||
);
|
);
|
||||||
|
|
||||||
useInput((input: string, key: InkKeyType) => {
|
useInput((input: string, key: InkKeyType) => {
|
||||||
if (key.ctrl && input === 'o') {
|
if (key.ctrl && input === 'o') {
|
||||||
setShowErrorDetails((prev) => !prev);
|
setShowErrorDetails((prev) => !prev);
|
||||||
refreshStatic();
|
refreshStatic();
|
||||||
|
} else if (key.ctrl && (input === 'c' || input === 'C')) {
|
||||||
|
if (ctrlCPressedOnce) {
|
||||||
|
if (ctrlCTimerRef.current) {
|
||||||
|
clearTimeout(ctrlCTimerRef.current);
|
||||||
|
}
|
||||||
|
process.exit(0);
|
||||||
|
} else {
|
||||||
|
setCtrlCPressedOnce(true);
|
||||||
|
ctrlCTimerRef.current = setTimeout(() => {
|
||||||
|
setCtrlCPressedOnce(false);
|
||||||
|
ctrlCTimerRef.current = null;
|
||||||
|
}, CTRL_C_PROMPT_DURATION_MS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
if (ctrlCTimerRef.current) {
|
||||||
|
clearTimeout(ctrlCTimerRef.current);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
useConsolePatcher({
|
useConsolePatcher({
|
||||||
onNewMessage: handleNewMessage,
|
onNewMessage: handleNewMessage,
|
||||||
debugMode: config.getDebugMode(),
|
debugMode: config.getDebugMode(),
|
||||||
|
@ -365,11 +392,17 @@ export const App = ({
|
||||||
{process.env.GEMINI_SYSTEM_MD && (
|
{process.env.GEMINI_SYSTEM_MD && (
|
||||||
<Text color={Colors.AccentRed}>|⌐■_■| </Text>
|
<Text color={Colors.AccentRed}>|⌐■_■| </Text>
|
||||||
)}
|
)}
|
||||||
{geminiMdFileCount > 0 && (
|
{ctrlCPressedOnce ? (
|
||||||
|
<Text color={Colors.AccentYellow}>
|
||||||
|
Press Ctrl+C again to exit.
|
||||||
|
</Text>
|
||||||
|
) : geminiMdFileCount > 0 ? (
|
||||||
<Text color={Colors.SubtleComment}>
|
<Text color={Colors.SubtleComment}>
|
||||||
Using {geminiMdFileCount} GEMINI.md file
|
Using {geminiMdFileCount} GEMINI.md file
|
||||||
{geminiMdFileCount > 1 ? 's' : ''}
|
{geminiMdFileCount > 1 ? 's' : ''}
|
||||||
</Text>
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Text> </Text> // Render an empty space to reserve height
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
|
|
Loading…
Reference in New Issue