diff --git a/packages/@ant/ink/src/core/__tests__/raw-mode-support.test.ts b/packages/@ant/ink/src/core/__tests__/raw-mode-support.test.ts index d143573fa..c65e71ded 100644 --- a/packages/@ant/ink/src/core/__tests__/raw-mode-support.test.ts +++ b/packages/@ant/ink/src/core/__tests__/raw-mode-support.test.ts @@ -18,11 +18,29 @@ describe('isWindowsRawModeUnsafe', () => { ).toBe(false); }); + test('does not disable raw mode for Git Bash terminals', () => { + expect( + isWindowsRawModeUnsafe({ + MSYSTEM: 'MINGW64', + TERM_PROGRAM: 'mintty', + SHELL: '/usr/bin/bash', + }, 'win32'), + ).toBe(false); + expect( + isWindowsRawModeUnsafe({ + MSYSTEM: 'MINGW32', + TERM: 'xterm-256color', + }, 'win32'), + ).toBe(false); + }); + test('disables raw mode for MSYS2 and Cygwin terminals', () => { expect(isWindowsRawModeUnsafe({ MSYSTEM: 'UCRT64' }, 'win32')).toBe(true); + expect(isWindowsRawModeUnsafe({ MSYSTEM: 'CLANG64' }, 'win32')).toBe(true); + expect(isWindowsRawModeUnsafe({ MSYSTEM: 'MSYS' }, 'win32')).toBe(true); expect(isWindowsRawModeUnsafe({ TERM: 'cygwin' }, 'win32')).toBe(true); expect(isWindowsRawModeUnsafe({ TERM_PROGRAM: 'mintty' }, 'win32')).toBe( - true, + false, ); expect(isWindowsRawModeUnsafe({ SHELL: '/usr/bin/bash' }, 'win32')).toBe( false, diff --git a/packages/@ant/ink/src/core/raw-mode-support.ts b/packages/@ant/ink/src/core/raw-mode-support.ts index 054b8dfca..91e390567 100644 --- a/packages/@ant/ink/src/core/raw-mode-support.ts +++ b/packages/@ant/ink/src/core/raw-mode-support.ts @@ -15,18 +15,27 @@ export function isWindowsRawModeUnsafe( } const term = env.TERM?.toLowerCase() ?? ''; - const termProgram = env.TERM_PROGRAM?.toLowerCase() ?? ''; const msystem = env.MSYSTEM?.toLowerCase() ?? ''; const shell = env.SHELL?.toLowerCase() ?? ''; + // Git for Windows reports MSYSTEM=MINGW64/MINGW32 and often runs under + // mintty, but it needs raw mode for Ink key parsing. Disabling raw mode + // there makes Enter, arrows, and slash commands behave like cooked shell + // input. Keep the startup-crash workaround scoped to MSYS2/Cygwin-like + // environments and leave Git Bash on the normal raw-mode path. + const isGitForWindowsMingw = + msystem === 'mingw64' || msystem === 'mingw32'; + if (isGitForWindowsMingw) { + return false; + } + return ( term === 'cygwin' || - term.includes('mintty') || - termProgram.includes('mintty') || - msystem.length > 0 || + msystem === 'msys' || + msystem.startsWith('ucrt') || + msystem.startsWith('clang') || shell.includes('msys') || - shell.includes('cygwin') || - shell.includes('mingw') + shell.includes('cygwin') ); } diff --git a/src/utils/earlyInput.ts b/src/utils/earlyInput.ts index 2c535c416..08a988c94 100644 --- a/src/utils/earlyInput.ts +++ b/src/utils/earlyInput.ts @@ -31,18 +31,20 @@ function supportsEarlyInputRawMode(): boolean { } const term = process.env.TERM?.toLowerCase() ?? '' - const termProgram = process.env.TERM_PROGRAM?.toLowerCase() ?? '' const msystem = process.env.MSYSTEM?.toLowerCase() ?? '' const shell = process.env.SHELL?.toLowerCase() ?? '' + if (msystem === 'mingw64' || msystem === 'mingw32') { + return true + } + return !( term === 'cygwin' || - term.includes('mintty') || - termProgram.includes('mintty') || - msystem.length > 0 || + msystem === 'msys' || + msystem.startsWith('ucrt') || + msystem.startsWith('clang') || shell.includes('msys') || - shell.includes('cygwin') || - shell.includes('mingw') + shell.includes('cygwin') ) }